Esempio n. 1
0
  /**
   * Returns a map of colored mana symbol to basic land cards of that color.
   *
   * @param setsToUse which sets to retrieve basic lands from.
   * @return a map of color to basic lands.
   */
  private static Map<String, List<CardInfo>> generateBasicLands(List<String> setsToUse) {

    List<String> landSets = new LinkedList<>();

    // decide from which sets basic lands are taken from
    for (String setCode : setsToUse) {
      ExpansionInfo expansionInfo = ExpansionRepository.instance.getSetByCode(setCode);
      if (expansionInfo.hasBasicLands()) {
        landSets.add(expansionInfo.getCode());
      }
    }

    // if sets have no basic land, take land from block
    if (landSets.isEmpty()) {
      for (String setCode : setsToUse) {
        ExpansionInfo expansionInfo = ExpansionRepository.instance.getSetByCode(setCode);
        List<ExpansionInfo> blockSets =
            ExpansionRepository.instance.getSetsFromBlock(expansionInfo.getBlockName());
        for (ExpansionInfo blockSet : blockSets) {
          if (blockSet.hasBasicLands()) {
            landSets.add(blockSet.getCode());
          }
        }
      }
    }
    // if still no set with lands found, take one by random
    if (landSets.isEmpty()) {
      // 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
      Random generator = new Random();
      List<ExpansionInfo> basicLandSets =
          ExpansionRepository.instance.getSetsWithBasicLandsByReleaseDate();
      if (basicLandSets.size() > 0) {
        landSets.add(basicLandSets.get(generator.nextInt(basicLandSets.size())).getCode());
      }
    }

    if (landSets.isEmpty()) {
      throw new IllegalArgumentException("No set with basic land was found");
    }

    CardCriteria criteria = new CardCriteria();
    if (!landSets.isEmpty()) {
      criteria.setCodes(landSets.toArray(new String[landSets.size()]));
    }

    Map<String, List<CardInfo>> basicLandMap = new HashMap<>();

    for (ColoredManaSymbol c : ColoredManaSymbol.values()) {
      String landName = DeckGeneratorPool.getBasicLandName(c.toString());
      criteria.rarities(Rarity.LAND).name(landName);
      List<CardInfo> cards = CardRepository.instance.findCards(criteria);
      basicLandMap.put(landName, cards);
    }
    return basicLandMap;
  }
Esempio n. 2
0
 /**
  * Generates all spells for the deck. Each card is retrieved from the database and checked against
  * the converted mana cost (CMC) needed for the current card pool. If a card's CMC matches the CMC
  * range required by the pool, it is added to the deck. This ensures that the majority of cards
  * fit a fixed mana curve for the deck, and it is playable. Creatures and non-creatures are
  * retrieved separately to ensure the deck contains a reasonable mix of both.
  *
  * @param criteria the criteria to search for in the database.
  * @param spellCount the number of spells that match the criteria needed in the deck.
  */
 private static void generateSpells(CardCriteria criteria, int spellCount) {
   List<CardInfo> cardPool = CardRepository.instance.findCards(criteria);
   int retrievedCount = cardPool.size();
   List<DeckGeneratorCMC> deckCMCs = genPool.getCMCsForSpellCount(spellCount);
   Random random = new Random();
   int count = 0;
   int reservesAdded = 0;
   if (retrievedCount > 0 && retrievedCount >= spellCount) {
     int tries = 0;
     while (count < spellCount) {
       Card card = cardPool.get(random.nextInt(retrievedCount)).getMockCard();
       if (genPool.isValidSpellCard(card)) {
         int cardCMC = card.getManaCost().convertedManaCost();
         for (DeckGeneratorCMC deckCMC : deckCMCs) {
           if (cardCMC >= deckCMC.min && cardCMC <= deckCMC.max) {
             int currentAmount = deckCMC.getAmount();
             if (currentAmount > 0) {
               deckCMC.setAmount(currentAmount - 1);
               genPool.addCard(card.copy());
               count++;
             }
           } else {
             if (reservesAdded < genPool.getDeckSize() / 2) {
               genPool.tryAddReserve(card, cardCMC);
               reservesAdded++;
             }
           }
         }
       }
       tries++;
       if (tries > MAX_TRIES) {
         // Break here, we'll fill in random missing ones later
         break;
       }
     }
   } else {
     throw new IllegalStateException("Not enough cards to generate deck.");
   }
 }
Esempio n. 3
0
  /**
   * Generates all the cards to use in the deck. Adds creatures, non-creatures, lands (including
   * non-basic). Fixes the deck, adjusting for size and color of the cards retrieved.
   *
   * @param deckSize how big the deck is to generate.
   * @param allowedColors which colors are allowed in the deck.
   * @param setsToUse which sets to use to retrieve cards for this deck.
   * @return the final deck to use.
   */
  private static Deck generateDeck(
      int deckSize, List<ColoredManaSymbol> allowedColors, List<String> setsToUse) {
    genPool = new DeckGeneratorPool(deckSize, allowedColors, genDialog.isSingleton());

    final String[] sets = setsToUse.toArray(new String[setsToUse.size()]);

    // Creatures
    final CardCriteria creatureCriteria = new CardCriteria();
    creatureCriteria.setCodes(sets);
    creatureCriteria.notTypes(CardType.LAND);
    creatureCriteria.types(CardType.CREATURE);
    if (!(genDialog.useArtifacts())) creatureCriteria.notTypes(CardType.ARTIFACT);

    // Non-creatures (sorcery, instant, enchantment, artifact etc.)
    final CardCriteria nonCreatureCriteria = new CardCriteria();
    nonCreatureCriteria.setCodes(sets);
    nonCreatureCriteria.notTypes(CardType.LAND);
    nonCreatureCriteria.notTypes(CardType.CREATURE);
    if (!(genDialog.useArtifacts())) nonCreatureCriteria.notTypes(CardType.ARTIFACT);

    // Non-basic land
    final CardCriteria nonBasicLandCriteria = new CardCriteria();
    nonBasicLandCriteria.setCodes(sets);
    nonBasicLandCriteria.types(CardType.LAND);
    nonBasicLandCriteria.notSupertypes("Basic");

    // Generate basic land cards
    Map<String, List<CardInfo>> basicLands = generateBasicLands(setsToUse);

    generateSpells(creatureCriteria, genPool.getCreatureCount());
    generateSpells(nonCreatureCriteria, genPool.getNonCreatureCount());
    generateLands(nonBasicLandCriteria, genPool.getLandCount(), basicLands);

    // Reconstructs the final deck and adjusts for Math rounding and/or missing cards
    return genPool.getDeck();
  }
