Added new color-specific booster packs to quests.

This commit is contained in:
Krazy
2015-06-13 02:23:02 +00:00
parent 00158ff984
commit 63a73df35f
18 changed files with 477 additions and 231 deletions

View File

@@ -1,17 +1,16 @@
package forge; package forge;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import forge.card.CardDb; import forge.card.CardDb;
import forge.item.*; import forge.item.*;
import forge.util.FileUtil; import forge.util.FileUtil;
import forge.util.ImageUtil; import forge.util.ImageUtil;
import org.apache.commons.lang3.StringUtils;
public class ImageKeys { import java.io.File;
import java.util.HashMap;
import java.util.Map;
public final class ImageKeys {
public static final String CARD_PREFIX = "c:"; public static final String CARD_PREFIX = "c:";
public static final String TOKEN_PREFIX = "t:"; public static final String TOKEN_PREFIX = "t:";
public static final String ICON_PREFIX = "i:"; public static final String ICON_PREFIX = "i:";
@@ -31,7 +30,7 @@ public class ImageKeys {
CACHE_FATPACK_PICS_DIR, CACHE_BOOSTERBOX_PICS_DIR, CACHE_PRECON_PICS_DIR, CACHE_TOURNAMENTPACK_PICS_DIR; CACHE_FATPACK_PICS_DIR, CACHE_BOOSTERBOX_PICS_DIR, CACHE_PRECON_PICS_DIR, CACHE_TOURNAMENTPACK_PICS_DIR;
private static Map<String, String> CACHE_CARD_PICS_SUBDIR; private static Map<String, String> CACHE_CARD_PICS_SUBDIR;
private static Map<String, Boolean> editionImageLookup = new HashMap<String, Boolean>(); private static Map<String, Boolean> editionImageLookup = new HashMap<>();
/** /**
* Private constructor to prevent instantiation. * Private constructor to prevent instantiation.
@@ -60,7 +59,7 @@ public class ImageKeys {
return ImageKeys.CARD_PREFIX + pc.getName() + CardDb.NameSetSeparator + pc.getEdition() + CardDb.NameSetSeparator + pc.getArtIndex() + (altState ? BACKFACE_POSTFIX : ""); return ImageKeys.CARD_PREFIX + pc.getName() + CardDb.NameSetSeparator + pc.getEdition() + CardDb.NameSetSeparator + pc.getArtIndex() + (altState ? BACKFACE_POSTFIX : "");
} }
// Inventory items don't have to know how a certain client should draw them. // Inventory items don't have to know how a certain client should draw them.
// That's why this method is not encapsulated and overloaded in the InventoryItem descendants // That's why this method is not encapsulated and overloaded in the InventoryItem descendants
public static String getImageKey(InventoryItem ii, boolean altState) { public static String getImageKey(InventoryItem ii, boolean altState) {
if (ii instanceof PaperCard) { if (ii instanceof PaperCard) {
@@ -71,6 +70,9 @@ public class ImageKeys {
} }
if (ii instanceof BoosterPack) { if (ii instanceof BoosterPack) {
BoosterPack bp = (BoosterPack)ii; BoosterPack bp = (BoosterPack)ii;
if (SealedProduct.specialSets.contains(bp.getEdition()) || bp.getEdition().equals("?")) {
return "b:" + bp.getName().substring(0, bp.getName().indexOf(bp.getItemType()) - 1);
}
int cntPics = StaticData.instance().getEditions().get(bp.getEdition()).getCntBoosterPictures(); int cntPics = StaticData.instance().getEditions().get(bp.getEdition()).getCntBoosterPictures();
String suffix = (1 >= cntPics) ? "" : ("_" + bp.getArtIndex()); String suffix = (1 >= cntPics) ? "" : ("_" + bp.getArtIndex());
return ImageKeys.BOOSTER_PREFIX + bp.getEdition() + suffix; return ImageKeys.BOOSTER_PREFIX + bp.getEdition() + suffix;
@@ -145,7 +147,7 @@ public class ImageKeys {
} }
// try without set name // try without set name
if (dir == CACHE_TOKEN_PICS_DIR) { if (dir.equals(CACHE_TOKEN_PICS_DIR)) {
int index = filename.lastIndexOf('_'); int index = filename.lastIndexOf('_');
if (index != -1) { if (index != -1) {
String setlessFilename = filename.substring(0, index); String setlessFilename = filename.substring(0, index);

View File

@@ -24,6 +24,7 @@ import com.google.common.collect.Lists;
import forge.StaticData; import forge.StaticData;
import forge.card.CardEdition.FoilType; import forge.card.CardEdition.FoilType;
import forge.item.IPaperCard; import forge.item.IPaperCard;
import forge.item.IPaperCard.Predicates.Presets;
import forge.item.PaperCard; import forge.item.PaperCard;
import forge.item.SealedProduct; import forge.item.SealedProduct;
import forge.util.Aggregates; import forge.util.Aggregates;
@@ -76,7 +77,7 @@ public class BoosterGenerator {
String[] sType = TextUtil.splitWithParenthesis(slotType, ' '); String[] sType = TextUtil.splitWithParenthesis(slotType, ' ');
String setCode = sType.length == 1 && template.getEdition() != null ? template.getEdition() : null; String setCode = sType.length == 1 && template.getEdition() != null ? template.getEdition() : null;
String sheetKey = StaticData.instance().getEditions().contains(setCode) ? slotType.trim() + " " + setCode: slotType.trim(); String sheetKey = StaticData.instance().getEditions().contains(setCode) ? slotType.trim() + " " + setCode : slotType.trim();
boolean foilInThisSlot = hasFoil && slotType.startsWith(foilSlot); boolean foilInThisSlot = hasFoil && slotType.startsWith(foilSlot);
if (foilInThisSlot) if (foilInThisSlot)
@@ -220,6 +221,32 @@ public class BoosterGenerator {
operator = StringUtils.strip(operator.substring(4), "() "); operator = StringUtils.strip(operator.substring(4), "() ");
String[] cardNames = TextUtil.splitWithParenthesis(operator, ',', '"', '"'); String[] cardNames = TextUtil.splitWithParenthesis(operator, ',', '"', '"');
toAdd = IPaperCard.Predicates.names(Lists.newArrayList(cardNames)); toAdd = IPaperCard.Predicates.names(Lists.newArrayList(cardNames));
} else if (operator.startsWith("color(")) {
operator = StringUtils.strip(operator.substring("color(".length() + 1), "()\" ");
switch (operator.toLowerCase()) {
case "black":
toAdd = Presets.IS_BLACK;
break;
case "blue":
toAdd = Presets.IS_BLUE;
break;
case "green":
toAdd = Presets.IS_GREEN;
break;
case "red":
toAdd = Presets.IS_RED;
break;
case "white":
toAdd = Presets.IS_WHITE;
break;
case "colorless":
toAdd = Presets.IS_COLORLESS;
break;
}
} else if (operator.startsWith("fromSets(")) {
operator = StringUtils.strip(operator.substring("fromSets(".length() + 1), "()\" ");
String[] sets = operator.split(",");
toAdd = IPaperCard.Predicates.printedInSets(sets);
} else if (operator.startsWith("fromSheet(") && invert) { } else if (operator.startsWith("fromSheet(") && invert) {
String sheetName = StringUtils.strip(operator.substring(9), "()\" "); String sheetName = StringUtils.strip(operator.substring(9), "()\" ");
Iterable<PaperCard> src = StaticData.instance().getPrintSheets().get(sheetName).toFlatList(); Iterable<PaperCard> src = StaticData.instance().getPrintSheets().get(sheetName).toFlatList();

View File

@@ -6,12 +6,12 @@
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -50,25 +50,25 @@ import java.util.Map.Entry;
* <p> * <p>
* CardSet class. * CardSet class.
* </p> * </p>
* *
* @author Forge * @author Forge
* @version $Id: CardSet.java 9708 2011-08-09 19:34:12Z jendave $ * @version $Id: CardSet.java 9708 2011-08-09 19:34:12Z jendave $
*/ */
public final class CardEdition implements Comparable<CardEdition> { // immutable public final class CardEdition implements Comparable<CardEdition> { // immutable
public enum Type { public enum Type {
UNKNOWN, UNKNOWN,
CORE, CORE,
EXPANSION, EXPANSION,
REPRINT, REPRINT,
ONLINE, ONLINE,
STARTER, STARTER,
DUEL_DECKS, DUEL_DECKS,
PREMIUM_DECK_SERIES, PREMIUM_DECK_SERIES,
FROM_THE_VAULT, FROM_THE_VAULT,
OTHER, OTHER,
THIRDPARTY // custom sets THIRDPARTY // custom sets
} }
@@ -78,7 +78,7 @@ public final class CardEdition implements Comparable<CardEdition> { // immutable
OLD_STYLE, // sets between Urza's Legacy and 8th Edition OLD_STYLE, // sets between Urza's Legacy and 8th Edition
MODERN // 8th Edition and newer MODERN // 8th Edition and newer
} }
public static class CardInSet { public static class CardInSet {
public final CardRarity rarity; public final CardRarity rarity;
public final String name; public final String name;
@@ -89,10 +89,10 @@ public final class CardEdition implements Comparable<CardEdition> { // immutable
} }
} }
/** The Constant unknown. */ /** The Constant unknown. */
private final static SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); private final static SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
public static final CardEdition UNKNOWN = new CardEdition("1990-01-01", "??", "???", Type.UNKNOWN, "Undefined", FoilType.NOT_SUPPORTED, new CardInSet[]{}); public static final CardEdition UNKNOWN = new CardEdition("1990-01-01", "??", "???", Type.UNKNOWN, "Undefined", FoilType.NOT_SUPPORTED, new CardInSet[]{});
private Date date; private Date date;
@@ -106,19 +106,19 @@ public final class CardEdition implements Comparable<CardEdition> { // immutable
private double foilChanceInBooster = 0; private double foilChanceInBooster = 0;
private boolean foilAlwaysInCommonSlot = false; private boolean foilAlwaysInCommonSlot = false;
private final CardInSet[] cards; private final CardInSet[] cards;
private int boosterArts = 1; private int boosterArts = 1;
private SealedProduct.Template boosterTpl = null; private SealedProduct.Template boosterTpl = null;
private CardEdition(CardInSet[] cards) { private CardEdition(CardInSet[] cards) {
this.cards = cards; this.cards = cards;
} }
/** /**
* Instantiates a new card set. * Instantiates a new card set.
* *
* @param index indicates order of set release date * @param date indicates order of set release date
* @param code2 the 2 (usually) letter code used for image filenames/URLs distributed by the HQ pics team that * @param code2 the 2 (usually) letter code used for image filenames/URLs distributed by the HQ pics team that
* use Magic Workstation-type edition codes. Older sets only had 2-letter codes, and some of the 3-letter * use Magic Workstation-type edition codes. Older sets only had 2-letter codes, and some of the 3-letter
* codes they use now aren't the same as the official list of 3-letter codes. When Forge downloads set-pics, * codes they use now aren't the same as the official list of 3-letter codes. When Forge downloads set-pics,
@@ -126,7 +126,7 @@ public final class CardEdition implements Comparable<CardEdition> { // immutable
* @param code the MTG 3-letter set code * @param code the MTG 3-letter set code
* @param type the set type * @param type the set type
* @param name the name of the set * @param name the name of the set
* @param an optional secondary code alias for the set * @param cards the cards in the set
*/ */
private CardEdition(String date, String code2, String code, Type type, String name, FoilType foil, CardInSet[] cards) { private CardEdition(String date, String code2, String code, Type type, String name, FoilType foil, CardInSet[] cards) {
this(cards); this(cards);
@@ -137,9 +137,9 @@ public final class CardEdition implements Comparable<CardEdition> { // immutable
this.date = parseDate(date); this.date = parseDate(date);
this.foilType = foil; this.foilType = foil;
} }
private static Date parseDate(String date) { private static Date parseDate(String date) {
if( date.length() <= 7 ) if( date.length() <= 7 )
date = date + "-01"; date = date + "-01";
try { try {
return formatter.parse(date); return formatter.parse(date);
@@ -220,19 +220,17 @@ public final class CardEdition implements Comparable<CardEdition> { // immutable
public boolean hasBoosterTemplate() { public boolean hasBoosterTemplate() {
return boosterTpl != null; return boosterTpl != null;
} }
public static class Reader extends StorageReaderFolder<CardEdition> { public static class Reader extends StorageReaderFolder<CardEdition> {
public Reader(File path) { public Reader(File path) {
super(path, CardEdition.FN_GET_CODE); super(path, CardEdition.FN_GET_CODE);
} }
public final static CardInSet[] arrCards = new CardInSet[] {};
@Override @Override
protected CardEdition read(File file) { protected CardEdition read(File file) {
final Map<String, List<String>> contents = FileSection.parseSections(FileUtil.readFile(file)); final Map<String, List<String>> contents = FileSection.parseSections(FileUtil.readFile(file));
List<CardEdition.CardInSet> processedCards = new ArrayList<CardEdition.CardInSet>(); List<CardEdition.CardInSet> processedCards = new ArrayList<>();
for(String line : contents.get("cards")) { for(String line : contents.get("cards")) {
if (StringUtils.isBlank(line)) if (StringUtils.isBlank(line))
continue; continue;
@@ -240,26 +238,26 @@ public final class CardEdition implements Comparable<CardEdition> { // immutable
// You may omit rarity for early development // You may omit rarity for early development
CardRarity r = CardRarity.smartValueOf(line.substring(0, 1)); CardRarity r = CardRarity.smartValueOf(line.substring(0, 1));
boolean hadRarity = r != CardRarity.Unknown && line.charAt(1) == ' '; boolean hadRarity = r != CardRarity.Unknown && line.charAt(1) == ' ';
String cardName = hadRarity ? line.substring(2) : line; String cardName = hadRarity ? line.substring(2) : line;
CardInSet cis = new CardInSet(cardName, r); CardInSet cis = new CardInSet(cardName, r);
processedCards.add(cis); processedCards.add(cis);
} }
CardEdition res = new CardEdition(processedCards.toArray(arrCards)); CardEdition res = new CardEdition(processedCards.toArray(new CardInSet[processedCards.size()]));
FileSection section = FileSection.parse(contents.get("metadata"), "="); FileSection section = FileSection.parse(contents.get("metadata"), "=");
res.name = section.get("name"); res.name = section.get("name");
res.date = parseDate(section.get("date")); res.date = parseDate(section.get("date"));
res.code = section.get("code"); res.code = section.get("code");
res.code2 = section.get("code2"); res.code2 = section.get("code2");
if( res.code2 == null ) if (res.code2 == null) {
res.code2 = res.code; res.code2 = res.code;
}
res.boosterArts = section.getInt("BoosterCovers", 1); res.boosterArts = section.getInt("BoosterCovers", 1);
String boosterDesc = section.get("Booster"); String boosterDesc = section.get("Booster");
res.boosterTpl = boosterDesc == null ? null : new SealedProduct.Template(res.code, SealedProduct.Template.Reader.parseSlots(boosterDesc)); res.boosterTpl = boosterDesc == null ? null : new SealedProduct.Template(res.code, SealedProduct.Template.Reader.parseSlots(boosterDesc));
res.alias = section.get("alias"); res.alias = section.get("alias");
res.whiteBorder = "white".equalsIgnoreCase(section.get("border")); res.whiteBorder = "white".equalsIgnoreCase(section.get("border"));
String type = section.get("type"); String type = section.get("type");
@@ -267,7 +265,7 @@ public final class CardEdition implements Comparable<CardEdition> { // immutable
if (null != type && !type.isEmpty()) { if (null != type && !type.isEmpty()) {
try { try {
enumType = Type.valueOf(type.toUpperCase(Locale.ENGLISH)); enumType = Type.valueOf(type.toUpperCase(Locale.ENGLISH));
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException ignored) {
// ignore; type will get UNKNOWN // ignore; type will get UNKNOWN
System.err.println(String.format("Ignoring unknown type in set definitions: name: %s; type: %s", res.name, type)); System.err.println(String.format("Ignoring unknown type in set definitions: name: %s; type: %s", res.name, type));
} }
@@ -292,7 +290,7 @@ public final class CardEdition implements Comparable<CardEdition> { // immutable
} }
res.foilChanceInBooster = section.getDouble("FoilChanceInBooster", 21.43F) / 100.0F; res.foilChanceInBooster = section.getDouble("FoilChanceInBooster", 21.43F) / 100.0F;
res.foilAlwaysInCommonSlot = section.getBoolean("FoilAlwaysInCommonSlot", true); res.foilAlwaysInCommonSlot = section.getBoolean("FoilAlwaysInCommonSlot", true);
return res; return res;
} }
@@ -312,7 +310,7 @@ public final class CardEdition implements Comparable<CardEdition> { // immutable
public static class Collection extends StorageBase<CardEdition> { public static class Collection extends StorageBase<CardEdition> {
private final Map<String, CardEdition> aliasToEdition = new TreeMap<String, CardEdition>(String.CASE_INSENSITIVE_ORDER); private final Map<String, CardEdition> aliasToEdition = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
public Collection(IItemReader<CardEdition> reader) { public Collection(IItemReader<CardEdition> reader) {
super("Card editions", reader); super("Card editions", reader);
@@ -328,7 +326,7 @@ public final class CardEdition implements Comparable<CardEdition> { // immutable
/** /**
* Gets a sets by code. It will search first by three letter codes, then by aliases and two-letter codes. * Gets a sets by code. It will search first by three letter codes, then by aliases and two-letter codes.
* *
* @param code * @param code
* the code * the code
* @return the sets the by code * @return the sets the by code
@@ -342,9 +340,7 @@ public final class CardEdition implements Comparable<CardEdition> { // immutable
CardEdition baseResult = super.get(code); CardEdition baseResult = super.get(code);
return baseResult == null ? aliasToEdition.get(code) : baseResult; return baseResult == null ? aliasToEdition.get(code) : baseResult;
} }
public Iterable<CardEdition> getOrderedEditions() { public Iterable<CardEdition> getOrderedEditions() {
List<CardEdition> res = Lists.newArrayList(this); List<CardEdition> res = Lists.newArrayList(this);
Collections.sort(res); Collections.sort(res);
@@ -354,7 +350,7 @@ public final class CardEdition implements Comparable<CardEdition> { // immutable
/** /**
* Gets the sets by code or throw. * Gets the sets by code or throw.
* *
* @param code * @param code
* the code * the code
* @return the sets the by code or throw * @return the sets the by code or throw
@@ -370,7 +366,7 @@ public final class CardEdition implements Comparable<CardEdition> { // immutable
// used by image generating code // used by image generating code
/** /**
* Gets the code2 by code. * Gets the code2 by code.
* *
* @param code * @param code
* the code * the code
* @return the code2 by code * @return the code2 by code
@@ -384,38 +380,38 @@ public final class CardEdition implements Comparable<CardEdition> { // immutable
@Override @Override
public CardEdition apply(String code) { public CardEdition apply(String code) {
return Collection.this.get(code); return Collection.this.get(code);
}; }
}; };
/** /**
* TODO: Write javadoc for this method. * TODO: Write javadoc for this method.
* @return * @return ItemReader<SealedProduct.Template>
*/ */
public IItemReader<SealedProduct.Template> getBoosterGenerator() { public IItemReader<SealedProduct.Template> getBoosterGenerator() {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return new StorageReaderBase<SealedProduct.Template>(null) { return new StorageReaderBase<SealedProduct.Template>(null) {
@Override @Override
public Map<String, SealedProduct.Template> readAll() { public Map<String, SealedProduct.Template> readAll() {
Map<String, SealedProduct.Template> map = new TreeMap<String, SealedProduct.Template>(String.CASE_INSENSITIVE_ORDER); Map<String, SealedProduct.Template> map = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
for(CardEdition ce : Collection.this) { for(CardEdition ce : Collection.this) {
map.put(ce.getCode(), ce.getBoosterTemplate()); map.put(ce.getCode(), ce.getBoosterTemplate());
} }
return map; return map;
} }
@Override @Override
public String getItemKey(SealedProduct.Template item) { public String getItemKey(SealedProduct.Template item) {
return item.getEdition(); return item.getEdition();
} }
}; };
} }
public CardEdition getEarliestEditionWithAllCards(CardPool cards) { public CardEdition getEarliestEditionWithAllCards(CardPool cards) {
Set<String> minEditions = new HashSet<String>(); Set<String> minEditions = new HashSet<>();
SetPreference strictness = SetPreference.EarliestCoreExp; SetPreference strictness = SetPreference.EarliestCoreExp;
for(Entry<PaperCard, Integer> k : cards) { for(Entry<PaperCard, Integer> k : cards) {
PaperCard cp = StaticData.instance().getCommonCards().getCardFromEdition(k.getKey().getName(), strictness); PaperCard cp = StaticData.instance().getCommonCards().getCardFromEdition(k.getKey().getName(), strictness);
if( cp == null && strictness == SetPreference.EarliestCoreExp) { if( cp == null && strictness == SetPreference.EarliestCoreExp) {
@@ -424,14 +420,14 @@ public final class CardEdition implements Comparable<CardEdition> { // immutable
} }
if ( cp == null ) if ( cp == null )
cp = k.getKey(); // it's unlikely, this code will ever run cp = k.getKey(); // it's unlikely, this code will ever run
minEditions.add(cp.getEdition()); minEditions.add(cp.getEdition());
} }
for(CardEdition ed : getOrderedEditions()) { for(CardEdition ed : getOrderedEditions()) {
if(minEditions.contains(ed.getCode())) if(minEditions.contains(ed.getCode()))
return ed; return ed;
} }
return UNKNOWN; return UNKNOWN;
} }
} }
@@ -448,10 +444,10 @@ public final class CardEdition implements Comparable<CardEdition> { // immutable
} }
public final static CardEdition getRandomSetWithAllBasicLands(Iterable<CardEdition> allEditions) { public static CardEdition getRandomSetWithAllBasicLands(Iterable<CardEdition> allEditions) {
return Aggregates.random(Iterables.filter(allEditions, hasBasicLands)); return Aggregates.random(Iterables.filter(allEditions, hasBasicLands));
} }
public static final Predicate<CardEdition> HAS_TOURNAMENT_PACK = new CanMakeStarter(); public static final Predicate<CardEdition> HAS_TOURNAMENT_PACK = new CanMakeStarter();
private static class CanMakeStarter implements Predicate<CardEdition> { private static class CanMakeStarter implements Predicate<CardEdition> {
@Override @Override
@@ -485,7 +481,7 @@ public final class CardEdition implements Comparable<CardEdition> { // immutable
return false; return false;
} }
return true; return true;
}; }
}; };
} }

View File

@@ -5,11 +5,11 @@ import forge.item.PaperCard;
import java.util.List; import java.util.List;
/** /**
* TODO: Write javadoc for this type. * TODO: Write javadoc for this type.
* *
*/ */
public interface IUnOpenedProduct extends Supplier<List<PaperCard>> { public interface IUnOpenedProduct extends Supplier<List<PaperCard>> {
public List<PaperCard> get(); List<PaperCard> get();
} }

View File

@@ -6,12 +6,12 @@
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -19,9 +19,12 @@
package forge.item; package forge.item;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import forge.StaticData; import forge.StaticData;
import forge.card.BoosterSlots;
import forge.card.CardEdition; import forge.card.CardEdition;
import forge.util.MyRandom; import forge.util.MyRandom;
import org.apache.commons.lang3.tuple.Pair;
public class BoosterPack extends SealedProduct { public class BoosterPack extends SealedProduct {
private final int artIndex; private final int artIndex;
@@ -35,11 +38,30 @@ public class BoosterPack extends SealedProduct {
} }
}; };
public static final Function<String, BoosterPack> FN_FROM_COLOR = new Function<String, BoosterPack>() {
@Override
public BoosterPack apply(final String color) {
return new BoosterPack(color, new Template("?", ImmutableList.of(
Pair.of(BoosterSlots.COMMON + ":color(\"" + color + "\"):!" + BoosterSlots.LAND, 11),
Pair.of(BoosterSlots.UNCOMMON + ":color(\"" + color + "\"):!" + BoosterSlots.LAND, 3),
Pair.of(BoosterSlots.RARE_MYTHIC + ":color(\"" + color + "\"):!" + BoosterSlots.LAND, 1),
Pair.of(BoosterSlots.LAND + ":color(\"" + color + "\")", 1))
));
}
};
public BoosterPack(final String name0, final Template boosterData) { public BoosterPack(final String name0, final Template boosterData) {
super(name0, boosterData); super(name0, boosterData);
int maxIdx = StaticData.instance().getEditions().get(boosterData.getEdition()).getCntBoosterPictures();
artIndex = MyRandom.getRandom().nextInt(maxIdx) + 1; if (specialSets.contains(boosterData.getEdition()) || boosterData.getEdition().equals("?")) {
hash = super.hashCode() ^ artIndex; artIndex = 1;
} else {
int maxIdx = StaticData.instance().getEditions().get(boosterData.getEdition()).getCntBoosterPictures();
artIndex = MyRandom.getRandom().nextInt(maxIdx) + 1;
}
hash = super.hashCode() ^ artIndex;
} }
public final int getArtIndex() { public final int getArtIndex() {
@@ -51,24 +73,32 @@ public class BoosterPack extends SealedProduct {
return "Booster Pack"; return "Booster Pack";
} }
@Override
public String getDescription() {
if (specialSets.contains(getEdition()) || getEdition().equals("?")) {
String color = getName().substring(0, getName().indexOf(getItemType()) - 1).toLowerCase();
return "11 " + color + " commons, 3 " + color + " uncommons, 1 " + color + " rare, and 1 " + color + " land.";
}
return super.getDescription();
}
@Override @Override
public final Object clone() { public final Object clone() {
return new BoosterPack(name, contents); return new BoosterPack(name, contents);
} }
public Template getBoosterData() { public Template getBoosterData() {
return contents; return contents;
} }
@Override @Override
public boolean equals(Object obj) { public boolean equals(final Object o) {
if (this == obj) { if (this == o) return true;
return true; if (o == null || getClass() != o.getClass()) return false;
} if (!super.equals(o)) return false;
if (!super.equals(obj)) {
return false; BoosterPack other = (BoosterPack) o;
}
BoosterPack other = (BoosterPack)obj;
return artIndex == other.artIndex; return artIndex == other.artIndex;
} }

View File

@@ -4,6 +4,8 @@ import com.google.common.base.Predicate;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import forge.card.CardRarity; import forge.card.CardRarity;
import forge.card.CardRules; import forge.card.CardRules;
import forge.card.CardType.CoreType;
import forge.card.MagicColor;
import forge.util.PredicateString; import forge.util.PredicateString;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@@ -18,88 +20,130 @@ public interface IPaperCard extends InventoryItem {
/** /**
* Number of filters based on CardPrinted values. * Number of filters based on CardPrinted values.
*/ */
public abstract static class Predicates { abstract class Predicates {
public static Predicate<PaperCard> rarity(final boolean isEqual, final CardRarity value) { public static Predicate<PaperCard> rarity(final boolean isEqual, final CardRarity value) {
return new PredicateRarity(value, isEqual); return new PredicateRarity(value, isEqual);
} }
public static Predicate<PaperCard> color(final boolean isEqual, final boolean noColor, final byte value) {
return new PredicateColor(value, noColor, isEqual);
}
public static Predicate<PaperCard> printedInSets(final String[] sets) { public static Predicate<PaperCard> printedInSets(final String[] sets) {
return printedInSets(Lists.newArrayList(sets), true); return printedInSets(Lists.newArrayList(sets), true);
} }
public static Predicate<PaperCard> printedInSets(final List<String> value, final boolean shouldContain) { public static Predicate<PaperCard> printedInSets(final List<String> value, final boolean shouldContain) {
if ((value == null) || value.isEmpty()) { if ((value == null) || value.isEmpty()) {
return com.google.common.base.Predicates.alwaysTrue(); return com.google.common.base.Predicates.alwaysTrue();
} }
return new PredicateSets(value, shouldContain); return new PredicateSets(value, shouldContain);
} }
public static Predicate<PaperCard> printedInSet(final String value) { public static Predicate<PaperCard> printedInSet(final String value) {
if (StringUtils.isEmpty(value)) { if (StringUtils.isEmpty(value)) {
return com.google.common.base.Predicates.alwaysTrue(); return com.google.common.base.Predicates.alwaysTrue();
} }
return new PredicateSets(Lists.newArrayList(value), true); return new PredicateSets(Lists.newArrayList(value), true);
} }
public static Predicate<PaperCard> name(final String what) { public static Predicate<PaperCard> name(final String what) {
return new PredicateName(PredicateString.StringOp.EQUALS_IC, what); return new PredicateName(PredicateString.StringOp.EQUALS_IC, what);
} }
public static Predicate<PaperCard> name(final PredicateString.StringOp op, final String what) { public static Predicate<PaperCard> name(final PredicateString.StringOp op, final String what) {
return new PredicateName(op, what); return new PredicateName(op, what);
} }
public static Predicate<PaperCard> names(final List<String> what) { public static Predicate<PaperCard> names(final List<String> what) {
return new PredicateNames(what); return new PredicateNames(what);
} }
private static class PredicateRarity implements Predicate<PaperCard> { private static final class PredicateColor implements Predicate<PaperCard> {
private final byte operand;
private final boolean noColor;
private final boolean shouldBeEqual;
private PredicateColor(final byte color, final boolean noColor, final boolean wantEqual) {
this.operand = color;
this.noColor = noColor;
this.shouldBeEqual = wantEqual;
}
@Override
public boolean apply(final PaperCard card) {
boolean colorFound = false;
if (noColor) {
return card.getRules().getColor().isColorless() == shouldBeEqual;
}
for (final byte color : card.getRules().getColor()) {
if (color == operand) {
colorFound = true;
break;
}
}
if (card.getRules().getType().hasType(CoreType.Land)) {
for (final byte color : card.getRules().getColorIdentity()) {
if (color == operand) {
colorFound = true;
break;
}
}
}
return colorFound == shouldBeEqual;
}
}
private static final class PredicateRarity implements Predicate<PaperCard> {
private final CardRarity operand; private final CardRarity operand;
private final boolean shouldBeEqual; private final boolean shouldBeEqual;
@Override @Override
public boolean apply(final PaperCard card) { public boolean apply(final PaperCard card) {
return (card.getRarity() == this.operand) == this.shouldBeEqual; return (card.getRarity() == this.operand) == this.shouldBeEqual;
} }
public PredicateRarity(final CardRarity type, final boolean wantEqual) { private PredicateRarity(final CardRarity type, final boolean wantEqual) {
this.operand = type; this.operand = type;
this.shouldBeEqual = wantEqual; this.shouldBeEqual = wantEqual;
} }
} }
private static class PredicateSets implements Predicate<PaperCard> { private static final class PredicateSets implements Predicate<PaperCard> {
private final Set<String> sets; private final Set<String> sets;
private final boolean mustContain; private final boolean mustContain;
@Override @Override
public boolean apply(final PaperCard card) { public boolean apply(final PaperCard card) {
return this.sets.contains(card.getEdition()) == this.mustContain; return this.sets.contains(card.getEdition()) == this.mustContain;
} }
public PredicateSets(final List<String> wantSets, final boolean shouldContain) { private PredicateSets(final List<String> wantSets, final boolean shouldContain) {
this.sets = new HashSet<String>(wantSets); this.sets = new HashSet<>(wantSets);
this.mustContain = shouldContain; this.mustContain = shouldContain;
} }
} }
private static class PredicateName extends PredicateString<PaperCard> { private static final class PredicateName extends PredicateString<PaperCard> {
private final String operand; private final String operand;
@Override @Override
public boolean apply(final PaperCard card) { public boolean apply(final PaperCard card) {
return this.op(card.getName(), this.operand); return this.op(card.getName(), this.operand);
} }
public PredicateName(final PredicateString.StringOp operator, final String operand) { private PredicateName(final PredicateString.StringOp operator, final String operand) {
super(operator); super(operator);
this.operand = operand; this.operand = operand;
} }
} }
private static class PredicateNames extends PredicateString<PaperCard> { private static final class PredicateNames extends PredicateString<PaperCard> {
private final List<String> operand; private final List<String> operand;
@Override @Override
public boolean apply(final PaperCard card) { public boolean apply(final PaperCard card) {
final String cardName = card.getName(); final String cardName = card.getName();
@@ -110,13 +154,13 @@ public interface IPaperCard extends InventoryItem {
} }
return false; return false;
} }
public PredicateNames(final List<String> operand) { private PredicateNames(final List<String> operand) {
super(StringOp.EQUALS); super(StringOp.EQUALS);
this.operand = operand; this.operand = operand;
} }
} }
/** /**
* Pre-built predicates are stored here to allow their re-usage and * Pre-built predicates are stored here to allow their re-usage and
* easier access from code. * easier access from code.
@@ -126,37 +170,45 @@ public interface IPaperCard extends InventoryItem {
// card. // card.
/** The Constant isCommon. */ /** The Constant isCommon. */
public static final Predicate<PaperCard> IS_COMMON = Predicates.rarity(true, CardRarity.Common); public static final Predicate<PaperCard> IS_COMMON = Predicates.rarity(true, CardRarity.Common);
/** The Constant isUncommon. */ /** The Constant isUncommon. */
public static final Predicate<PaperCard> IS_UNCOMMON = Predicates.rarity(true, CardRarity.Uncommon); public static final Predicate<PaperCard> IS_UNCOMMON = Predicates.rarity(true, CardRarity.Uncommon);
/** The Constant isRare. */ /** The Constant isRare. */
public static final Predicate<PaperCard> IS_RARE = Predicates.rarity(true, CardRarity.Rare); public static final Predicate<PaperCard> IS_RARE = Predicates.rarity(true, CardRarity.Rare);
/** The Constant isMythicRare. */ /** The Constant isMythicRare. */
public static final Predicate<PaperCard> IS_MYTHIC_RARE = Predicates.rarity(true, CardRarity.MythicRare); public static final Predicate<PaperCard> IS_MYTHIC_RARE = Predicates.rarity(true, CardRarity.MythicRare);
/** The Constant isRareOrMythic. */ /** The Constant isRareOrMythic. */
public static final Predicate<PaperCard> IS_RARE_OR_MYTHIC = com.google.common.base.Predicates.or(Presets.IS_RARE, public static final Predicate<PaperCard> IS_RARE_OR_MYTHIC = com.google.common.base.Predicates.or(Presets.IS_RARE,
Presets.IS_MYTHIC_RARE); Presets.IS_MYTHIC_RARE);
/** The Constant isSpecial. */ /** The Constant isSpecial. */
public static final Predicate<PaperCard> IS_SPECIAL = Predicates.rarity(true, CardRarity.Special); public static final Predicate<PaperCard> IS_SPECIAL = Predicates.rarity(true, CardRarity.Special);
/** The Constant exceptLands. */ /** The Constant exceptLands. */
public static final Predicate<PaperCard> IS_BASIC_LAND = Predicates.rarity(true, CardRarity.BasicLand); public static final Predicate<PaperCard> IS_BASIC_LAND = Predicates.rarity(true, CardRarity.BasicLand);
public static final Predicate<PaperCard> IS_BLACK = Predicates.color(true, false, MagicColor.BLACK);
public static final Predicate<PaperCard> IS_BLUE = Predicates.color(true, false, MagicColor.BLUE);
public static final Predicate<PaperCard> IS_GREEN = Predicates.color(true, false, MagicColor.GREEN);
public static final Predicate<PaperCard> IS_RED = Predicates.color(true, false, MagicColor.RED);
public static final Predicate<PaperCard> IS_WHITE = Predicates.color(true, false, MagicColor.WHITE);
public static final Predicate<PaperCard> IS_COLORLESS = Predicates.color(true, true, MagicColor.COLORLESS);
} }
} }
public abstract String getName(); String getName();
public abstract String getEdition(); String getEdition();
public abstract int getArtIndex(); int getArtIndex();
public abstract boolean isFoil(); boolean isFoil();
public abstract boolean isToken(); boolean isToken();
public abstract CardRules getRules(); CardRules getRules();
public abstract CardRarity getRarity(); CardRarity getRarity();
public abstract String getItemType(); String getItemType();
} }

View File

@@ -6,12 +6,12 @@
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -38,11 +38,23 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
public abstract class SealedProduct implements InventoryItemFromSet { public abstract class SealedProduct implements InventoryItemFromSet {
public static final List<String> specialSets = new ArrayList<>();
protected final Template contents; protected final Template contents;
protected final String name; protected final String name;
private final int hash; private final int hash;
protected List<PaperCard> cards = null; protected List<PaperCard> cards = null;
static {
specialSets.add("Black");
specialSets.add("Blue");
specialSets.add("Green");
specialSets.add("Red");
specialSets.add("White");
specialSets.add("Colorless");
}
public SealedProduct(String name0, Template boosterData) { public SealedProduct(String name0, Template boosterData) {
if (null == name0) { throw new IllegalArgumentException("name0 must not be null"); } if (null == name0) { throw new IllegalArgumentException("name0 must not be null"); }
if (null == boosterData) { throw new IllegalArgumentException("boosterData must not be null"); } if (null == boosterData) { throw new IllegalArgumentException("boosterData must not be null"); }
@@ -59,37 +71,32 @@ public abstract class SealedProduct implements InventoryItemFromSet {
public String getDescription() { public String getDescription() {
return contents.toString(); return contents.toString();
} }
@Override @Override
public final String getEdition() { public final String getEdition() {
return contents.getEdition(); return contents.getEdition();
} }
public List<PaperCard> getCards() { public List<PaperCard> getCards() {
if (null == cards) { if (null == cards) {
cards = generate(); cards = generate();
} }
return cards; return cards;
} }
public int getTotalCards() { public int getTotalCards() {
return contents.getNumberOfCardsExpected(); return contents.getNumberOfCardsExpected();
} }
@Override @Override
public boolean equals(Object obj) { public boolean equals(final Object o) {
if (this == obj) { if (this == o) return true;
return true; if (o == null || getClass() != o.getClass()) return false;
}
if (obj == null) { SealedProduct other = (SealedProduct) o;
return false;
} return contents.equals(other.contents) && name.equals(other.name);
if (this.getClass() != obj.getClass()) {
return false;
}
SealedProduct other = (SealedProduct)obj;
return name.equals(other.name) && contents.equals(other.contents);
} }
@Override @Override
@@ -116,25 +123,23 @@ public abstract class SealedProduct implements InventoryItemFromSet {
Predicates.compose(CardRulesPredicates.Presets.IS_BASIC_LAND, PaperCard.FN_GET_RULES)); Predicates.compose(CardRulesPredicates.Presets.IS_BASIC_LAND, PaperCard.FN_GET_RULES));
return Aggregates.random(Iterables.filter(StaticData.instance().getCommonCards().getAllCards(), cardsRule), count); return Aggregates.random(Iterables.filter(StaticData.instance().getCommonCards().getAllCards(), cardsRule), count);
} }
public static class Template { public static class Template {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final static Template genericBooster = new Template(null, Lists.newArrayList( public final static Template genericBooster = new Template(null, Lists.newArrayList(
Pair.of(BoosterSlots.COMMON, 10), Pair.of(BoosterSlots.UNCOMMON, 3), Pair.of(BoosterSlots.COMMON, 10), Pair.of(BoosterSlots.UNCOMMON, 3),
Pair.of(BoosterSlots.RARE_MYTHIC, 1), Pair.of(BoosterSlots.BASIC_LAND, 1) Pair.of(BoosterSlots.RARE_MYTHIC, 1), Pair.of(BoosterSlots.BASIC_LAND, 1)
)); ));
protected final List<Pair<String, Integer>> slots; protected final List<Pair<String, Integer>> slots;
protected final String name; protected final String name;
public final List<Pair<String, Integer>> getSlots() { public final List<Pair<String, Integer>> getSlots() {
return slots; return slots;
} }
public final String getEdition() { public final String getEdition() {
return name; return name;
} }
@@ -142,75 +147,92 @@ public abstract class SealedProduct implements InventoryItemFromSet {
{ {
this(null, itrSlots); this(null, itrSlots);
} }
public Template(String name0, Iterable<Pair<String, Integer>> itrSlots) public Template(String name0, Iterable<Pair<String, Integer>> itrSlots)
{ {
slots = Lists.newArrayList(itrSlots); slots = Lists.newArrayList(itrSlots);
name = name0; name = name0;
} }
public Template(String code, String boosterDesc) { public Template(String code, String boosterDesc) {
this(code, Reader.parseSlots(boosterDesc)); this(code, Reader.parseSlots(boosterDesc));
} }
public int getNumberOfCardsExpected() { public int getNumberOfCardsExpected() {
int sum = 0; int sum = 0;
for(Pair<String, Integer> p : slots) { for(Pair<String, Integer> p : slots) {
sum += p.getRight().intValue(); sum += p.getRight();
} }
return sum; return sum;
} }
public static final Function<? super Template, String> FN_GET_NAME = new Function<Template, String>() { public static final Function<? super Template, String> FN_GET_NAME = new Function<Template, String>() {
@Override @Override
public String apply(Template arg1) { public String apply(Template arg1) {
return arg1.name; return arg1.name;
} }
}; };
@Override @Override
public String toString() { public String toString() {
StringBuilder s = new StringBuilder(); StringBuilder s = new StringBuilder();
s.append("consisting of "); s.append("consisting of ");
for(Pair<String, Integer> p : slots) { for(Pair<String, Integer> p : slots) {
s.append(p.getRight()).append(" ").append(p.getLeft()).append(", "); s.append(p.getRight()).append(" ").append(p.getLeft()).append(", ");
} }
// trim the last comma and space // trim the last comma and space
s.replace(s.length() - 2, s.length(), ""); s.replace(s.length() - 2, s.length(), "");
// put an 'and' before the previous comma // put an 'and' before the previous comma
int lastCommaIdx = s.lastIndexOf(","); int lastCommaIdx = s.lastIndexOf(",");
if (0 < lastCommaIdx) { if (0 < lastCommaIdx) {
s.replace(lastCommaIdx+1, lastCommaIdx+1, " and"); s.replace(lastCommaIdx+1, lastCommaIdx+1, " and");
} }
return s.toString(); return s.toString();
} }
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Template template = (Template) o;
return slots.equals(template.slots) && name.equals(template.name);
}
@Override
public int hashCode() {
int result = slots.hashCode();
result = 31 * result + name.hashCode();
return result;
}
public final static class Reader extends StorageReaderFile<Template> { public final static class Reader extends StorageReaderFile<Template> {
public Reader(File file) { public Reader(File file) {
super(file, Template.FN_GET_NAME); super(file, Template.FN_GET_NAME);
} }
public static List<Pair<String, Integer>> parseSlots(String data) { public static List<Pair<String, Integer>> parseSlots(String data) {
final String[] dataz = TextUtil.splitWithParenthesis(data, ','); final String[] dataz = TextUtil.splitWithParenthesis(data, ',');
List<Pair<String, Integer>> slots = new ArrayList<Pair<String,Integer>>(); List<Pair<String, Integer>> slots = new ArrayList<>();
for(String slotDesc : dataz) { for(String slotDesc : dataz) {
String[] kv = TextUtil.splitWithParenthesis(slotDesc, ' ', 2); String[] kv = TextUtil.splitWithParenthesis(slotDesc, ' ', 2);
slots.add(ImmutablePair.of(kv[1], Integer.parseInt(kv[0]))); slots.add(ImmutablePair.of(kv[1], Integer.parseInt(kv[0])));
} }
return slots; return slots;
} }
@Override @Override
protected Template read(String line, int i) { protected Template read(String line, int i) {
String[] headAndData = TextUtil.split(line, ':', 2); String[] headAndData = TextUtil.split(line, ':', 2);
return new Template(headAndData[0], parseSlots(headAndData[1])); return new Template(headAndData[0], parseSlots(headAndData[1]));
} }
} }
} }
} }

View File

@@ -340,6 +340,11 @@ public enum VSubmenuQuestPrefs implements IVSubmenu<CSubmenuQuestPrefs> {
pnlBooster.add(new FLabel.Builder().text("Rare").fontAlign(SwingConstants.RIGHT).build(), labelConstraints); pnlBooster.add(new FLabel.Builder().text("Rare").fontAlign(SwingConstants.RIGHT).build(), labelConstraints);
pnlBooster.add(new PrefInput(QPref.BOOSTER_RARES, QuestPreferencesErrType.BOOSTER), fieldConstraints); pnlBooster.add(new PrefInput(QPref.BOOSTER_RARES, QuestPreferencesErrType.BOOSTER), fieldConstraints);
FLabel specialBoosters = new FLabel.Builder().text("Special Boosters").fontAlign(SwingConstants.RIGHT).build();
specialBoosters.setToolTipText("Allows special, color-specific boosters to appear in the shop and as match rewards.");
pnlBooster.add(specialBoosters, labelConstraints);
pnlBooster.add(new PrefInput(QPref.SPECIAL_BOOSTERS, QuestPreferencesErrType.BOOSTER), fieldConstraints);
} }
private void populateShop() { private void populateShop() {

View File

@@ -73,6 +73,7 @@ public class QuestPrefsScreen extends FScreen {
scroller.add(new PrefsOption("Common", QPref.BOOSTER_COMMONS, PrefsGroup.BOOSTER)); scroller.add(new PrefsOption("Common", QPref.BOOSTER_COMMONS, PrefsGroup.BOOSTER));
scroller.add(new PrefsOption("Uncommon", QPref.BOOSTER_UNCOMMONS, PrefsGroup.BOOSTER)); scroller.add(new PrefsOption("Uncommon", QPref.BOOSTER_UNCOMMONS, PrefsGroup.BOOSTER));
scroller.add(new PrefsOption("Rare", QPref.BOOSTER_RARES, PrefsGroup.BOOSTER)); scroller.add(new PrefsOption("Rare", QPref.BOOSTER_RARES, PrefsGroup.BOOSTER));
scroller.add(new PrefsOption("Special Boosters", QPref.SPECIAL_BOOSTERS, PrefsGroup.BOOSTER));
//Shop Preferences //Shop Preferences
scroller.add(new PrefsHeader("Shop Preferences", FSkinImage.QUEST_COIN, PrefsGroup.SHOP)); scroller.add(new PrefsHeader("Shop Preferences", FSkinImage.QUEST_COIN, PrefsGroup.SHOP));

View File

@@ -8,11 +8,18 @@ Forge Beta: 65-2015 ver 1.5.41
Release Notes Release Notes
------------- -------------
- Special Quest Booster Packs -
New booster packs have been added to quest mode that contain cards of a single
color. Blue Booster Packs will contain only blue cards, White Booster Packs
will contain only white cards, and so on. There's a pack for each color and
these new packs can be disabled by setting the "Special Boosters" quest
preference to "0".
- Updated Forge Content Downloads - - Updated Forge Content Downloads -
Card images for the latest sets are now available for download, including Card images for the latest sets are now available for download, including
Tempest Remastered and Modern Masters 2015. All images have also been moved to a Tempest Remastered and Modern Masters 2015. All images have also been moved to a
new server for increased reliability and performance and many previously new server for increased reliability and performance and many previously
missing images have been added. There are still a few images missing in Forge missing images have been added. There are still a few images missing in Forge
and rectifying that is an ongoing effort. and rectifying that is an ongoing effort.
@@ -40,12 +47,12 @@ The interface has received several small changes.
- Display Color Identity - - Display Color Identity -
There's a new option "Display Color Identity" in both desktop and mobile Forge There's a new option "Display Color Identity" in both desktop and mobile Forge
that allows you to display the current color identity of cards. It's disabled that allows you to display the current color identity of cards. It's disabled
by default (set to "Never") but can be toggled to "Always" (which displays color by default (set to "Never") but can be toggled to "Always" (which displays color
identity for all cards, even mono-color), to "Changed" (which displays color identity for all cards, even mono-color), to "Changed" (which displays color
identity of all cards whose color identity has been altered compared to its identity of all cards whose color identity has been altered compared to its
"pristine" state), to "Multicolor" (which only displays color identity of cards "pristine" state), to "Multicolor" (which only displays color identity of cards
that are currently of two or more colors) or to "Multi+Changed" (which displays that are currently of two or more colors) or to "Multi+Changed" (which displays
color identity of all multicolor cards and also of all cards the identity of color identity of all multicolor cards and also of all cards the identity of
which has changed). This might help with effects such as Painter's Servant which which has changed). This might help with effects such as Painter's Servant which
@@ -58,12 +65,12 @@ term that is not equivalent to the sum of card colors).
- New Quest Preferences - - New Quest Preferences -
Three new quest preferences (Playset Size: Basic Lands, Playset Size: Any Three new quest preferences (Playset Size: Basic Lands, Playset Size: Any
Number, and Playset Size) have been added to control the number of cards to keep Number, and Playset Size) have been added to control the number of cards to keep
before selling extras in quest mode. One is for basic lands, one is for before selling extras in quest mode. One is for basic lands, one is for
"unlimited" cards (Relentless Rats and Shadowborn Apostle), and the last one is "unlimited" cards (Relentless Rats and Shadowborn Apostle), and the last one is
for all other cards. This is mostly useful when playing for antes and you want for all other cards. This is mostly useful when playing for antes and you want
to keep an extra couple of cards on hand, just in case, or if you want to keep to keep an extra couple of cards on hand, just in case, or if you want to keep
fewer copies of basic lands around. fewer copies of basic lands around.
@@ -72,7 +79,7 @@ By default the game now displays tokens on the same row as non-token cards (and
to the right of them), which makes the game use the battlefield space more to the right of them), which makes the game use the battlefield space more
effectively. For example, creature tokens are displayed to the right of regular effectively. For example, creature tokens are displayed to the right of regular
non-token creatures in the same row. If you prefer the classic Forge behavior non-token creatures in the same row. If you prefer the classic Forge behavior
(when tokens are displayed on their own row), the option that controls this (when tokens are displayed on their own row), the option that controls this
behavior can be found in Forge preferences under "Graphic Options". It is called behavior can be found in Forge preferences under "Graphic Options". It is called
"Display Tokens in a Separate Row". "Display Tokens in a Separate Row".
@@ -95,28 +102,13 @@ longer considered unless they can be produced by a land in the deck
When filtering colors in the Deck Editor, lands that produce all selected colors will now be shown When filtering colors in the Deck Editor, lands that produce all selected colors will now be shown
This means if you filter to show only green and white cards, lands that produce green and white will now be shown This means if you filter to show only green and white cards, lands that produce green and white will now be shown
This should hopefully make finding multicolor lands for your decks easier. This should hopefully make finding multicolor lands for your decks easier.
An attempt was made to make this option behave in a more consistent and helpful way - now lands won't suddenly An attempt was made to make this option behave in a more consistent and helpful way - now lands won't suddenly
disappear when one color is filtered out, basic lands of appropriate colors will be shown, lands that feature at disappear when one color is filtered out, basic lands of appropriate colors will be shown, lands that feature at
least one of the colors relevant for the deck will be shown. Also, the mode to filter lands in this way is now least one of the colors relevant for the deck will be shown. Also, the mode to filter lands in this way is now
optional and can be toggled on or off in the Preferences ("Filter Lands by Color in Activated Abilities" under optional and can be toggled on or off in the Preferences ("Filter Lands by Color in Activated Abilities" under
"Deck Editor Options"). "Deck Editor Options").
- Quest Starting Pool Configuration -
When starting a new quest, you now have many more options to configure your starting pool. Instead of just picking a
single color, you can pick any combination of them, including colorless. There's also the option to include artifacts in
the pool alongside your colored cards or not.
The "color bias" option in the quest settings is now the percentage of your generated card pool that will contain the
settings you've selected. For example, if you picked Green cards and a color bias of 75, your card pool would be 75%
green, 25% all other colors.
Finally, there's three settings to choose your color distribution. "Balanced" maintains an equal balance between your
selected colors. "Random" completely randomizes the pool and makes only miniscule attempts to control the cards you get.
"Surprise Me" is much like "Balanced", except it will pick all your settings for you and not tell you what they were!
The New/Load quest menu has been given a small facelift to accommodate these changes and make it easier to read.
You will need to update your color bias quest setting as the values are now much too low.
--------- ---------
New Cards New Cards
--------- ---------
@@ -144,7 +136,7 @@ Known Issues
------------ ------------
- Dragon Presence cards from DTK - - Dragon Presence cards from DTK -
Work has started on the Dragon Presence cards. These cards should typically work on their own merits, but a few corner cases dealing with copying/cloning may not work as expected. As these cases are fairly limited, it was decided to add these cards for people to be able to use. Work has started on the Dragon Presence cards. These cards should typically work on their own merits, but a few corner cases dealing with copying/cloning may not work as expected. As these cases are fairly limited, it was decided to add these cards for people to be able to use.
- Dragons of Tarkir - - Dragons of Tarkir -
Forge now includes many of the new Dragons of Tarkir cards. It may take a few days/weeks before these new card pictures become available for downloading via the "Download LQ Card Pictures" button. The LQ set pictures tend to take a few more weeks/months to process before they become available for downloading via the "Download LQ Set Pictures" button. Please be patient. The Forge devs are not involved in maintaining the servers that house these pictures. Forge now includes many of the new Dragons of Tarkir cards. It may take a few days/weeks before these new card pictures become available for downloading via the "Download LQ Card Pictures" button. The LQ set pictures tend to take a few more weeks/months to process before they become available for downloading via the "Download LQ Set Pictures" button. Please be patient. The Forge devs are not involved in maintaining the servers that house these pictures.

View File

@@ -1,3 +1,9 @@
http://downloads.cardforge.link/images/products/boosters/Black.jpg
http://downloads.cardforge.link/images/products/boosters/Blue.jpg
http://downloads.cardforge.link/images/products/boosters/Colorless.jpg
http://downloads.cardforge.link/images/products/boosters/Green.jpg
http://downloads.cardforge.link/images/products/boosters/Red.jpg
http://downloads.cardforge.link/images/products/boosters/White.jpg
http://downloads.cardforge.link/images/products/boosters/10E_1.jpg http://downloads.cardforge.link/images/products/boosters/10E_1.jpg
http://downloads.cardforge.link/images/products/boosters/10E_2.jpg http://downloads.cardforge.link/images/products/boosters/10E_2.jpg
http://downloads.cardforge.link/images/products/boosters/10E_3.jpg http://downloads.cardforge.link/images/products/boosters/10E_3.jpg

View File

@@ -250,4 +250,10 @@ Journey into Nyx Fat Pack =2400
Magic 2015 Fat Pack =2400 Magic 2015 Fat Pack =2400
Magic 2013 Fat Pack =2400 Magic 2013 Fat Pack =2400
Magic 2014 Fat Pack =2400 Magic 2014 Fat Pack =2400
Khans of Tarkir Fat Pack =3200 Khans of Tarkir Fat Pack =3200
Black Booster Pack =600
Blue Booster Pack =600
Colorless Booster Pack =600
Green Booster Pack =600
Red Booster Pack =600
White Booster Pack =600

View File

@@ -186,6 +186,13 @@ public class QuestSpellShop {
SealedProduct booster = null; SealedProduct booster = null;
if (item instanceof BoosterPack) { if (item instanceof BoosterPack) {
booster = (BoosterPack) ((BoosterPack) item).clone(); booster = (BoosterPack) ((BoosterPack) item).clone();
//Replace the booster here if it's a special colored booster
//This is to ensure that the correct sets are included in the booster
//When loading a quest save, the set information is not available to the booster loader
if (SealedProduct.specialSets.contains(booster.getEdition()) || booster.getEdition().equals("?")) {
String color = booster.getName().substring(0, booster.getName().indexOf(booster.getItemType()) - 1);
booster = new BoosterPack(color, QuestUtilCards.getColoredBoosterTemplate(color));
}
} }
else if (item instanceof TournamentPack) { else if (item instanceof TournamentPack) {
booster = (TournamentPack) ((TournamentPack) item).clone(); booster = (TournamentPack) ((TournamentPack) item).clone();

View File

@@ -23,12 +23,12 @@ import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import forge.card.*; import forge.card.*;
import forge.deck.Deck; import forge.deck.Deck;
import forge.deck.DeckSection; import forge.deck.DeckSection;
import forge.game.GameFormat; import forge.game.GameFormat;
import forge.item.*; import forge.item.*;
import forge.item.SealedProduct.Template;
import forge.model.FModel; import forge.model.FModel;
import forge.properties.ForgePreferences.FPref; import forge.properties.ForgePreferences.FPref;
import forge.quest.bazaar.QuestItemType; import forge.quest.bazaar.QuestItemType;
@@ -40,7 +40,6 @@ import forge.quest.data.QuestPreferences.QPref;
import forge.util.Aggregates; import forge.util.Aggregates;
import forge.util.ItemPool; import forge.util.ItemPool;
import forge.util.MyRandom; import forge.util.MyRandom;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import java.util.ArrayList; import java.util.ArrayList;
@@ -538,6 +537,15 @@ public final class QuestUtilCards {
} }
this.qa.getShopList().add(BoosterPack.FN_FROM_SET.apply(Aggregates.random(rightEditions))); this.qa.getShopList().add(BoosterPack.FN_FROM_SET.apply(Aggregates.random(rightEditions)));
} }
if (qpref.getPrefInt(QPref.SPECIAL_BOOSTERS) == 1) {
for (String color : SealedProduct.specialSets) {
for (int i = 0; i < count; i++) {
this.qa.getShopList().add(new BoosterPack(color, getColoredBoosterTemplate(color)));
}
}
}
} }
/** /**
@@ -640,6 +648,37 @@ public final class QuestUtilCards {
)); ));
} }
public static SealedProduct.Template getColoredBoosterTemplate(final String color) {
if (FModel.getQuest().getFormat() == null) {
return new Template("?", ImmutableList.of(
Pair.of(BoosterSlots.COMMON + ":color(\"" + color + "\"):!" + BoosterSlots.LAND, 11),
Pair.of(BoosterSlots.UNCOMMON + ":color(\"" + color + "\"):!" + BoosterSlots.LAND, 3),
Pair.of(BoosterSlots.RARE_MYTHIC + ":color(\"" + color + "\"):!" + BoosterSlots.LAND, 1),
Pair.of(BoosterSlots.LAND + ":color(\"" + color + "\")", 1))
);
} else {
String restrictions = "";
List<String> allowedSetCodes = FModel.getQuest().getFormat().getAllowedSetCodes();
if (allowedSetCodes.isEmpty()) {
for (String restrictedCard : FModel.getQuest().getFormat().getRestrictedCards()) {
restrictions += ":!name(\"" + restrictedCard + "\")";
}
} else {
restrictions += ":fromSets(\"";
for (String set : allowedSetCodes) {
restrictions += set + ",";
}
restrictions += ")";
}
return new Template("?", ImmutableList.of(
Pair.of(BoosterSlots.COMMON + ":color(\"" + color + "\"):!" + BoosterSlots.LAND + restrictions, 11),
Pair.of(BoosterSlots.UNCOMMON + ":color(\"" + color + "\"):!" + BoosterSlots.LAND + restrictions, 3),
Pair.of(BoosterSlots.RARE_MYTHIC + ":color(\"" + color + "\"):!" + BoosterSlots.LAND + restrictions, 1),
Pair.of(BoosterSlots.LAND + ":color(\"" + color + "\")" + restrictions, 1))
);
}
}
/** /**
* Generate cards in shop. * Generate cards in shop.
*/ */
@@ -755,6 +794,17 @@ public final class QuestUtilCards {
} }
public int getCompletionPercent(String edition) { public int getCompletionPercent(String edition) {
for (String color : SealedProduct.specialSets) {
if (color.equals(edition)) {
return 0;
}
}
if (edition.equals("?")) {
return 0;
}
// get all cards in the specified edition // get all cards in the specified edition
Predicate<PaperCard> filter = IPaperCard.Predicates.printedInSet(edition); Predicate<PaperCard> filter = IPaperCard.Predicates.printedInSet(edition);
Iterable<PaperCard> editionCards = Iterables.filter(FModel.getMagicDb().getCommonCards().getAllCards(), filter); Iterable<PaperCard> editionCards = Iterables.filter(FModel.getMagicDb().getCommonCards().getAllCards(), filter);

View File

@@ -3,10 +3,7 @@ package forge.quest;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import forge.LobbyPlayer; import forge.LobbyPlayer;
import forge.assets.FSkinProp; import forge.assets.FSkinProp;
import forge.card.BoosterSlots; import forge.card.*;
import forge.card.CardEdition;
import forge.card.IUnOpenedProduct;
import forge.card.UnOpenedProduct;
import forge.game.GameEndReason; import forge.game.GameEndReason;
import forge.game.GameFormat; import forge.game.GameFormat;
import forge.game.GameOutcome; import forge.game.GameOutcome;
@@ -495,12 +492,13 @@ public class QuestWinLoseController {
String title; String title;
if (qData.getFormat() == null) { if (qData.getFormat() == null) {
final List<GameFormat> formats = new ArrayList<>(); //final List<GameFormat> formats = new ArrayList<>();
final List<String> formats = new ArrayList<>();
final String preferredFormat = FModel.getQuestPreferences().getPref(QPref.BOOSTER_FORMAT); final String preferredFormat = FModel.getQuestPreferences().getPref(QPref.BOOSTER_FORMAT);
GameFormat pref = null; GameFormat pref = null;
for (final GameFormat f : FModel.getFormats().getOrderedList()) { for (final GameFormat f : FModel.getFormats().getOrderedList()) {
formats.add(f); formats.add(f.toString());
if (f.toString().equals(preferredFormat)) { if (f.toString().equals(preferredFormat)) {
pref = f; pref = f;
} }
@@ -508,14 +506,40 @@ public class QuestWinLoseController {
Collections.sort(formats); Collections.sort(formats);
final GameFormat selected = SGuiChoose.getChoices("Choose bonus booster format", 1, 1, formats, pref, null).get(0); formats.addAll(SealedProduct.specialSets);
FModel.getQuestPreferences().setPref(QPref.BOOSTER_FORMAT, selected.toString());
String preferredSelection = null;
if (pref != null) {
preferredSelection = pref.toString();
}
final String selected = SGuiChoose.getChoices("Choose bonus booster format", 1, 1, formats, preferredSelection, null).get(0);
if (SealedProduct.specialSets.contains(selected)) {
BoosterPack boosterPack = BoosterPack.FN_FROM_COLOR.apply(selected);
assert boosterPack != null;
cardsWon = boosterPack.getCards();
title = "Bonus " + selected + " Booster Pack!";
} else {
GameFormat selectedFormat = null;
for (final GameFormat f : FModel.getFormats().getOrderedList()) {
if (f.toString().equals(selected)) {
selectedFormat = f;
}
}
assert selectedFormat != null;
FModel.getQuestPreferences().setPref(QPref.BOOSTER_FORMAT, selected);
cardsWon = qData.getCards().generateQuestBooster(selectedFormat.getFilterPrinted());
title = "Bonus booster pack from the \"" + selectedFormat.getName() + "\" format!";
}
cardsWon = qData.getCards().generateQuestBooster(selected.getFilterPrinted());
qData.getCards().addAllCards(cardsWon); qData.getCards().addAllCards(cardsWon);
title = "Bonus booster pack from the \"" + selected.getName() + "\" format!";
} else { } else {
final List<String> sets = new ArrayList<>(); final List<String> sets = new ArrayList<>();
@@ -549,29 +573,43 @@ public class QuestWinLoseController {
maxChoices += qData.getAssets().getItemLevel(QuestItemType.MEMBERSHIP_TOKEN); maxChoices += qData.getAssets().getItemLevel(QuestItemType.MEMBERSHIP_TOKEN);
} }
final List<CardEdition> options = new ArrayList<>(); final List<String> options = new ArrayList<>();
while (!sets.isEmpty() && maxChoices > 0) { while (!sets.isEmpty() && maxChoices > 0) {
final int ix = MyRandom.getRandom().nextInt(sets.size()); final int ix = MyRandom.getRandom().nextInt(sets.size());
final String set = sets.get(ix); final String set = sets.get(ix);
sets.remove(ix); sets.remove(ix);
options.add(FModel.getMagicDb().getEditions().get(set)); if (SealedProduct.specialSets.contains(set)) {
options.add(set);
} else {
options.add(FModel.getMagicDb().getEditions().get(set).toString());
}
if (FModel.getQuestPreferences().getPrefInt(QPref.SPECIAL_BOOSTERS) == 1) {
if (Math.random() > 0.85 - (double) (maxChoices) / 10.0) {
options.add(SealedProduct.specialSets.get((int) (Math.random() * SealedProduct.specialSets.size())));
}
}
maxChoices--; maxChoices--;
} }
final CardEdition chooseEd = SGuiChoose.one("Choose bonus booster set", options); String chooseEd = SGuiChoose.one("Choose bonus booster set", options);
if (customBooster) { if (SealedProduct.specialSets.contains(chooseEd)) {
List<PaperCard> cards = FModel.getMagicDb().getCommonCards().getAllCards(Predicates.printedInSet(chooseEd.getCode())); final IUnOpenedProduct product = new UnOpenedProduct(QuestUtilCards.getColoredBoosterTemplate(chooseEd));
cardsWon = product.get();
} else if (customBooster) {
List<PaperCard> cards = FModel.getMagicDb().getCommonCards().getAllCards(Predicates.printedInSet(FModel.getMagicDb().getEditions().get(chooseEd).getCode()));
final IUnOpenedProduct product = new UnOpenedProduct(getBoosterTemplate(), cards); final IUnOpenedProduct product = new UnOpenedProduct(getBoosterTemplate(), cards);
cardsWon = product.get(); cardsWon = product.get();
} else { } else {
final IUnOpenedProduct product = new UnOpenedProduct(FModel.getMagicDb().getBoosters().get(chooseEd.getCode())); String chosenEdition = chooseEd.substring(chooseEd.lastIndexOf("(") + 1, chooseEd.lastIndexOf(")"));
chooseEd = chooseEd.substring(0, chooseEd.lastIndexOf("(")).trim();
final IUnOpenedProduct product = new UnOpenedProduct(FModel.getMagicDb().getBoosters().get(chosenEdition));
cardsWon = product.get(); cardsWon = product.get();
} }
qData.getCards().addAllCards(cardsWon); qData.getCards().addAllCards(cardsWon);
title = "Bonus " + chooseEd.getName() + " booster pack!"; title = "Bonus " + chooseEd + " Booster Pack!";
} }

View File

@@ -37,6 +37,8 @@ public class QuestPreferences extends PreferencesStore<QuestPreferences.QPref> i
// The preferred format of the won booster pack // The preferred format of the won booster pack
BOOSTER_FORMAT("Standard"), BOOSTER_FORMAT("Standard"),
SPECIAL_BOOSTERS("1"),
// How many credits are lost for losing a match // How many credits are lost for losing a match
PENALTY_LOSS("15"), PENALTY_LOSS("15"),
@@ -263,6 +265,7 @@ public class QuestPreferences extends PreferencesStore<QuestPreferences.QPref> i
} }
break; break;
case SPECIAL_BOOSTERS:
case ITEM_LEVEL_RESTRICTION: case ITEM_LEVEL_RESTRICTION:
if (val != 0 && val != 1) { if (val != 0 && val != 1) {
return "Only values 0 or 1 are acceptable; 1 for enabled, 0 for disabled."; return "Only values 0 or 1 are acceptable; 1 for enabled, 0 for disabled.";

View File

@@ -743,7 +743,11 @@ public class QuestDataIO {
protected void write(final BoosterPack booster, final Integer count, final HierarchicalStreamWriter writer) { protected void write(final BoosterPack booster, final Integer count, final HierarchicalStreamWriter writer) {
writer.startNode("booster"); writer.startNode("booster");
writer.addAttribute("s", booster.getEdition()); if (booster.getEdition().equals("?")) {
writer.addAttribute("s", booster.getName().substring(0, booster.getName().indexOf(booster.getItemType()) - 1));
} else {
writer.addAttribute("s", booster.getEdition());
}
writer.addAttribute("n", count.toString()); writer.addAttribute("n", count.toString());
writer.endNode(); writer.endNode();
} }
@@ -841,8 +845,13 @@ public class QuestDataIO {
} }
protected BoosterPack readBooster(final HierarchicalStreamReader reader) { protected BoosterPack readBooster(final HierarchicalStreamReader reader) {
final CardEdition ed = FModel.getMagicDb().getEditions().get(reader.getAttribute("s")); String s = reader.getAttribute("s");
return BoosterPack.FN_FROM_SET.apply(ed); if (SealedProduct.specialSets.contains(s) || s.equals("?")) {
return BoosterPack.FN_FROM_COLOR.apply(s);
} else {
final CardEdition ed = FModel.getMagicDb().getEditions().get(s);
return BoosterPack.FN_FROM_SET.apply(ed);
}
} }
protected TournamentPack readTournamentPack(final HierarchicalStreamReader reader) { protected TournamentPack readTournamentPack(final HierarchicalStreamReader reader) {

View File

@@ -17,18 +17,17 @@
*/ */
package forge.quest.io; package forge.quest.io;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import com.esotericsoftware.minlog.Log; import com.esotericsoftware.minlog.Log;
import forge.card.MagicColor; import forge.card.MagicColor;
import forge.properties.ForgeConstants; import forge.properties.ForgeConstants;
import forge.util.FileUtil; import forge.util.FileUtil;
import forge.util.MyRandom; import forge.util.MyRandom;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
/** /**
* <p> * <p>
* ReadPriceList class. * ReadPriceList class.
@@ -73,12 +72,13 @@ public class ReadPriceList {
* @return a {@link java.util.HashMap} object. * @return a {@link java.util.HashMap} object.
*/ */
private Map<String, Integer> readFile(final String file) { private Map<String, Integer> readFile(final String file) {
final Map<String, Integer> map = new HashMap<String, Integer>();
final Map<String, Integer> map = new HashMap<>();
final Random r = MyRandom.getRandom(); final Random r = MyRandom.getRandom();
final List<String> lines = FileUtil.readFile(file); final List<String> lines = FileUtil.readFile(file);
for (final String line : lines) { for (final String line : lines) {
if (line.trim().length() == 0) { if (line.trim().isEmpty()) {
break; break;
} }
@@ -95,8 +95,8 @@ public class ReadPriceList {
try { try {
int val = Integer.parseInt(price.trim()); int val = Integer.parseInt(price.trim());
if (!(MagicColor.Constant.BASIC_LANDS.contains(name) || MagicColor.Constant.SNOW_LANDS.contains(name))) { if (!(MagicColor.Constant.BASIC_LANDS.contains(name) || MagicColor.Constant.SNOW_LANDS.contains(name)) && !ForgeConstants.PRICES_BOOSTER_FILE.equals(file)) {
float ff = 0; float ff;
if (r.nextInt(100) < 90) { if (r.nextInt(100) < 90) {
ff = r.nextInt(10) * (float) .01; ff = r.nextInt(10) * (float) .01;
} }