Unified Deck AI Hints

This commit is contained in:
Paco Ito
2022-02-03 17:42:08 +00:00
committed by Sol
parent 2425623491
commit cde80c9c6e
9 changed files with 139 additions and 48 deletions

View File

@@ -51,6 +51,7 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
private String lastCardArtPreferenceUsed = "";
private Boolean lastCardArtOptimisationOptionUsed = null;
private boolean includeCardsFromUnspecifiedSet = false;
private UnplayableAICards unplayableAI = null;
public Deck() {
this("");
@@ -533,6 +534,37 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
return allCards;
}
public UnplayableAICards getUnplayableAICards() {
if (unplayableAI == null) {
unplayableAI = new UnplayableAICards(this);
}
return unplayableAI;
}
public static final class UnplayableAICards {
public final Map<DeckSection, List<? extends PaperCard>> unplayable = new HashMap<>();
public final int inMainDeck;
private UnplayableAICards(Deck myDeck) {
int mainDeck = 0;
for (Entry<DeckSection, CardPool> ds : myDeck) {
List<PaperCard> result = Lists.newArrayList();
for (Entry<PaperCard, Integer> cp : ds.getValue()) {
if (cp.getKey().getRules().getAiHints().getRemAIDecks()) {
result.add(cp.getKey());
}
}
if (ds.getKey().equals(DeckSection.Main)) {
mainDeck = result.size();
}
if (!result.isEmpty()) {
unplayable.put(ds.getKey(), result);
}
}
inMainDeck = mainDeck;
}
}
@Override
public boolean isEmpty() {
loadDeferredSections();

View File

@@ -0,0 +1,56 @@
/*
* 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.itemmanager.views;
import java.awt.Component;
import java.util.TreeSet;
import javax.swing.JTable;
import forge.deck.Deck;
import forge.deck.DeckSection;
import forge.util.DeckAIUtils;
import forge.util.Localizer;
public class DeckAIRenderer extends ItemCellRenderer {
private final Localizer localizer = Localizer.getInstance();
@Override
public boolean alwaysShowTooltip() {
return false;
}
@Override
public Component getTableCellRendererComponent(final JTable table, final Object value, final boolean isSelected, final boolean hasFocus, final int row, final int column) {
final StringBuilder label = new StringBuilder("");
final StringBuilder tooltip = new StringBuilder("");
if (value instanceof Deck.UnplayableAICards) {
final Deck.UnplayableAICards removedUnplayableCards = ((Deck.UnplayableAICards) value);
for (final DeckSection s: new TreeSet<>(removedUnplayableCards.unplayable.keySet())) {
int unplayableSize = removedUnplayableCards.unplayable.get(s).size();
tooltip.append("[" + DeckAIUtils.getLocalizedDeckSection(localizer, s) + ":" + unplayableSize + "]");
}
label.append(removedUnplayableCards.inMainDeck > 0 ? "" + removedUnplayableCards.inMainDeck : "");
}
setToolTipText(tooltip.toString());
return super.getTableCellRendererComponent(table, label.toString(), isSelected, hasFocus, row, row);
}
}

View File

@@ -58,6 +58,8 @@ public class ItemCellRenderer extends DefaultTableCellRenderer {
return new DeckStarRenderer();
case DECK_QUANTITY:
return new DeckQuantityRenderer();
case DECK_AI:
return new DeckAIRenderer();
default:
return new ItemCellRenderer();
}

View File

@@ -134,7 +134,7 @@ public final class DeckManager extends ItemManager<DeckProxy> implements IHasGam
x += IMAGE_SIZE + FList.PADDING;
ColorSet deckColor = deck.getColor();
float availableNameWidth = w - CardFaceSymbols.getWidth(deckColor, IMAGE_SIZE) - IMAGE_SIZE - 2 * FList.PADDING;
if (deck.getAI()) {
if (deck.getAI().inMainDeck == 0) {
g.drawOutlinedText("AI", font, Color.GREEN, Color.BLACK, x, y, w, IMAGE_SIZE, true, Align.left, true, false);
x += IMAGE_SIZE + FList.PADDING;
}

View File

@@ -1065,7 +1065,7 @@ public class ImageView<T extends InventoryItem> extends ItemView<T> {
g.drawImage(DeckPreferences.getPrefs(dp).getStarCount() > 0 ? FSkinImage.HDSTAR_FILLED : FSkinImage.HDSTAR_OUTLINE, x, y, symbolSize, symbolSize);
else
g.drawImage(DeckPreferences.getPrefs(dp).getStarCount() > 0 ? FSkinImage.STAR_FILLED : FSkinImage.STAR_OUTLINE, x, y, symbolSize, symbolSize);
if (dp.getAI()) {
if (dp.getAI().inMainDeck == 0) {
g.drawOutlinedText("AI", GROUP_HEADER_FONT, Color.GREEN, Color.BLACK, x+PADDING, y+symbolSize+PADDING, w, h, true, Align.left, false, false);
}
}

View File

@@ -42,7 +42,6 @@ public class DeckProxy implements InventoryItem {
// cached values
protected ColorSet color;
protected ColorSet colorIdentity;
protected Boolean ai;
protected Set<GameFormat> formats;
protected Set<GameFormat> exhaustiveFormats;
private Integer mainSize = null;
@@ -141,7 +140,6 @@ public class DeckProxy implements InventoryItem {
edition = null;
mainSize = null;
sbSize = null;
ai = null;
}
public ColorSet getColor() {
@@ -213,32 +211,8 @@ public class DeckProxy implements InventoryItem {
return colorIdentity;
}
public boolean getAI() {
if (ai == null) {
boolean hasAi = true;
for (final Entry<DeckSection, CardPool> deckEntry : getDeck()) {
switch (deckEntry.getKey()) {
case Main:
case Commander:
for (final Entry<PaperCard, Integer> poolEntry : deckEntry.getValue()) {
CardAiHints ai = poolEntry.getKey().getRules().getAiHints();
if (ai.getRemAIDecks()) {
hasAi = false;
break;
}
}
break;
case Sideboard: // Let's pretend the sideboard doesn't matter
default:
break; //ignore other sections
}
if (hasAi == false) {
break;
}
}
ai = hasAi;
}
return ai;
public Deck.UnplayableAICards getAI() {
return getDeck().getUnplayableAICards();
}

View File

@@ -463,13 +463,13 @@ public enum ColumnDef {
new Function<Entry<InventoryItem, Integer>, Comparable<?>>() {
@Override
public Comparable<?> apply(final Entry<InventoryItem, Integer> from) {
return toDeck(from.getKey()).getAI() ? Integer.valueOf(1) : Integer.valueOf(-1);
return toDeck(from.getKey()).getAI().inMainDeck;
}
},
new Function<Entry<? extends InventoryItem, Integer>, Object>() {
@Override
public Object apply(final Entry<? extends InventoryItem, Integer> from) {
return toDeck(from.getKey()).getAI()? "" : "X";
return toDeck(from.getKey()).getAI();
}
}),
/**

View File

@@ -17,6 +17,7 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeSet;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.Range;
@@ -133,6 +134,7 @@ import forge.localinstance.properties.ForgePreferences.FPref;
import forge.localinstance.skin.FSkinProp;
import forge.model.FModel;
import forge.util.CardTranslation;
import forge.util.DeckAIUtils;
import forge.util.ITriggerEvent;
import forge.util.Lang;
import forge.util.Localizer;
@@ -2093,8 +2095,8 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
for (Player p : unplayable.keySet()) {
final Map<DeckSection, List<? extends PaperCard>> removedUnplayableCards = unplayable.get(p);
final List<String> labels = new ArrayList<>();
for (final DeckSection s: removedUnplayableCards.keySet()) {
labels.add("=== " + getLocalizedDeckSection(s) + " ===");
for (final DeckSection s: new TreeSet<>(removedUnplayableCards.keySet())) {
labels.add("=== " + DeckAIUtils.getLocalizedDeckSection(localizer, s) + " ===");
for (PaperCard c: removedUnplayableCards.get(s)) {
labels.add(c.toString());
}
@@ -2104,20 +2106,6 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
}
}
private String getLocalizedDeckSection(DeckSection d) {
switch (d) {
case Avatar: return localizer.getMessage("lblAvatar");
case Commander: return localizer.getMessage("lblCommanderDeck");
case Main: return localizer.getMessage("lblMainDeck");
case Sideboard: return localizer.getMessage("lblSideboard");
case Planes: return localizer.getMessage("lblPlanarDeck");
case Schemes: return localizer.getMessage("lblSchemeDeck");
case Conspiracy: return /* TODO localise */ "Conspiracy";
case Dungeon: return /* TODO localise */ "Dungeon";
default: return /* TODO better handling */ "UNKNOWN";
}
}
@Override
public List<PaperCard> chooseCardsYouWonToAddToDeck(final List<PaperCard> losses) {
return getGui().many(localizer.getMessage("lblSelectCardstoAddtoYourDeck"), localizer.getMessage("lblAddTheseToMyDeck"), 0, losses.size(), losses, null);

View File

@@ -0,0 +1,39 @@
/*
* 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.util;
import forge.deck.DeckSection;
public class DeckAIUtils {
private DeckAIUtils() {
}
public static String getLocalizedDeckSection(Localizer localizer, DeckSection d) {
switch (d) {
case Avatar: return localizer.getMessage("lblAvatar");
case Commander: return localizer.getMessage("lblCommanderDeck");
case Main: return localizer.getMessage("lblMainDeck");
case Sideboard: return localizer.getMessage("lblSideboard");
case Planes: return localizer.getMessage("lblPlanarDeck");
case Schemes: return localizer.getMessage("lblSchemeDeck");
case Conspiracy: return /* TODO localise */ "Conspiracy";
case Dungeon: return /* TODO localise */ "Dungeon";
default: return /* TODO better handling */ "UNKNOWN";
}
}
}