Esempio n. 4
0
  /**
   * Once any non-basic lands are added, add basic lands until the deck is filled.
   *
   * @param landsNeeded how many remaining lands are needed.
   * @param percentage the percentage needed for each color in the final deck.
   * @param count how many of each color can be produced by non-basic lands.
   * @param basicLands list of information about basic lands from the database.
   */
  private static void addBasicLands(
      int landsNeeded,
      Map<String, Double> percentage,
      Map<String, Integer> count,
      Map<String, List<CardInfo>> basicLands) {
    int colorTotal = 0;
    ColoredManaSymbol colorToAdd = null;

    // Add up the totals for all colors, to keep track of the percentage a color is.
    for (Map.Entry<String, Integer> c : count.entrySet()) {
      colorTotal += c.getValue();
    }

    // Keep adding basic lands until we fill the deck
    while (landsNeeded > 0) {

      double minPercentage = Integer.MIN_VALUE;

      for (ColoredManaSymbol color : ColoredManaSymbol.values()) {
        // What percentage of this color is requested
        double neededPercentage = percentage.get(color.toString());
        // If there is a 0% need for basic lands of this color, skip it
        if (neededPercentage <= 0) {
          continue;
        }
        int currentCount = count.get(color.toString());
        double thisPercentage = 0.0;
        // Calculate the percentage of lands so far that produce this color
        if (currentCount > 0) thisPercentage = (currentCount / (double) colorTotal) * 100.0;
        // Check if the color is the most "needed" (highest percentage) we have seen so far
        if (neededPercentage - thisPercentage > minPercentage) {
          // Put this color land forward to be added
          colorToAdd = color;
          minPercentage = (neededPercentage - thisPercentage);
        }
      }
      if (colorToAdd != null) {
        genPool.addCard(getBasicLand(colorToAdd, basicLands));
        count.put(colorToAdd.toString(), count.get(colorToAdd.toString()) + 1);
        colorTotal++;
        landsNeeded--;
      }
    }
  }
Esempio n. 5
0
  /**
   * Generates all the lands for the deck. Generates non-basic if selected by the user and if the
   * deck isn't monocolored. Will fetch non-basic lands if required and then fill up the remaining
   * space with basic lands. Basic lands are adjusted according to the mana symbols seen in the
   * cards used in this deck. Usually the lands will be well balanced relative to the color of
   * cards.
   *
   * @param criteria the criteria of the lands to search for in the database.
   * @param landsCount the amount of lands required for this deck.
   * @param basicLands information about the basic lands from the sets used.
   */
  private static void generateLands(
      CardCriteria criteria, int landsCount, Map<String, List<CardInfo>> basicLands) {

    int tries = 0;
    int countNonBasic = 0;
    // Store the nonbasic lands (if any) we'll add
    List<Card> deckLands = new ArrayList<>();

    // Calculates the percentage of colored mana symbols over all spells in the deck
    Map<String, Double> percentage = genPool.calculateSpellColorPercentages();

    // Only dual/tri color lands are generated for now, and not non-basic lands that only produce
    // colorless mana.
    if (!genPool.isMonoColoredDeck() && genDialog.useNonBasicLand()) {
      List<Card> landCards = genPool.filterLands(CardRepository.instance.findCards(criteria));
      int allCount = landCards.size();
      Random random = new Random();
      if (allCount > 0) {
        while (countNonBasic < landsCount / 2) {
          Card card = landCards.get(random.nextInt(allCount));
          if (genPool.isValidLandCard(card)) {
            Card addedCard = card.copy();
            deckLands.add(addedCard);
            genPool.addCard(addedCard);
            countNonBasic++;
          }
          tries++;
          // to avoid infinite loop
          if (tries > MAX_TRIES) {
            // Not a problem, just use what we have
            break;
          }
        }
      }
    }
    // Calculate the amount of colored mana already can be produced by the non-basic lands
    Map<String, Integer> count = genPool.countManaProduced(deckLands);
    // Fill up the rest of the land quota with basic lands adjusted to fit the deck's mana costs
    addBasicLands(landsCount - countNonBasic, percentage, count, basicLands);
  }
Esempio n. 6
0
 /**
  * Return a random basic land of the chosen color.
  *
  * @param color the color the basic land should produce.
  * @param basicLands list of information about basic lands from the database.
  * @return a single basic land that produces the color needed.
  */
 private static Card getBasicLand(
     ColoredManaSymbol color, Map<String, List<CardInfo>> basicLands) {
   Random random = new Random();
   String landName = DeckGeneratorPool.getBasicLandName(color.toString());
   return basicLands.get(landName).get(random.nextInt(basicLands.size() - 1)).getMockCard().copy();
 }