- Implemented a way to auto-suggest basic lands in the Add Basic Lands dialog in desktop and mobile Forge.

This commit is contained in:
Agetian
2017-06-18 16:41:51 +00:00
parent bcaf069d96
commit b19efd6c0d
4 changed files with 111 additions and 2 deletions

View File

@@ -42,17 +42,21 @@ import forge.card.mana.ManaCostShard;
import forge.deck.CardPool;
import forge.deck.Deck;
import forge.deck.DeckProxy;
import forge.deck.DeckgenUtil;
import forge.item.PaperCard;
import forge.model.FModel;
import forge.toolbox.FComboBox;
import forge.toolbox.FComboBoxPanel;
import forge.toolbox.FHtmlViewer;
import forge.toolbox.FLabel;
import forge.toolbox.FMouseAdapter;
import forge.toolbox.FOptionPane;
import forge.toolbox.FSkin;
import forge.toolbox.FTextField;
import forge.toolbox.FSkin.SkinnedPanel;
import forge.view.arcane.CardPanel;
import java.awt.event.MouseEvent;
import java.util.Map;
@SuppressWarnings("serial")
@@ -99,6 +103,26 @@ public class AddBasicLandsDialog {
panel.add(lblDeckInfo);
lblDeckInfo.setFont(FSkin.getFont(14));
lblDeckInfo.addMouseListener(new FMouseAdapter() {
@Override
public void onLeftDoubleClick(MouseEvent e) {
Map<ManaCostShard, Integer> suggestionMap = DeckgenUtil.suggestBasicLandCount(deck);
pnlPlains.count = suggestionMap.get(ManaCostShard.WHITE);
pnlIsland.count = suggestionMap.get(ManaCostShard.BLUE);
pnlSwamp.count = suggestionMap.get(ManaCostShard.BLACK);
pnlMountain.count = suggestionMap.get(ManaCostShard.RED);
pnlForest.count = suggestionMap.get(ManaCostShard.GREEN);
pnlPlains.lblCount.setText(String.valueOf(pnlPlains.count));
pnlIsland.lblCount.setText(String.valueOf(pnlIsland.count));
pnlSwamp.lblCount.setText(String.valueOf(pnlSwamp.count));
pnlMountain.lblCount.setText(String.valueOf(pnlMountain.count));
pnlForest.lblCount.setText(String.valueOf(pnlForest.count));
updateDeckInfoLabel();
}
});
lblDeckInfo.setToolTipText("Deck statistics. Double click to auto-suggest basic lands.");
cbLandSet.addActionListener(new ActionListener() {
@Override

View File

@@ -48,12 +48,15 @@ import forge.util.Callback;
import forge.util.Utils;
import com.badlogic.gdx.graphics.g2d.BitmapFont.HAlignment;
import java.util.Map;
public class AddBasicLandsDialog extends FDialog {
private static final float ADD_BTN_SIZE = Utils.AVG_FINGER_HEIGHT * 0.75f;
private static final float LAND_PANEL_PADDING = Utils.scale(3);
private final Deck currentDeck;
private final Callback<CardPool> callback;
private final FLabel lblLandSet = add(new FLabel.Builder().text("Land Set:").font(FSkinFont.get(12)).textColor(FLabel.INLINE_LABEL_COLOR).build());
@@ -86,15 +89,37 @@ public class AddBasicLandsDialog extends FDialog {
private final LandPanel pnlMountain = scroller.add(new LandPanel("Mountain"));
private final LandPanel pnlForest = scroller.add(new LandPanel("Forest"));
private final FTextArea lblDeckInfo = add(new FTextArea(true));
private final FTextArea lblDeckInfo = add(new FTextArea(true) {
@Override
public boolean tap(float x, float y, int count) {
if (count == 2) {
Map<ManaCostShard, Integer> suggestionMap = DeckgenUtil.suggestBasicLandCount(currentDeck);
pnlPlains.count = suggestionMap.get(ManaCostShard.WHITE);
pnlIsland.count = suggestionMap.get(ManaCostShard.BLUE);
pnlSwamp.count = suggestionMap.get(ManaCostShard.BLACK);
pnlMountain.count = suggestionMap.get(ManaCostShard.RED);
pnlForest.count = suggestionMap.get(ManaCostShard.GREEN);
pnlPlains.lblCount.setText(String.valueOf(pnlPlains.count));
pnlIsland.lblCount.setText(String.valueOf(pnlIsland.count));
pnlSwamp.lblCount.setText(String.valueOf(pnlSwamp.count));
pnlMountain.lblCount.setText(String.valueOf(pnlMountain.count));
pnlForest.lblCount.setText(String.valueOf(pnlForest.count));
updateDeckInfoLabel();
}
return true;
}
});
private int nonLandCount, oldLandCount;
private CardEdition landSet;
public AddBasicLandsDialog(Deck deck, CardEdition defaultLandSet, final Callback<CardPool> callback0) {
super("Add Basic Lands \n" + deck.getName(), 2);
super("Add Basic Lands to " + deck.getName() + "\n(double-tap statistics to auto-suggest)", 2);
callback = callback0;
currentDeck = deck;
lblDeckInfo.setAlignment(HAlignment.CENTER);
lblDeckInfo.setFont(FSkinFont.get(12));

View File

@@ -8,6 +8,9 @@ Some adjustments have been made to the algorithm used for calculating probabilit
- Achievement System updates -
Planar Conquest now uses its own set of achievements separate from Constructed achievements (this includes the Planar Conquest-exclusive Planeswalker game mode). Puzzle Mode should no longer give Constructed achievements and uses its own achievement set (currently only the number of solved puzzles is tracked, but this may improve in the future).
- Automatically Suggest Basic Lands in Deck Editor -
It is now possible to ask Forge to automatically suggest basic lands for your deck in the Add Basic Lands dialog of the deck editor. In desktop Forge, this is accomplished by double-clicking the statistics text in the bottom part of the dialog (hopefully someone will be able to code in a better, more intuitive way of doing this eventually). In mobile Forge, this is done by double tapping the statistics text. A tooltip is available in desktop Forge (and a hint text in mobile Forge) to make this feature more visible. Three deck sizes are supported by this algorithm: 40-card decks (if the number of cards in the main portion of the deck is less than 30, the algorithm will target a 40-card deck), 60-card decks (if the number of cards in the main portion is between 30 and 60, a 60-card deck will be targeted), and 100-card decks (if the deck is already above 60 cards when the feature is used, a 100-card deck will be targeted).
- Java 8 -
As part of increased privacy protections (cardforge.org now uses SSL), the content downloaders now require a minimum Java version of 8u101. In the future, all of Forge will be updated to require Java 8. If you're running the latest version of Java, but Forge does not let you use the content downloaders, check to make sure that you've uninstalled old versions. Additionally, check any JDK installations you have and ensure Forge is using the most up-to-date version.

View File

@@ -9,6 +9,8 @@ import forge.card.CardDb;
import forge.card.CardRules;
import forge.card.CardRulesPredicates;
import forge.card.ColorSet;
import forge.card.mana.ManaCost;
import forge.card.mana.ManaCostShard;
import forge.deck.generation.*;
import forge.game.GameFormat;
import forge.game.GameType;
@@ -530,4 +532,59 @@ public class DeckgenUtil {
return deck;
}
public static Map<ManaCostShard, Integer> suggestBasicLandCount(Deck d) {
int W=0, U=0, R=0, B=0, G=0, total=0;
List<PaperCard> cards = d.getOrCreate(DeckSection.Main).toFlatList();
// attempt to determine if building for sealed, constructed or EDH
int targetDeckSize = cards.size() < 30 ? 40
: cards.size() > 60 ? 100 : 60;
int numLandsToAdd = targetDeckSize - cards.size();
for (PaperCard c : d.getMain().toFlatList()) {
ManaCost m = c.getRules().getManaCost();
W += m.getShardCount(ManaCostShard.WHITE);
U += m.getShardCount(ManaCostShard.BLUE);
R += m.getShardCount(ManaCostShard.RED);
B += m.getShardCount(ManaCostShard.BLACK);
G += m.getShardCount(ManaCostShard.GREEN);
}
total = W + U + R + B + G;
int whiteSources = Math.round(numLandsToAdd * ((float)W / (float)total));
numLandsToAdd -= whiteSources;
total -= W;
int blueSources = Math.round(numLandsToAdd * ((float)U / (float)total));
numLandsToAdd -= blueSources;
total -= U;
int blackSources = Math.round(numLandsToAdd * ((float)B / (float)total));
numLandsToAdd -= blackSources;
total -= B;
int redSources = Math.round(numLandsToAdd * ((float)R / (float)total));
numLandsToAdd -= redSources;
total -= R;
int greenSources = Math.round(numLandsToAdd * ((float)G / (float)total));
numLandsToAdd -= greenSources;
total -= G;
// in case of a rounding error, add the remaining lands to one of the relevant colors
if (numLandsToAdd > 0) {
if (whiteSources > 0) { whiteSources += numLandsToAdd; }
else if (blueSources > 0) { blueSources += numLandsToAdd; }
else if (blackSources > 0) { blackSources += numLandsToAdd; }
else if (redSources > 0) { redSources += numLandsToAdd; }
else if (greenSources > 0) { greenSources += numLandsToAdd; }
}
HashMap<ManaCostShard, Integer> suggestionMap = new HashMap<>();
suggestionMap.put(ManaCostShard.WHITE, whiteSources);
suggestionMap.put(ManaCostShard.BLUE, blueSources);
suggestionMap.put(ManaCostShard.RED, redSources);
suggestionMap.put(ManaCostShard.BLACK, blackSources);
suggestionMap.put(ManaCostShard.GREEN, greenSources);
return suggestionMap;
}
}