forked from External/mage
GUI, table: added drafts with single multiplayer and multiple 1vs1 games support (#13701)
- new tourney's single game mode allow to play tourneys/drafts with all players in one game without multiple rounds; - it's allow to setup classic drafts with 1 vs 1 games and multiple rounds - added AI opponents supported including draft bots from a public servers;
This commit is contained in:
parent
a61851db09
commit
f2826cc676
22 changed files with 247 additions and 256 deletions
|
|
@ -11,7 +11,7 @@ import mage.game.match.MatchOptions;
|
|||
public class FakeMatch extends MatchImpl {
|
||||
|
||||
public FakeMatch() {
|
||||
super(new MatchOptions("fake match", "fake game type", true, 2));
|
||||
super(new MatchOptions("fake match", "fake game type", false));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -31,8 +31,7 @@ public class MatchOptions implements Serializable {
|
|||
protected String deckType;
|
||||
protected boolean limited;
|
||||
protected List<PlayerType> playerTypes = new ArrayList<>();
|
||||
protected boolean multiPlayer;
|
||||
protected int numSeats;
|
||||
protected boolean multiPlayer; // allow to play single game with all tourney's players
|
||||
protected String password;
|
||||
protected SkillLevel skillLevel = SkillLevel.CASUAL;
|
||||
protected boolean rollbackTurnsAllowed;
|
||||
|
|
@ -51,27 +50,14 @@ public class MatchOptions implements Serializable {
|
|||
protected Collection<DeckCardInfo> perPlayerEmblemCards = Collections.emptySet();
|
||||
protected Collection<DeckCardInfo> globalEmblemCards = Collections.emptySet();
|
||||
|
||||
public MatchOptions(String name, String gameType, boolean multiPlayer, int numSeats) {
|
||||
public MatchOptions(String name, String gameType, boolean multiPlayer) {
|
||||
this.name = name;
|
||||
this.gameType = gameType;
|
||||
this.password = "";
|
||||
this.multiPlayer = multiPlayer;
|
||||
this.numSeats = numSeats;
|
||||
}
|
||||
|
||||
public void setNumSeats(int numSeats) {
|
||||
this.numSeats = numSeats;
|
||||
}
|
||||
|
||||
public int getNumSeats() {
|
||||
return numSeats;
|
||||
}
|
||||
|
||||
public void setMultiPlayer(boolean multiPlayer) {
|
||||
this.multiPlayer = multiPlayer;
|
||||
}
|
||||
|
||||
public boolean getMultiPlayer() {
|
||||
public boolean isSingleGameTourney() {
|
||||
return multiPlayer;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,28 +15,19 @@ public class MultiplayerRound {
|
|||
|
||||
private final int roundNum;
|
||||
private final Tournament tournament;
|
||||
private final int numSeats;
|
||||
private final List<TournamentPlayer> allPlayers = new ArrayList<>();
|
||||
private Match match;
|
||||
private UUID tableId;
|
||||
|
||||
|
||||
public MultiplayerRound(int roundNum, Tournament tournament, int numSeats) {
|
||||
public MultiplayerRound(int roundNum, Tournament tournament) {
|
||||
this.roundNum = roundNum;
|
||||
this.tournament = tournament;
|
||||
this.numSeats = numSeats;
|
||||
}
|
||||
|
||||
public List<TournamentPlayer> getAllPlayers () {
|
||||
return allPlayers;
|
||||
}
|
||||
|
||||
public TournamentPlayer getPlayer (int i) {
|
||||
if (i >= 0 && i < numSeats && i < allPlayers.size()) {
|
||||
return allPlayers.get(i);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void addPairing(TournamentPairing match) {
|
||||
this.allPlayers.add(match.getPlayer1());
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
|||
*/
|
||||
public abstract class TournamentImpl implements Tournament {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(TournamentImpl.class);
|
||||
|
||||
protected UUID id = UUID.randomUUID();
|
||||
protected UUID tableId = null; // assign on table create
|
||||
protected List<Round> rounds = new CopyOnWriteArrayList<>();
|
||||
|
|
@ -223,9 +225,11 @@ public abstract class TournamentImpl implements Tournament {
|
|||
}
|
||||
|
||||
protected void playMultiplayerRound(MultiplayerRound round) {
|
||||
// it's a single game, so tourney will be ends immediately
|
||||
// and will keep one game active for better performance
|
||||
// and less max tourney restrictions on the server
|
||||
updateResults();
|
||||
playMultiPlayerMatch(round);
|
||||
|
||||
updateResults(); // show points from byes
|
||||
}
|
||||
|
||||
protected List<TournamentPlayer> getActivePlayers() {
|
||||
|
|
@ -248,6 +252,8 @@ public abstract class TournamentImpl implements Tournament {
|
|||
player.setPoints(0);
|
||||
player.setStateInfo("");
|
||||
}
|
||||
|
||||
// multiple games tourney
|
||||
for (Round round : rounds) {
|
||||
for (TournamentPairing pair : round.getPairs()) {
|
||||
Match match = pair.getMatch();
|
||||
|
|
@ -256,8 +262,10 @@ public abstract class TournamentImpl implements Tournament {
|
|||
TournamentPlayer tp2 = pair.getPlayer2();
|
||||
MatchPlayer mp1 = match.getPlayer(pair.getPlayer1().getPlayer().getId());
|
||||
MatchPlayer mp2 = match.getPlayer(pair.getPlayer2().getPlayer().getId());
|
||||
|
||||
// set player state if they finished the round
|
||||
if (round.getRoundNumber() == rounds.size()) { // for elimination getRoundNumber = 0 so never true here
|
||||
// for elimination getRoundNumber = 0 so never true here
|
||||
if (round.getRoundNumber() == rounds.size()) {
|
||||
match.setTournamentRound(round.getRoundNumber());
|
||||
if (tp1.getState() == TournamentPlayerState.DUELING) {
|
||||
if (round.getRoundNumber() == getNumberRounds()) {
|
||||
|
|
@ -274,6 +282,7 @@ public abstract class TournamentImpl implements Tournament {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add round result
|
||||
tp1.setResults(addRoundResult(round.getRoundNumber(), pair, tp1, tp2));
|
||||
tp2.setResults(addRoundResult(round.getRoundNumber(), pair, tp2, tp1));
|
||||
|
|
|
|||
|
|
@ -26,9 +26,9 @@ public class TournamentOptions implements Serializable {
|
|||
protected int quitRatio;
|
||||
protected int minimumRating;
|
||||
|
||||
public TournamentOptions(String name, String matchType, int numSeats) {
|
||||
public TournamentOptions(String name, String matchType, boolean isSingleMultiplayerGame) {
|
||||
this.name = name;
|
||||
this.matchOptions = new MatchOptions("", matchType, numSeats > 2, numSeats);
|
||||
this.matchOptions = new MatchOptions("", matchType, isSingleMultiplayerGame);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ package mage.game.tournament;
|
|||
*/
|
||||
public class TournamentSealedOptions extends TournamentOptions {
|
||||
|
||||
public TournamentSealedOptions(String name, String matchType, int numSeats) {
|
||||
super(name, matchType, numSeats);
|
||||
public TournamentSealedOptions(String name, String matchType, boolean isSingleMultiplayerGame) {
|
||||
super(name, matchType, isSingleMultiplayerGame);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
package mage.game.tournament;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import mage.constants.MultiplayerAttackOption;
|
||||
import mage.game.events.TableEvent;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public abstract class TournamentSingleElimination extends TournamentImpl {
|
||||
|
|
@ -19,38 +19,39 @@ public abstract class TournamentSingleElimination extends TournamentImpl {
|
|||
|
||||
@Override
|
||||
protected void runTournament() {
|
||||
for (Map.Entry<UUID, TournamentPlayer> entry: players.entrySet()) {
|
||||
for (Map.Entry<UUID, TournamentPlayer> entry : players.entrySet()) {
|
||||
if (entry.getValue().getPlayer().autoLoseGame()) {
|
||||
entry.getValue().setEliminated();
|
||||
entry.getValue().setResults("Auto Eliminated");
|
||||
}
|
||||
}
|
||||
if (options.matchOptions.getNumSeats() == 2) {
|
||||
}
|
||||
if (options.matchOptions.isSingleGameTourney()) {
|
||||
// one game with all players
|
||||
options.matchOptions.setAttackOption(MultiplayerAttackOption.MULTIPLE);
|
||||
MultiplayerRound round = new MultiplayerRound(0, this);
|
||||
for (TournamentPlayer player : getActivePlayers()) {
|
||||
round.addPlayer(player);
|
||||
}
|
||||
playMultiplayerRound(round);
|
||||
} else {
|
||||
// split to multiple rounds/games
|
||||
while (this.getActivePlayers().size() > 1) {
|
||||
// check if some player got killed / disconnected meanwhile and update their state
|
||||
tableEventSource.fireTableEvent(TableEvent.EventType.CHECK_STATE_PLAYERS);
|
||||
Round round = createRoundRandom();
|
||||
playRound(round);
|
||||
eliminatePlayers(round);
|
||||
}
|
||||
} else {
|
||||
options.matchOptions.setAttackOption(MultiplayerAttackOption.MULTIPLE);
|
||||
MultiplayerRound round = new MultiplayerRound(0, this, options.matchOptions.getNumSeats());
|
||||
for (TournamentPlayer player : getActivePlayers()) {
|
||||
round.addPlayer(player);
|
||||
}
|
||||
playMultiplayerRound(round);
|
||||
}
|
||||
|
||||
|
||||
nextStep();
|
||||
}
|
||||
|
||||
|
||||
private void eliminatePlayers(Round round) {
|
||||
for (TournamentPairing pair: round.getPairs()) {
|
||||
for (TournamentPairing pair : round.getPairs()) {
|
||||
pair.eliminatePlayers();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,18 @@
|
|||
|
||||
package mage.game.tournament;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.UUID;
|
||||
import mage.constants.MultiplayerAttackOption;
|
||||
|
||||
import mage.constants.TournamentPlayerState;
|
||||
import mage.game.events.TableEvent;
|
||||
import mage.game.tournament.pairing.RoundPairings;
|
||||
import mage.game.tournament.pairing.SwissPairingMinimalWeightMatching;
|
||||
import mage.game.tournament.pairing.SwissPairingSimple;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public abstract class TournamentSwiss extends TournamentImpl {
|
||||
|
|
@ -31,82 +30,65 @@ public abstract class TournamentSwiss extends TournamentImpl {
|
|||
}
|
||||
}
|
||||
|
||||
if (options.matchOptions.getNumSeats() == 2) {
|
||||
if (options.matchOptions.isSingleGameTourney()) {
|
||||
// one game with all players (it's same as normal tourney's mode)
|
||||
options.matchOptions.setAttackOption(MultiplayerAttackOption.MULTIPLE);
|
||||
MultiplayerRound round = new MultiplayerRound(0, this);
|
||||
for (TournamentPlayer player : getActivePlayers()) {
|
||||
round.addPlayer(player);
|
||||
}
|
||||
playMultiplayerRound(round);
|
||||
} else {
|
||||
// split to multiple rounds/games
|
||||
while (this.getActivePlayers().size() > 1 && this.getNumberRounds() > this.getRounds().size()) {
|
||||
// check if some player got killed / disconnected meanwhile and update their state
|
||||
tableEventSource.fireTableEvent(TableEvent.EventType.CHECK_STATE_PLAYERS);
|
||||
// Swiss pairing
|
||||
Round round = createRoundSwiss();
|
||||
playRound(round);
|
||||
}
|
||||
} else {
|
||||
options.matchOptions.setAttackOption(MultiplayerAttackOption.MULTIPLE);
|
||||
MultiplayerRound round = createMultiplayerRound();
|
||||
playMultiplayerRound(round);
|
||||
}
|
||||
|
||||
|
||||
nextStep();
|
||||
}
|
||||
|
||||
protected Round createRoundSwiss() {
|
||||
// multiple rounds, can be called multiple times per tourney
|
||||
|
||||
List<TournamentPlayer> roundPlayers = getActivePlayers();
|
||||
boolean isLastRound = (rounds.size() + 1 == getNumberRounds());
|
||||
if (options.matchOptions.isSingleGameTourney()) {
|
||||
throw new IllegalStateException("Wrong code usage: multi rounds for non single game tourneys only (e.g. with two seats)");
|
||||
}
|
||||
|
||||
Round round = null;
|
||||
if (options.matchOptions.getNumSeats() == 2) {
|
||||
RoundPairings roundPairings;
|
||||
if (roundPlayers.size() <= 16) {
|
||||
SwissPairingMinimalWeightMatching swissPairing = new SwissPairingMinimalWeightMatching(roundPlayers, rounds, isLastRound);
|
||||
roundPairings = swissPairing.getRoundPairings();
|
||||
} else {
|
||||
SwissPairingSimple swissPairing = new SwissPairingSimple(roundPlayers, rounds);
|
||||
roundPairings = swissPairing.getRoundPairings();
|
||||
}
|
||||
|
||||
round = new Round(rounds.size() + 1, this);
|
||||
rounds.add(round);
|
||||
for (TournamentPairing pairing : roundPairings.getPairings()) {
|
||||
round.addPairing(pairing);
|
||||
}
|
||||
for (TournamentPlayer playerBye : roundPairings.getPlayerByes()) {
|
||||
// player free round - add to bye players of this round
|
||||
round.getPlayerByes().add(playerBye);
|
||||
if (isLastRound) {
|
||||
playerBye.setState(TournamentPlayerState.FINISHED);
|
||||
} else {
|
||||
playerBye.setState(TournamentPlayerState.WAITING);
|
||||
}
|
||||
playerBye.setStateInfo("Round Bye");
|
||||
updateResults();
|
||||
RoundPairings roundPairings;
|
||||
if (roundPlayers.size() <= 16) {
|
||||
SwissPairingMinimalWeightMatching swissPairing = new SwissPairingMinimalWeightMatching(roundPlayers, rounds, isLastRound);
|
||||
roundPairings = swissPairing.getRoundPairings();
|
||||
} else {
|
||||
SwissPairingSimple swissPairing = new SwissPairingSimple(roundPlayers, rounds);
|
||||
roundPairings = swissPairing.getRoundPairings();
|
||||
}
|
||||
|
||||
round = new Round(rounds.size() + 1, this);
|
||||
rounds.add(round);
|
||||
for (TournamentPairing pairing : roundPairings.getPairings()) {
|
||||
round.addPairing(pairing);
|
||||
}
|
||||
|
||||
for (TournamentPlayer playerBye : roundPairings.getPlayerByes()) {
|
||||
// player free round - add to bye players of this round
|
||||
round.getPlayerByes().add(playerBye);
|
||||
if (isLastRound) {
|
||||
playerBye.setState(TournamentPlayerState.FINISHED);
|
||||
} else {
|
||||
playerBye.setState(TournamentPlayerState.WAITING);
|
||||
}
|
||||
playerBye.setStateInfo("Round Bye");
|
||||
updateResults();
|
||||
}
|
||||
|
||||
return round;
|
||||
}
|
||||
|
||||
public MultiplayerRound createMultiplayerRound() {
|
||||
List<TournamentPlayer> roundPlayers = getActivePlayers();
|
||||
boolean isLastRound = (rounds.size() + 1 == getNumberRounds());
|
||||
|
||||
MultiplayerRound round = null;
|
||||
if (options.matchOptions.getNumSeats() > 2) {
|
||||
options.matchOptions.setAttackOption(MultiplayerAttackOption.MULTIPLE);
|
||||
RoundPairings roundPairings;
|
||||
if (roundPlayers.size() <= 16) {
|
||||
SwissPairingMinimalWeightMatching swissPairing = new SwissPairingMinimalWeightMatching(roundPlayers, rounds, isLastRound);
|
||||
roundPairings = swissPairing.getRoundPairings();
|
||||
} else {
|
||||
SwissPairingSimple swissPairing = new SwissPairingSimple(roundPlayers, rounds);
|
||||
roundPairings = swissPairing.getRoundPairings();
|
||||
}
|
||||
|
||||
round = new MultiplayerRound(rounds.size() + 1, this, options.matchOptions.getNumSeats());
|
||||
for (TournamentPairing pairing : roundPairings.getPairings()) {
|
||||
round.addPairing(pairing);
|
||||
}
|
||||
|
||||
}
|
||||
return round;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue