Sealed Deck mini tournaments, stage 1 (no sideboarding yet).

This commit is contained in:
RumbleBBU
2012-09-11 15:15:09 +00:00
parent 016953c2a0
commit a492cbe985
10 changed files with 556 additions and 32 deletions

2
.gitattributes vendored
View File

@@ -12191,6 +12191,7 @@ src/main/java/forge/game/limited/CardRatings.java -text
src/main/java/forge/game/limited/CreatureComparator.java -text
src/main/java/forge/game/limited/CustomLimited.java svneol=native#text/plain
src/main/java/forge/game/limited/DeckColors.java svneol=native#text/plain
src/main/java/forge/game/limited/GauntletMini.java -text
src/main/java/forge/game/limited/IBoosterDraft.java svneol=native#text/plain
src/main/java/forge/game/limited/LimitedDeck.java -text
src/main/java/forge/game/limited/ReadDraftRankings.java -text
@@ -12357,6 +12358,7 @@ src/main/java/forge/gui/home/utilities/VSubmenuUtilities.java -text
src/main/java/forge/gui/home/utilities/package-info.java svneol=native#text/plain
src/main/java/forge/gui/match/CMatchUI.java -text
src/main/java/forge/gui/match/ControlWinLose.java -text
src/main/java/forge/gui/match/GauntletWinLose.java -text
src/main/java/forge/gui/match/QuestWinLoseCardViewer.java -text
src/main/java/forge/gui/match/QuestWinLoseHandler.java -text
src/main/java/forge/gui/match/VMatchUI.java -text

View File

