mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 03:08:02 +00:00
Unified Deck AI Hints
This commit is contained in:
@@ -51,6 +51,7 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
|
|||||||
private String lastCardArtPreferenceUsed = "";
|
private String lastCardArtPreferenceUsed = "";
|
||||||
private Boolean lastCardArtOptimisationOptionUsed = null;
|
private Boolean lastCardArtOptimisationOptionUsed = null;
|
||||||
private boolean includeCardsFromUnspecifiedSet = false;
|
private boolean includeCardsFromUnspecifiedSet = false;
|
||||||
|
private UnplayableAICards unplayableAI = null;
|
||||||
|
|
||||||
public Deck() {
|
public Deck() {
|
||||||
this("");
|
this("");
|
||||||
@@ -533,6 +534,37 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
|
|||||||
return allCards;
|
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
|
@Override
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
loadDeferredSections();
|
loadDeferredSections();
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -58,6 +58,8 @@ public class ItemCellRenderer extends DefaultTableCellRenderer {
|
|||||||
return new DeckStarRenderer();
|
return new DeckStarRenderer();
|
||||||
case DECK_QUANTITY:
|
case DECK_QUANTITY:
|
||||||
return new DeckQuantityRenderer();
|
return new DeckQuantityRenderer();
|
||||||
|
case DECK_AI:
|
||||||
|
return new DeckAIRenderer();
|
||||||
default:
|
default:
|
||||||
return new ItemCellRenderer();
|
return new ItemCellRenderer();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ public final class DeckManager extends ItemManager<DeckProxy> implements IHasGam
|
|||||||
x += IMAGE_SIZE + FList.PADDING;
|
x += IMAGE_SIZE + FList.PADDING;
|
||||||
ColorSet deckColor = deck.getColor();
|
ColorSet deckColor = deck.getColor();
|
||||||
float availableNameWidth = w - CardFaceSymbols.getWidth(deckColor, IMAGE_SIZE) - IMAGE_SIZE - 2 * FList.PADDING;
|
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);
|
g.drawOutlinedText("AI", font, Color.GREEN, Color.BLACK, x, y, w, IMAGE_SIZE, true, Align.left, true, false);
|
||||||
x += IMAGE_SIZE + FList.PADDING;
|
x += IMAGE_SIZE + FList.PADDING;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
g.drawImage(DeckPreferences.getPrefs(dp).getStarCount() > 0 ? FSkinImage.HDSTAR_FILLED : FSkinImage.HDSTAR_OUTLINE, x, y, symbolSize, symbolSize);
|
||||||
else
|
else
|
||||||
g.drawImage(DeckPreferences.getPrefs(dp).getStarCount() > 0 ? FSkinImage.STAR_FILLED : FSkinImage.STAR_OUTLINE, x, y, symbolSize, symbolSize);
|
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);
|
g.drawOutlinedText("AI", GROUP_HEADER_FONT, Color.GREEN, Color.BLACK, x+PADDING, y+symbolSize+PADDING, w, h, true, Align.left, false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ public class DeckProxy implements InventoryItem {
|
|||||||
// cached values
|
// cached values
|
||||||
protected ColorSet color;
|
protected ColorSet color;
|
||||||
protected ColorSet colorIdentity;
|
protected ColorSet colorIdentity;
|
||||||
protected Boolean ai;
|
|
||||||
protected Set<GameFormat> formats;
|
protected Set<GameFormat> formats;
|
||||||
protected Set<GameFormat> exhaustiveFormats;
|
protected Set<GameFormat> exhaustiveFormats;
|
||||||
private Integer mainSize = null;
|
private Integer mainSize = null;
|
||||||
@@ -141,7 +140,6 @@ public class DeckProxy implements InventoryItem {
|
|||||||
edition = null;
|
edition = null;
|
||||||
mainSize = null;
|
mainSize = null;
|
||||||
sbSize = null;
|
sbSize = null;
|
||||||
ai = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ColorSet getColor() {
|
public ColorSet getColor() {
|
||||||
@@ -213,32 +211,8 @@ public class DeckProxy implements InventoryItem {
|
|||||||
return colorIdentity;
|
return colorIdentity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getAI() {
|
public Deck.UnplayableAICards getAI() {
|
||||||
if (ai == null) {
|
return getDeck().getUnplayableAICards();
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -463,13 +463,13 @@ public enum ColumnDef {
|
|||||||
new Function<Entry<InventoryItem, Integer>, Comparable<?>>() {
|
new Function<Entry<InventoryItem, Integer>, Comparable<?>>() {
|
||||||
@Override
|
@Override
|
||||||
public Comparable<?> apply(final Entry<InventoryItem, Integer> from) {
|
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>() {
|
new Function<Entry<? extends InventoryItem, Integer>, Object>() {
|
||||||
@Override
|
@Override
|
||||||
public Object apply(final Entry<? extends InventoryItem, Integer> from) {
|
public Object apply(final Entry<? extends InventoryItem, Integer> from) {
|
||||||
return toDeck(from.getKey()).getAI()? "" : "X";
|
return toDeck(from.getKey()).getAI();
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
|
||||||
import org.apache.commons.lang3.ObjectUtils;
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
import org.apache.commons.lang3.Range;
|
import org.apache.commons.lang3.Range;
|
||||||
@@ -133,6 +134,7 @@ import forge.localinstance.properties.ForgePreferences.FPref;
|
|||||||
import forge.localinstance.skin.FSkinProp;
|
import forge.localinstance.skin.FSkinProp;
|
||||||
import forge.model.FModel;
|
import forge.model.FModel;
|
||||||
import forge.util.CardTranslation;
|
import forge.util.CardTranslation;
|
||||||
|
import forge.util.DeckAIUtils;
|
||||||
import forge.util.ITriggerEvent;
|
import forge.util.ITriggerEvent;
|
||||||
import forge.util.Lang;
|
import forge.util.Lang;
|
||||||
import forge.util.Localizer;
|
import forge.util.Localizer;
|
||||||
@@ -2093,8 +2095,8 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
for (Player p : unplayable.keySet()) {
|
for (Player p : unplayable.keySet()) {
|
||||||
final Map<DeckSection, List<? extends PaperCard>> removedUnplayableCards = unplayable.get(p);
|
final Map<DeckSection, List<? extends PaperCard>> removedUnplayableCards = unplayable.get(p);
|
||||||
final List<String> labels = new ArrayList<>();
|
final List<String> labels = new ArrayList<>();
|
||||||
for (final DeckSection s: removedUnplayableCards.keySet()) {
|
for (final DeckSection s: new TreeSet<>(removedUnplayableCards.keySet())) {
|
||||||
labels.add("=== " + getLocalizedDeckSection(s) + " ===");
|
labels.add("=== " + DeckAIUtils.getLocalizedDeckSection(localizer, s) + " ===");
|
||||||
for (PaperCard c: removedUnplayableCards.get(s)) {
|
for (PaperCard c: removedUnplayableCards.get(s)) {
|
||||||
labels.add(c.toString());
|
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
|
@Override
|
||||||
public List<PaperCard> chooseCardsYouWonToAddToDeck(final List<PaperCard> losses) {
|
public List<PaperCard> chooseCardsYouWonToAddToDeck(final List<PaperCard> losses) {
|
||||||
return getGui().many(localizer.getMessage("lblSelectCardstoAddtoYourDeck"), localizer.getMessage("lblAddTheseToMyDeck"), 0, losses.size(), losses, null);
|
return getGui().many(localizer.getMessage("lblSelectCardstoAddtoYourDeck"), localizer.getMessage("lblAddTheseToMyDeck"), 0, losses.size(), losses, null);
|
||||||
|
|||||||
39
forge-gui/src/main/java/forge/util/DeckAIUtils.java
Normal file
39
forge-gui/src/main/java/forge/util/DeckAIUtils.java
Normal 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";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user