* Game: fixed that Snow-Covered lands can be added to auto-generated or submitted/timeout decks (#7222);

This commit is contained in:
Oleg Agafonov 2020-12-23 10:26:49 +04:00
parent 10cf9c4a4e
commit dd7c1939d3
6 changed files with 71 additions and 51 deletions

View file

@ -1,12 +1,5 @@
package mage.client.deck.generator; package mage.client.deck.generator;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.decks.Deck; import mage.cards.decks.Deck;
import mage.cards.repository.CardCriteria; import mage.cards.repository.CardCriteria;
@ -21,6 +14,8 @@ import mage.constants.Rarity;
import mage.util.RandomUtil; import mage.util.RandomUtil;
import mage.util.TournamentUtil; import mage.util.TournamentUtil;
import java.util.*;
/** /**
* Generates random card pool and builds a deck. * Generates random card pool and builds a deck.
* *
@ -289,6 +284,7 @@ public final class DeckGenerator {
if (!landSets.isEmpty()) { if (!landSets.isEmpty()) {
criteria.setCodes(landSets.toArray(new String[landSets.size()])); criteria.setCodes(landSets.toArray(new String[landSets.size()]));
} }
criteria.ignoreSetsWithSnowLands();
Map<String, List<CardInfo>> basicLandMap = new HashMap<>(); Map<String, List<CardInfo>> basicLandMap = new HashMap<>();
@ -297,7 +293,7 @@ public final class DeckGenerator {
criteria.rarities(Rarity.LAND).name(landName); criteria.rarities(Rarity.LAND).name(landName);
List<CardInfo> cards = CardRepository.instance.findCards(criteria); List<CardInfo> cards = CardRepository.instance.findCards(criteria);
if (cards.isEmpty()) { // Workaround to get basic lands if lands are not available for the given sets if (cards.isEmpty()) { // Workaround to get basic lands if lands are not available for the given sets
criteria.setCodes("ORI"); criteria.setCodes("M15");
cards = CardRepository.instance.findCards(criteria); cards = CardRepository.instance.findCards(criteria);
} }
basicLandMap.put(landName, cards); basicLandMap.put(landName, cards);

View file

@ -37,10 +37,6 @@ public class AddLandDialog extends MageDialog {
this.setModal(true); this.setModal(true);
} }
private boolean setHaveSnowLands(ExpansionInfo exp) {
return CardRepository.instance.haveSnowLands(exp.getCode());
}
public void showDialog(Deck deck, DeckEditorMode mode) { public void showDialog(Deck deck, DeckEditorMode mode) {
this.deck = deck; this.deck = deck;
SortedSet<String> landSetNames = new TreeSet<>(); SortedSet<String> landSetNames = new TreeSet<>();
@ -49,7 +45,7 @@ public class AddLandDialog extends MageDialog {
// decide from which sets basic lands are taken from // decide from which sets basic lands are taken from
for (String setCode : deck.getExpansionSetCodes()) { for (String setCode : deck.getExpansionSetCodes()) {
ExpansionInfo expansionInfo = ExpansionRepository.instance.getSetByCode(setCode); ExpansionInfo expansionInfo = ExpansionRepository.instance.getSetByCode(setCode);
if (expansionInfo != null && expansionInfo.hasBasicLands() && !setHaveSnowLands(expansionInfo)) { if (expansionInfo != null && expansionInfo.hasBasicLands() && !CardRepository.haveSnowLands(expansionInfo.getCode())) {
defaultSetName = expansionInfo.getName(); defaultSetName = expansionInfo.getName();
break; break;
} }
@ -62,7 +58,7 @@ public class AddLandDialog extends MageDialog {
if (expansionInfo != null) { if (expansionInfo != null) {
List<ExpansionInfo> blockSets = ExpansionRepository.instance.getSetsFromBlock(expansionInfo.getBlockName()); List<ExpansionInfo> blockSets = ExpansionRepository.instance.getSetsFromBlock(expansionInfo.getBlockName());
for (ExpansionInfo blockSet : blockSets) { for (ExpansionInfo blockSet : blockSets) {
if (blockSet.hasBasicLands() && !setHaveSnowLands(expansionInfo)) { if (blockSet.hasBasicLands() && !CardRepository.haveSnowLands(expansionInfo.getCode())) {
defaultSetName = expansionInfo.getName(); defaultSetName = expansionInfo.getName();
break; break;
} }
@ -71,11 +67,12 @@ public class AddLandDialog extends MageDialog {
} }
} }
} }
// if still no set with lands found, add list of all available // if still no set with lands found, add list of all available
List<ExpansionInfo> basicLandSets = ExpansionRepository.instance.getSetsWithBasicLandsByReleaseDate(); List<ExpansionInfo> basicLandSets = ExpansionRepository.instance.getSetsWithBasicLandsByReleaseDate();
for (ExpansionInfo expansionInfo : basicLandSets) { for (ExpansionInfo expansionInfo : basicLandSets) {
// snow lands only in free mode // snow lands only in free mode
if (mode != DeckEditorMode.FREE_BUILDING && setHaveSnowLands(expansionInfo)) { if (mode != DeckEditorMode.FREE_BUILDING && CardRepository.haveSnowLands(expansionInfo.getCode())) {
continue; continue;
} }
landSetNames.add(expansionInfo.getName()); landSetNames.add(expansionInfo.getName());
@ -148,6 +145,8 @@ public class AddLandDialog extends MageDialog {
throw new IllegalArgumentException("Code of Set " + landSetName + " not found"); throw new IllegalArgumentException("Code of Set " + landSetName + " not found");
} }
criteria.setCodes(expansionInfo.getCode()); criteria.setCodes(expansionInfo.getCode());
} else {
criteria.ignoreSetsWithSnowLands();
} }
criteria.rarities(Rarity.LAND).name(landName); criteria.rarities(Rarity.LAND).name(landName);
List<CardInfo> cards = CardRepository.instance.findCards(criteria); List<CardInfo> cards = CardRepository.instance.findCards(criteria);

View file

@ -820,11 +820,11 @@ public class VerifyCardDataTest {
// CHECK: wrong basic lands settings (it's for lands search, not booster construct) // CHECK: wrong basic lands settings (it's for lands search, not booster construct)
for (ExpansionSet set : sets) { for (ExpansionSet set : sets) {
Boolean needLand = set.hasBasicLands(); Boolean needLand = set.hasBasicLands();
Boolean foundedLand = false; Boolean foundLand = false;
Map<String, Integer> foundLandsList = new HashMap<>(); Map<String, Integer> foundLandsList = new HashMap<>();
for (ExpansionSet.SetCardInfo card : set.getSetCardInfo()) { for (ExpansionSet.SetCardInfo card : set.getSetCardInfo()) {
if (isBasicLandName(card.getName())) { if (isBasicLandName(card.getName())) {
foundedLand = true; foundLand = true;
int count = foundLandsList.getOrDefault(card.getName(), 0); int count = foundLandsList.getOrDefault(card.getName(), 0);
foundLandsList.put(card.getName(), count + 1); foundLandsList.put(card.getName(), count + 1);
} }
@ -834,11 +834,11 @@ public class VerifyCardDataTest {
.map(p -> (p.getKey() + " - " + p.getValue().toString())) .map(p -> (p.getKey() + " - " + p.getValue().toString()))
.sorted().collect(Collectors.joining(", ")); .sorted().collect(Collectors.joining(", "));
if (needLand && !foundedLand) { if (needLand && !foundLand) {
errorsList.add("error, found set with wrong hasBasicLands - it's true, but haven't land cards: " + set.getCode() + " in " + set.getClass().getName()); errorsList.add("error, found set with wrong hasBasicLands - it's true, but haven't land cards: " + set.getCode() + " in " + set.getClass().getName());
} }
if (!needLand && foundedLand) { if (!needLand && foundLand) {
errorsList.add("error, found set with wrong hasBasicLands - it's false, but have land cards: " + set.getCode() + " in " + set.getClass().getName() + ", lands: " + landNames); errorsList.add("error, found set with wrong hasBasicLands - it's false, but have land cards: " + set.getCode() + " in " + set.getClass().getName() + ", lands: " + landNames);
} }

View file

@ -20,6 +20,7 @@ public class CardCriteria {
private String nameExact; private String nameExact;
private String rules; private String rules;
private final List<String> setCodes; private final List<String> setCodes;
private final List<String> ignoreSetCodes; // sets to ignore, use with little amount of sets (example: ignore sets with snow lands)
private final List<CardType> types; private final List<CardType> types;
private final List<CardType> notTypes; private final List<CardType> notTypes;
private final List<String> supertypes; private final List<String> supertypes;
@ -42,6 +43,7 @@ public class CardCriteria {
public CardCriteria() { public CardCriteria() {
this.setCodes = new ArrayList<>(); this.setCodes = new ArrayList<>();
this.ignoreSetCodes = new ArrayList<>();
this.rarities = new ArrayList<>(); this.rarities = new ArrayList<>();
this.types = new ArrayList<>(); this.types = new ArrayList<>();
this.notTypes = new ArrayList<>(); this.notTypes = new ArrayList<>();
@ -130,6 +132,16 @@ public class CardCriteria {
return this; return this;
} }
public CardCriteria ignoreSetCodes(String... ignoreSetCodes) {
this.ignoreSetCodes.addAll(Arrays.asList(ignoreSetCodes));
return this;
}
public CardCriteria ignoreSetsWithSnowLands() {
this.ignoreSetCodes.addAll(CardRepository.snowLandSetCodes);
return this;
}
public CardCriteria types(CardType... types) { public CardCriteria types(CardType... types) {
this.types.addAll(Arrays.asList(types)); this.types.addAll(Arrays.asList(types));
return this; return this;
@ -216,6 +228,14 @@ public class CardCriteria {
clausesCount++; clausesCount++;
} }
for (String ignoreSetCode : ignoreSetCodes) {
where.ne("setCode", ignoreSetCode);
}
if (!ignoreSetCodes.isEmpty()) {
where.or(ignoreSetCodes.size());
clausesCount++;
}
if (types.size() != 7) { //if all types selected - no selection needed (Tribal and Conspiracy not selectable yet) if (types.size() != 7) { //if all types selected - no selection needed (Tribal and Conspiracy not selectable yet)
for (CardType type : types) { for (CardType type : types) {
where.like("types", new SelectArg('%' + type.name() + '%')); where.like("types", new SelectArg('%' + type.name() + '%'));
@ -357,6 +377,10 @@ public class CardCriteria {
return setCodes; return setCodes;
} }
public List<String> getIgnoreSetCodes() {
return ignoreSetCodes;
}
public List<CardType> getTypes() { public List<CardType> getTypes() {
return types; return types;
} }

View file

@ -41,6 +41,14 @@ public enum CardRepository {
private Set<String> classNames; private Set<String> classNames;
private final RepositoryEventSource eventSource = new RepositoryEventSource(); private final RepositoryEventSource eventSource = new RepositoryEventSource();
public static final Set<String> snowLandSetCodes = new HashSet<>(Arrays.asList(
"CSP",
"MH1",
"SLD",
"ME2",
"ICE"
));
CardRepository() { CardRepository() {
File file = new File("db"); File file = new File("db");
if (!file.exists()) { if (!file.exists()) {
@ -188,12 +196,8 @@ public enum CardRepository {
return names; return names;
} }
public Boolean haveSnowLands(String setCode) { public static Boolean haveSnowLands(String setCode) {
return setCode.equals("CSP") return snowLandSetCodes.contains(setCode);
|| setCode.equals("MH1")
|| setCode.equals("SLD")
|| setCode.equals("ME2")
|| setCode.equals("ICE");
} }
public Set<String> getNonbasicLandNames() { public Set<String> getNonbasicLandNames() {

View file

@ -6,51 +6,43 @@
package mage.util; package mage.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.repository.CardCriteria; import mage.cards.repository.*;
import mage.cards.repository.CardInfo;
import mage.cards.repository.CardRepository;
import mage.cards.repository.ExpansionInfo;
import mage.cards.repository.ExpansionRepository;
import mage.constants.Rarity; import mage.constants.Rarity;
import java.util.*;
import java.util.stream.Collectors;
/** /**
*
* @author LevelX2 * @author LevelX2
*/ */
public final class TournamentUtil { public final class TournamentUtil {
/** /**
* Tries to calculate the most appropiate sets to add basic lands for cards of a deck * Tries to calculate the most appropiate sets to add basic lands for cards of a deck
* *
* @param setCodesDeck * @param setCodesDeck
* @return setCode for lands * @return setCode for lands
*/ */
public static Set<String> getLandSetCodeForDeckSets(Collection<String> setCodesDeck) { public static Set<String> getLandSetCodeForDeckSets(Collection<String> setCodesDeck) {
Set<String> landSetCodes = new HashSet<>(); Set<String> landSetCodes = new HashSet<>();
// decide from which sets basic lands are taken from // decide from which sets basic lands are taken from
for (String setCode :setCodesDeck) { for (String setCode : setCodesDeck) {
ExpansionInfo expansionInfo = ExpansionRepository.instance.getSetByCode(setCode); ExpansionInfo expansionInfo = ExpansionRepository.instance.getSetByCode(setCode);
if (expansionInfo.hasBasicLands()) { if (expansionInfo.hasBasicLands() && !CardRepository.haveSnowLands(setCode)) {
landSetCodes.add(expansionInfo.getCode()); landSetCodes.add(expansionInfo.getCode());
} }
} }
// if sets have no basic land, take land from block // if sets have no basic land, take land from block
if (landSetCodes.isEmpty()) { if (landSetCodes.isEmpty()) {
for (String setCode :setCodesDeck) { for (String setCode : setCodesDeck) {
ExpansionInfo expansionInfo = ExpansionRepository.instance.getSetByCode(setCode); ExpansionInfo expansionInfo = ExpansionRepository.instance.getSetByCode(setCode);
List<ExpansionInfo> blockSets = ExpansionRepository.instance.getSetsFromBlock(expansionInfo.getBlockName()); List<ExpansionInfo> blockSets = ExpansionRepository.instance.getSetsFromBlock(expansionInfo.getBlockName());
for (ExpansionInfo blockSet: blockSets) { for (ExpansionInfo blockSet : blockSets) {
if (blockSet.hasBasicLands()) { if (blockSet.hasBasicLands() && !CardRepository.haveSnowLands(blockSet.getCode())) {
landSetCodes.add(blockSet.getCode()); landSetCodes.add(blockSet.getCode());
} }
} }
@ -60,7 +52,10 @@ public final class TournamentUtil {
if (landSetCodes.isEmpty()) { if (landSetCodes.isEmpty()) {
// if sets have no basic lands and also it has no parent or parent has no lands get last set with lands // if sets have no basic lands and also it has no parent or parent has no lands get last set with lands
// select a set with basic lands by random // select a set with basic lands by random
List<ExpansionInfo> basicLandSets = ExpansionRepository.instance.getSetsWithBasicLandsByReleaseDate(); List<ExpansionInfo> basicLandSets = ExpansionRepository.instance.getSetsWithBasicLandsByReleaseDate()
.stream()
.filter(exp -> !CardRepository.haveSnowLands(exp.getCode()))
.collect(Collectors.toList());
if (!basicLandSets.isEmpty()) { if (!basicLandSets.isEmpty()) {
landSetCodes.add(basicLandSets.get(RandomUtil.nextInt(basicLandSets.size())).getCode()); landSetCodes.add(basicLandSets.get(RandomUtil.nextInt(basicLandSets.size())).getCode());
} }
@ -71,11 +66,13 @@ public final class TournamentUtil {
} }
return landSetCodes; return landSetCodes;
} }
public static List<Card> getLands(String landName, int number, Set<String> landSets) { public static List<Card> getLands(String landName, int number, Set<String> landSets) {
CardCriteria criteria = new CardCriteria(); CardCriteria criteria = new CardCriteria();
if (!landSets.isEmpty()) { if (!landSets.isEmpty()) {
criteria.setCodes(landSets.toArray(new String[landSets.size()])); criteria.setCodes(landSets.toArray(new String[landSets.size()]));
} else {
criteria.ignoreSetsWithSnowLands();
} }
criteria.rarities(Rarity.LAND).name(landName); criteria.rarities(Rarity.LAND).name(landName);
List<CardInfo> lands = CardRepository.instance.findCards(criteria); List<CardInfo> lands = CardRepository.instance.findCards(criteria);
@ -84,9 +81,9 @@ public final class TournamentUtil {
for (int i = 0; i < number; i++) { for (int i = 0; i < number; i++) {
Card land = lands.get(RandomUtil.nextInt(lands.size())).getCard(); Card land = lands.get(RandomUtil.nextInt(lands.size())).getCard();
cards.add(land); cards.add(land);
} }
} }
return cards; return cards;
} }
} }