@@ -35,6 +35,8 @@ import forge.game.zone.ZoneType;
import forge.properties.ForgeProps;
import forge.properties.NewConstants;
import forge.quest.QuestController;
import forge.game.limited.GauntletMini;
/**
* Please use public getters and setters instead of direct field access.
@@ -58,6 +60,9 @@ public final class AllZone {
/** Global <code>questData</code>. */
private static forge.quest.QuestController quest = null;
/** Global <code>gauntletData</code>. */
private static forge.game.limited.GauntletMini gauntlet = null;
/** Constant <code>NAME_CHANGER</code>. */
private static final NameChanger NAME_CHANGER = new NameChanger();
@@ -132,7 +137,21 @@ public final class AllZone {
return AllZone.quest;
}
/**
* <p>
* getGauntletData.
* </p>
*
* @return a {@link forge.quest.data.QuestData} object.
* @since 1.0.15
*/
public static forge.game.limited.GauntletMini getGauntlet() {
if (gauntlet == null) {
gauntlet = new GauntletMini();
}
return AllZone.gauntlet;
}
/**
* <p>

View File

@@ -8787,8 +8787,7 @@ public class Card extends GameEntity implements Comparable<Card> {
}
if (kw.equals("Protection from colored spells")
&& (source.isInstant() || source.isSorcery()
|| (source.isAura() && !source.isInZone(ZoneType.Battlefield)))
&& (source.isInstant() || source.isSorcery() || source.isAura())
&& CardFactoryUtil.isColored(source)) {
return true;
}

View File

@@ -36,6 +36,7 @@ import forge.deck.io.DeckSerializer;
import forge.gui.deckeditor.tables.TableSorter;
import forge.item.CardPrinted;
import forge.item.ItemPoolView;
import forge.game.limited.ReadDraftRankings;
import forge.util.FileSection;
import forge.util.FileUtil;
import forge.util.closures.Lambda1;
@@ -271,6 +272,49 @@ public class Deck extends DeckBase implements Serializable {
return out;
}
/**
* <p>
* getDraftValue.
* </p>
*
* @return the combined draft values of cards in the main deck
*/
public double getDraftValue() {
double value = 0;
double divider = 0;
ReadDraftRankings ranker = new ReadDraftRankings();
if (this.getMain().isEmpty()) {
return 0;
}
double best = 1.0;
for (int i = 0; i < this.getMain().toForgeCardList().size(); i++) {
CardPrinted evalCard = this.getMain().toFlatList().get(i);
if (ranker.getRanking(evalCard.getName(), evalCard.getEdition()) != null) {
double add = ranker.getRanking(evalCard.getName(), evalCard.getEdition());
// System.out.println(this.getMain().toFlatList().get(i).getName() + " is worth " + add);
value += add;
divider += 1.0;
if (best > add) {
best = add;
}
}
}
if (divider == 0 || value == 0) {
return 0;
}
value /= divider;
return (20.0 / (best + (2 * value)));
}
public static final Lambda1<String, Deck> FN_NAME_SELECTOR = new Lambda1<String, Deck>() {
@Override
public String apply(Deck arg1) {

View File

@@ -18,6 +18,8 @@
package forge.deck;
import java.util.ArrayList;
import java.util.TreeMap;
// import java.lang.Double;
import java.util.List;
@@ -42,7 +44,7 @@ public class DeckGroup extends DeckBase {
private static final long serialVersionUID = -1628725522049635829L;
private Deck humanDeck;
private final List<Deck> aiDecks = new ArrayList<Deck>();
private List<Deck> aiDecks = new ArrayList<Deck>();
/**
* Gets the human deck.
@@ -71,6 +73,35 @@ public class DeckGroup extends DeckBase {
this.humanDeck = humanDeck;
}
/**
* Evaluate and 'rank' the ai decks.
*
*
*/
public final void rankAiDecks() {
if (this.aiDecks.size() < 2) {
return;
}
// double [] draftValues = new double [this.aiDecks.size()];
TreeMap<Double, Deck> draftData = new TreeMap<Double, Deck>();
for (int i = 0; i < this.aiDecks.size(); i++) {
// draftValues[i] = this.aiDecks.get(i).getDraftValue();
draftData.put(new Double(this.aiDecks.get(i).getDraftValue()), this.aiDecks.get(i));
// System.out.println("\nAI Deck " + i + "(" + this.aiDecks.get(i) + ") has draft value:" + this.aiDecks.get(i).getDraftValue() + "\n\n");
}
List<Deck> sortedData = new ArrayList<Deck>(draftData.values());
for (int j = 0; j < sortedData.size(); j++) {
Deck getDeck = sortedData.get(j);
}
this.aiDecks = sortedData;
}
@Override
protected void cloneFieldsTo(final DeckBase clone) {
super.cloneFieldsTo(clone);

View File

@@ -0,0 +1,208 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.game.limited;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import forge.Constant;
import forge.AllZone;
import forge.Command;
import forge.Singletons;
import forge.control.FControl;
import forge.deck.Deck;
import forge.deck.DeckBase;
import forge.deck.DeckGroup;
import forge.game.GameNew;
import forge.game.GameType;
import forge.gui.GuiUtils;
import forge.gui.SOverlayUtils;
import forge.gui.deckeditor.CDeckEditorUI;
import forge.gui.deckeditor.controllers.ACEditorBase;
import forge.gui.deckeditor.controllers.CEditorLimited;
import forge.gui.framework.ICDoc;
import forge.gui.toolbox.FSkin;
import forge.item.CardPrinted;
import forge.item.ItemPool;
import forge.properties.ForgeProps;
import forge.properties.NewConstants;
import forge.util.TextUtil;
/**
* <p>
* GauntletMini class.
* </p>
*
* @author Forge
* @version $Id: GauntletMini.java $
* @since 1.2.xx
*/
public class GauntletMini {
private int rounds;
private Deck humanDeck;
private int currentRound;
private int wins;
private int losses;
// private final String humanName;
/**
* TODO: Write javadoc for Constructor.
*/
public void gauntletMini() {
currentRound = 1;
wins = 0;
losses = 0;
// humanName = hName;
}
/**
* TODO: Write javadoc.
* @param gameRounds
* the number of rounds in the mini tournament
*/
public void setRounds(int gameRounds) {
rounds = gameRounds;
}
/**
* TODO: Write javadoc.
* @param hDeck
* the human deck for this tournament
*/
public void setHumanDeck(Deck hDeck) {
humanDeck = hDeck;
}
/**
* TODO: Write javadoc.
*/
public void resetCurrentRound() {
wins = 0;
losses = 0;
Constant.Runtime.HUMAN_DECK[0] = humanDeck;
Constant.Runtime.COMPUTER_DECK[0] = Singletons.getModel().getDecks().getSealed().get(humanDeck.getName()).getAiDecks().get(0);
currentRound = 1;
}
/**
* TODO: Write javadoc.
*/
public void nextRound() {
// System.out.println("Moving from round " + currentRound + " to round " + currentRound + 1 + " of " + rounds);
if (currentRound >= rounds) {
currentRound = rounds;
return;
}
Constant.Runtime.HUMAN_DECK[0] = humanDeck;
Constant.Runtime.COMPUTER_DECK[0] = Singletons.getModel().getDecks().getSealed().get(humanDeck.getName()).getAiDecks().get(currentRound);
currentRound += 1;
}
/**
* TODO: Write javadoc for this method.
* @param args
*/
public void launch() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
SOverlayUtils.startGameOverlay();
SOverlayUtils.showOverlay();
}
});
final SwingWorker<Object, Void> worker = new SwingWorker<Object, Void>() {
@Override
public Object doInBackground() {
Constant.Runtime.setGameType(GameType.Sealed);
GameNew.newGame(Constant.Runtime.HUMAN_DECK[0], Constant.Runtime.COMPUTER_DECK[0]);
return null;
}
@Override
public void done() {
SOverlayUtils.hideOverlay();
}
};
worker.execute();
}
/**
* TODO: Write javadoc for this method.
* @param args
* @return int, number of rounds in the Sealed Deck tournament
*/
public final int getRounds() {
return rounds;
}
/**
* TODO: Write javadoc for this method.
* @param args
* @return int, number of rounds in the Sealed Deck tournament
*/
public final int getCurrentRound() {
return currentRound;
}
/**
* TODO: Write javadoc for this method.
* @param args
*/
public void addWin() {
wins++;
}
/**
* TODO: Write javadoc for this method.
* @param args
*/
public void addLoss() {
losses++;
}
/**
* TODO: Write javadoc for this method.
* @param args
*/
public final int getWins() {
return wins;
}
/**
* TODO: Write javadoc for this method.
* @param args
*/
public final int getLosses() {
return losses;
}
}

