- Adding Tournaments to Simulater

This commit is contained in:
Sol
2016-04-17 16:32:20 +00:00
parent 271998b422
commit 1c0ebbae4c
9 changed files with 328 additions and 45 deletions

View File

@@ -5,8 +5,10 @@ import forge.GuiBase;
import forge.deck.Deck;
import forge.deck.DeckGroup;
import forge.deck.DeckSection;
import forge.game.Game;
import forge.game.GameRules;
import forge.game.GameType;
import forge.game.Match;
import forge.game.player.RegisteredPlayer;
import forge.interfaces.IGuiGame;
import forge.match.HostedMatch;
@@ -24,6 +26,7 @@ import java.util.List;
public class QuestDraftUtils {
private static final List<DraftMatchup> matchups = new ArrayList<>();
public static boolean TOURNAMENT_TOGGLE = false;
public static boolean AI_BACKGROUND = false;
public static boolean matchInProgress = false;
private static boolean waitForUserInput = false;
@@ -304,9 +307,9 @@ public class QuestDraftUtils {
final DeckGroup decks = FModel.getQuest().getAssets().getDraftDeckStorage().get(QuestEventDraft.DECK_NAME);
boolean waitForUserInput = pairing.hasPlayer(GamePlayerUtil.getGuiPlayer());
GameRules rules = createQuestDraftRuleset();
final GameRules rules = createQuestDraftRuleset();
List<RegisteredPlayer> registered = registerTournamentPlayers(pairing, draft, decks);
final List<RegisteredPlayer> registered = TournamentBracket.registerTournamentPlayers(pairing, decks);
RegisteredPlayer registeredHuman = null;
if (waitForUserInput) {
@@ -320,8 +323,37 @@ public class QuestDraftUtils {
} else {
// TODO Show a "Simulating Dialog" and simulate off-thread. Temporary replication of code for now
gui.disableOverlay();
final HostedMatch newMatch = GuiBase.getInterface().hostMatch();
newMatch.startMatch(rules, null, registered, registeredHuman, GuiBase.getInterface().getNewGuiGame());
if (AI_BACKGROUND) {
System.out.println("Spawning a thread to simulate the match");
// Show Dialog popup
/*
FThreads.invokeInBackgroundThread(new Runnable() {
@Override
public void run() {
Match mc = new Match(rules, registered, "Simulated Match");
Game gm = mc.createGame();
mc.startGame(gm);
}
});*/
Match mc = new Match(rules, registered, "Simulated Match");
String winner = null;
while (!mc.isMatchOver()) {
Game gm = mc.createGame();
mc.startGame(gm);
// Update dialog with winner
}
RegisteredPlayer regPlayer = mc.getWinner();
//draft.setWinner(regPlayer.getPlayer().getName());
//FModel.getQuest().save();
gui.finishGame();
} else {
final HostedMatch newMatch = GuiBase.getInterface().hostMatch();
newMatch.startMatch(rules, null, registered, registeredHuman, GuiBase.getInterface().getNewGuiGame());
}
}
}

View File

@@ -1,14 +1,18 @@
package forge.tournament.system;
import com.google.common.collect.Lists;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import forge.LobbyPlayer;
import forge.deck.DeckGroup;
import forge.game.player.RegisteredPlayer;
import forge.player.GamePlayerUtil;
import forge.util.MyRandom;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
@SuppressWarnings("serial")
@@ -52,6 +56,8 @@ public abstract class AbstractTournament implements Serializable {
return activePairings.get(0);
}
public int getActiveRound() { return activeRound; }
public boolean isContinualPairing() { return continualPairing; }
public void setContinualPairing(boolean continualPairing) { this.continualPairing = continualPairing; }
@@ -74,7 +80,7 @@ public abstract class AbstractTournament implements Serializable {
}
abstract public void generateActivePairings();
abstract public void reportMatchCompletion(TournamentPairing pairing);
abstract public boolean reportMatchCompletion(TournamentPairing pairing);
abstract public boolean completeRound();
public void finishMatch(TournamentPairing pairing) {
@@ -88,6 +94,32 @@ public abstract class AbstractTournament implements Serializable {
return (initialized && activeRound == totalRounds && activePairings.isEmpty());
}
public void outputTournamentResults() {
Collections.sort(allPlayers, new Comparator<TournamentPlayer>() {
@Override
public int compare(TournamentPlayer o1, TournamentPlayer o2) {
return o2.getWins()*3 + o2.getTies() - o1.getWins()*3 + o1.getTies();
}
});
System.out.println("Name\t\tWins\tLosses\tTies");
for(TournamentPlayer tp : allPlayers) {
System.out.println(String.format("%s\t\t%d\t%d\t%d", tp.getPlayer().getName(), tp.getWins(),
tp.getLosses(), tp.getTies()));
}
}
public static List<RegisteredPlayer> registerTournamentPlayers(TournamentPairing pairing, DeckGroup decks) {
List<RegisteredPlayer> registered = Lists.newArrayList();
for (TournamentPlayer pl : pairing.getPairedPlayers()) {
if (pl.getIndex() == -1) {
registered.add(new RegisteredPlayer(decks.getHumanDeck()).setPlayer(pl.getPlayer()));
} else {
registered.add(new RegisteredPlayer(decks.getAiDecks().get(pl.getIndex())).setPlayer(pl.getPlayer()));
}
}
return registered;
}
public void addTournamentPlayer(LobbyPlayer pl) {
TournamentPlayer player = new TournamentPlayer(pl);
allPlayers.add(player);

View File

@@ -12,6 +12,11 @@ public class TournamentBracket extends AbstractTournament {
// Don't initialize the tournament if no players are available
}
public TournamentBracket(List<TournamentPlayer> allPlayers, int pairingAmount) {
super((int)(Math.ceil(Math.log(allPlayers.size())/Math.log(2))), allPlayers);
this.playersInPairing = pairingAmount;
}
public TournamentBracket(int ttlRnds, List<TournamentPlayer> allPlayers) {
super(ttlRnds, allPlayers);
initializeTournament();
@@ -26,42 +31,58 @@ public class TournamentBracket extends AbstractTournament {
@Override
public void generateActivePairings() {
activeRound++;
int numByes = 0;
if (activeRound == 1) {
// Determine how many first round byes there should be.
int fullBracketSize = (int)(Math.pow(2, Math.ceil(Math.log(this.remainingPlayers.size())/Math.log(2))));
numByes = fullBracketSize - this.remainingPlayers.size();
}
// The first X remaining players will receive the required first round Byes
// Since this is a bracket, this should "even" the bracket out.
// Preferably our brackets will always have 2^X amount of players
List<TournamentPlayer> pair = new ArrayList<>();
int count = 0;
for (TournamentPlayer tp : this.remainingPlayers) {
pair.add(tp);
count++;
if (count == this.playersInPairing) {
if (count == this.playersInPairing || numByes > 0) {
count = 0;
activePairings.add(new TournamentPairing(activeRound, pair));
TournamentPairing pairing = new TournamentPairing(activeRound, pair);
if (numByes > 0) {
numByes--;
pairing.setBye(true);
}
activePairings.add(pairing);
pair = new ArrayList<>();
}
}
if (count >= 1) {
// Leftover players. Really shouldn't happen in a Bracket.
TournamentPairing pairing = new TournamentPairing(activeRound, pair);
if (count == 1) {
pairing.setBye(true);
}
activePairings.add(pairing);
}
}
@Override
public void reportMatchCompletion(TournamentPairing pairing) {
public boolean reportMatchCompletion(TournamentPairing pairing) {
// Returns whether there are more matches left in this round
finishMatch(pairing);
for (TournamentPlayer tp : pairing.getPairedPlayers()) {
if (!tp.equals(pairing.getWinner())) {
remainingPlayers.remove(tp);
tp.setActive(false);
if (!pairing.isBye()) {
for (TournamentPlayer tp : pairing.getPairedPlayers()) {
if (!tp.equals(pairing.getWinner())) {
tp.addLoss();
remainingPlayers.remove(tp);
tp.setActive(false);
} else {
tp.addWin();
}
}
}
if (activePairings.isEmpty()) {
completeRound();
return false;
}
return true;
}
@Override

View File

@@ -29,6 +29,10 @@ public class TournamentPlayer {
this.player = player;
}
public void addLoss() { losses++; }
public void addWin() { wins++; }
public void addTie() { ties++; }
public int getWins() {
return wins;
}

View File

@@ -1,34 +1,113 @@
package forge.tournament.system;
import com.google.common.collect.Lists;
import forge.player.GamePlayerUtil;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@SuppressWarnings("serial")
public class TournamentRoundRobin extends AbstractTournament {
// Round Robin tournaments where you play everyone in your group/pod. Declare winner or break to top X
public TournamentRoundRobin(int ttlRnds, int pairingAmount) {
super(ttlRnds);
this.playersInPairing = pairingAmount;
// Don't initialize the tournament if no players are available
}
public TournamentRoundRobin(int ttlRnds, List<TournamentPlayer> allPlayers) {
super(ttlRnds, allPlayers);
initializeTournament();
}
@Override
public void generateActivePairings() {
public TournamentRoundRobin(List<TournamentPlayer> allPlayers, int pairingAmount) {
super(allPlayers.size() % 2 == 0 ? allPlayers.size() - 1 : allPlayers.size(), allPlayers);
this.playersInPairing = pairingAmount;
}
@Override
public void reportMatchCompletion(TournamentPairing pairing) {
public void generateActivePairings() {
int numPlayers = this.remainingPlayers.size();
List<TournamentPlayer> pair = new ArrayList<>();
int count = 0;
List<TournamentPlayer> roundPairings = Lists.newArrayList(this.remainingPlayers);
if (numPlayers % 2 == 1) {
roundPairings.add(new TournamentPlayer(GamePlayerUtil.createAiPlayer("BYE", 0)));
numPlayers++;
}
TournamentPlayer pivot = roundPairings.get(0);
roundPairings.remove(0);
for(int i = 0; i < activeRound; i++) {
// Rotate X amount of players, where X is the current round-1
TournamentPlayer rotate = roundPairings.get(0);
roundPairings.remove(0);
roundPairings.add(rotate);
}
roundPairings.add(0, pivot);
activeRound++;
for(int i = 0; i < numPlayers/2; i++) {
boolean bye = false;
if (roundPairings.get(i).getPlayer().getName().equals("BYE")) {
bye = true;
} else {
pair.add(roundPairings.get(i));
}
if (roundPairings.get(numPlayers-i-1).getPlayer().getName().equals("BYE")) {
bye = true;
} else {
pair.add(roundPairings.get(numPlayers-i-1));
}
TournamentPairing pairing = new TournamentPairing(activeRound, pair);
pairing.setBye(bye);
activePairings.add(pairing);
pair = new ArrayList<>();
}
}
@Override
public boolean reportMatchCompletion(TournamentPairing pairing) {
// Returns whether there are more matches left in this round
finishMatch(pairing);
if (!pairing.isBye()) {
for (TournamentPlayer tp : pairing.getPairedPlayers()) {
if (!tp.equals(pairing.getWinner())) {
tp.addLoss();
} else {
tp.addWin();
}
}
}
if (activePairings.isEmpty()) {
completeRound();
return false;
}
return true;
}
@Override
public boolean completeRound() {
return false;
if (activeRound < totalRounds) {
if (continualPairing) {
generateActivePairings();
}
return true;
} else {
endTournament();
return false;
}
}
@Override
public void endTournament() {
this.activePairings.clear();
}
}

View File

@@ -4,6 +4,12 @@ import java.util.List;
@SuppressWarnings("serial")
public class TournamentSwiss extends AbstractTournament {
//http://www.wizards.com/DCI/downloads/Swiss_Pairings.pdf
public TournamentSwiss(int ttlRnds, int pairingAmount) {
super(ttlRnds);
this.playersInPairing = pairingAmount;
// Don't initialize the tournament if no players are available
}
public TournamentSwiss(int ttlRnds, List<TournamentPlayer> allPlayers) {
super(ttlRnds, allPlayers);
@@ -16,8 +22,8 @@ public class TournamentSwiss extends AbstractTournament {
}
@Override
public void reportMatchCompletion(TournamentPairing pairing) {
public boolean reportMatchCompletion(TournamentPairing pairing) {
return false;
}
@Override