View File

@@ -13,6 +13,7 @@ import javax.swing.SwingWorker;
import org.apache.commons.lang3.StringUtils;
import forge.AllZone;
import forge.Command;
import forge.Constant;
import forge.Singletons;
@@ -24,6 +25,7 @@ import forge.game.GameNew;
import forge.game.GameType;
import forge.game.limited.SealedDeck;
import forge.game.limited.SealedDeckFormat;
import forge.game.limited.GauntletMini;
import forge.gui.GuiUtils;
import forge.gui.SOverlayUtils;
import forge.gui.deckeditor.CDeckEditorUI;
@@ -125,37 +127,19 @@ public enum CSubmenuSealed implements ICDoc {
return;
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
SOverlayUtils.startGameOverlay();
SOverlayUtils.showOverlay();
}
});
int rounds = Singletons.getModel().getDecks().getSealed().get(human.getName()).getAiDecks().size();
// System.out.println("There are " + rounds + " rounds in this game.");
final SwingWorker<Object, Void> worker = new SwingWorker<Object, Void>() {
@Override
public Object doInBackground() {
Constant.Runtime.HUMAN_DECK[0] = human;
Constant.Runtime.COMPUTER_DECK[0] = Singletons.getModel().getDecks().getSealed().get(human.getName()).getAiDecks().get(0);
Constant.Runtime.setGameType(GameType.Sealed);
GameNew.newGame(Constant.Runtime.HUMAN_DECK[0], Constant.Runtime.COMPUTER_DECK[0]);
return null;
}
@Override
public void done() {
SOverlayUtils.hideOverlay();
}
};
worker.execute();
AllZone.getGauntlet().setRounds(rounds);
AllZone.getGauntlet().setHumanDeck(human);
AllZone.getGauntlet().resetCurrentRound();
AllZone.getGauntlet().launch();
}
/** */
@SuppressWarnings("unchecked")
private <T extends DeckBase> void setupSealed() {
final ArrayList<String> sealedTypes = new ArrayList<String>();
sealedTypes.add("Full Cardpool");
sealedTypes.add("Block / Set");
@@ -186,6 +170,16 @@ public enum CSubmenuSealed implements ICDoc {
return;
}
final Integer[] integers = new Integer[5];
for (int i = 0; i <= 4; i++) {
integers[i] = Integer.valueOf(i + 1);
}
Integer rounds = GuiUtils.chooseOne("How many rounds?", integers);
// System.out.println("You selected " + rounds + " rounds.");
final String sDeckName = JOptionPane.showInputDialog(null,
ForgeProps.getLocalized(NewConstants.Lang.OldGuiNewGame.NewGameText.SAVE_SEALED_MSG),
ForgeProps.getLocalized(NewConstants.Lang.OldGuiNewGame.NewGameText.SAVE_SEALED_TTL),
@@ -195,10 +189,12 @@ public enum CSubmenuSealed implements ICDoc {
return;
}
// May check for name uniqueness here
// NOTE: Here we should check if a similarly-named tournament already exists,
// and if it does, delete it first! -BBU
final ItemPool<CardPrinted> sDeck = sd.getCardpool();
final ItemPool<CardPrinted> sDeck2 = sd.getCardpool();
ItemPool<CardPrinted> aiDecks = sd.getCardpool();
final Deck deck = new Deck(sDeckName);
deck.getSideboard().addAll(sDeck);
@@ -209,7 +205,17 @@ public enum CSubmenuSealed implements ICDoc {
final DeckGroup sealed = new DeckGroup(sDeckName);
sealed.setHumanDeck(deck);
sealed.addAiDeck(new SealedDeck(sDeck2.toFlatList()).buildDeck());
for (int i = 0; i < rounds; i++) {
if (i > 0) {
// Re-randomize for AI decks beyond the first...
aiDecks = sd.getCardpool();
}
sealed.addAiDeck(new SealedDeck(aiDecks.toFlatList()).buildDeck());
}
// Rank the AI decks
sealed.rankAiDecks();
Singletons.getModel().getDecks().getSealed().add(sealed);
final ACEditorBase<?, T> editor = (ACEditorBase<?, T>) new CEditorLimited(

View File

@@ -49,7 +49,7 @@ public enum VSubmenuSealed implements IVSubmenu {
private final DeckLister lstDecks = new DeckLister(GameType.Sealed);
private final JLabel btnBuildDeck = new FLabel.Builder()
.fontSize(16)
.opaque(true).hoverable(true).text("Build a Sealed Deck").build();
.opaque(true).hoverable(true).text("Build a Sealed Deck Game").build();
private final JLabel btnDirections = new FLabel.Builder()
.fontSize(16)
.text("Click For Directions").fontAlign(SwingConstants.CENTER).build();

View File

@@ -0,0 +1,211 @@
package forge.gui.match;
/** Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import forge.AllZone;
import forge.Singletons;
import javax.swing.JLabel;
import forge.gui.toolbox.FSkin;
import forge.model.FMatchState;
import forge.properties.ForgePreferences.FPref;
import forge.game.limited.GauntletMini;
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.BorderFactory;
import javax.swing.SwingConstants;
/**
* TODO: Write javadoc for this type.
*
*/
public class GauntletWinLose extends ControlWinLose {
private final transient boolean wonMatch;
private transient ViewWinLose view;
private GauntletMini gauntlet;
private boolean nextRound = false;
/** String constraint parameters. */
private static final String CONSTRAINTS_TITLE = "w 95%!, gap 0 0 20px 10px";
private static final String CONSTRAINTS_TEXT = "w 95%!,, h 180px!, gap 0 0 0 20px";
private transient JLabel lblTemp1;
private transient JLabel lblTemp2;
private final transient FMatchState matchState;
/**
* Instantiates a new gauntlet win/lose handler.
*
* @param view0 ViewWinLose object
*/
public GauntletWinLose(final ViewWinLose view0) {
super(view0);
this.view = view0;
gauntlet = AllZone.getGauntlet();
matchState = Singletons.getModel().getMatchState();
this.wonMatch = matchState.isMatchWonBy(AllZone.getHumanPlayer().getName());
}
/**
* <p>
* populateCustomPanel.
* </p>
* @return true, if successful
*/
@Override
public final boolean populateCustomPanel() {
// view.getBtnRestart().setVisible(false);
// Deliberate; allow replaying bad tournaments
//TODO: do per-game actions like ante here...
resetView();
nextRound = false;
if (Singletons.getModel().getMatchState().hasWonLastGame(AllZone.getHumanPlayer().getName())) {
gauntlet.addWin();
}
else {
gauntlet.addLoss();
}
if (!matchState.isMatchOver()) {
showTournamentInfo("Tournament Info");
return true;
} else {
if (this.wonMatch) {
if (gauntlet.getCurrentRound() < gauntlet.getRounds()) {
view.getBtnContinue().setText("Next Round (" + (gauntlet.getCurrentRound() + 1)
+ "/" + gauntlet.getRounds() + ")");
nextRound = true;
view.getBtnContinue().setEnabled(true);
showTournamentInfo("YOU HAVE WON ROUND " + gauntlet.getCurrentRound() + "/"
+ gauntlet.getRounds());
}
else {
showTournamentInfo("***CONGRATULATIONS! YOU HAVE WON THE TOURNAMENT!***");
}
} else {
showTournamentInfo("YOU HAVE LOST ON ROUND " + gauntlet.getCurrentRound() + "/"
+ gauntlet.getRounds());
view.getBtnContinue().setVisible(false);
}
}
return true;
}
private void showTournamentInfo(final String newTitle) {
this.lblTemp1 = new TitleLabel(newTitle);
this.lblTemp2 = new JLabel("Round: " + gauntlet.getCurrentRound() + "/" + gauntlet.getRounds()
+ " Total Wins: " + gauntlet.getWins()
+ " Total Losses: " + gauntlet.getLosses());
this.lblTemp2.setHorizontalAlignment(SwingConstants.CENTER);
this.lblTemp2.setFont(FSkin.getFont(14));
this.lblTemp2.setForeground(Color.white);
this.lblTemp2.setIconTextGap(50);
this.getView().getPnlCustom().add(this.lblTemp1, GauntletWinLose.CONSTRAINTS_TITLE);
this.getView().getPnlCustom().add(this.lblTemp2, GauntletWinLose.CONSTRAINTS_TEXT);
}
/**
* <p>
* actionOnRestart.
* </p>
* When "quit" button is pressed, this method restarts the whole tournament.
*
*/
@Override
public final void actionOnRestart() {
resetView();
gauntlet.resetCurrentRound();
super.actionOnRestart();
}
/**
* <p>
* actionOnQuit.
* </p>
* When "quit" button is pressed, we exit the tournament.
*
*/
@Override
public final void actionOnQuit() {
resetView();
gauntlet.resetCurrentRound();
super.actionOnQuit();
}
/**
* <p>
* actionOnContinue.
* </p>
* When "continue / next round" button is pressed, we either continue
* to the next game in the current match or (next round) proceed to
* the next round in the mini tournament.
*
*/
@Override
public final void actionOnContinue() {
resetView();
if (nextRound) {
gauntlet.nextRound();
super.actionOnRestart();
}
else {
super.actionOnContinue();
}
}
/**
* <p>
* ResetView
* </p>
* Restore the default texts to the win/lose panel buttons.
*
*/
private void resetView() {
view.getBtnQuit().setText("Quit");
view.getBtnContinue().setText("Continue");
}
/**
* JLabel header, adapted from QuestWinLoseHandler.
*
*/
@SuppressWarnings("serial")
private class TitleLabel extends JLabel {
TitleLabel(final String msg) {
super(msg);
this.setFont(FSkin.getFont(16));
this.setPreferredSize(new Dimension(200, 40));
this.setHorizontalAlignment(SwingConstants.CENTER);
this.setForeground(Color.white);
this.setBorder(BorderFactory.createMatteBorder(1, 0, 1, 0, Color.white));
}
}
}

View File

@@ -58,6 +58,10 @@ public class ViewWinLose {
if (Constant.Runtime.getGameType() == GameType.Quest) {
control = new QuestWinLoseHandler(this);
}
else if (Constant.Runtime.getGameType() == GameType.Sealed) {
System.out.println("Sealed game over!");
control = new ControlWinLose(this);
}
else {
control = new ControlWinLose(this);
}