Refactor to only rank cards once

This commit is contained in:
mcrawford620
2016-07-10 03:41:07 +00:00
parent 52458fd146
commit 8b5e00f93b
5 changed files with 154 additions and 210 deletions

View File

@@ -37,10 +37,7 @@ public class CardRankerTest {
PaperCard c1 = readCard("makindi_patrol.txt"); PaperCard c1 = readCard("makindi_patrol.txt");
list.add(c1); list.add(c1);
List<Pair<Double, PaperCard>> ranked = ranker.rankCards(list); List<PaperCard> ranked = ranker.rankCards(list);
for (Pair<Double, PaperCard> pair : ranked) {
System.out.println(pair.getKey().toString() + " " + pair.getValue().getName());
}
} }
/** /**

View File

@@ -5,6 +5,5 @@ PT:6/6
K:Vigilance K:Vigilance
A:AB$ ChangeZone | Cost$Sac<2/Eldrazi.Scion> | Origin$ Graveyard | Destination$ Hand | ActivationZone$ Graveyard | SorcerySpeed$ True | SpellDescription$ Return CARDNAME from your graveyard to your hand. Activate this ability only any time you could cast a sorcery. A:AB$ ChangeZone | Cost$Sac<2/Eldrazi.Scion> | Origin$ Graveyard | Destination$ Hand | ActivationZone$ Graveyard | SorcerySpeed$ True | SpellDescription$ Return CARDNAME from your graveyard to your hand. Activate this ability only any time you could cast a sorcery.
SVar:DiscardMe:1 SVar:DiscardMe:1
SVar:RemRandomDeck:True
SVar:Picture:http://www.wizards.com/global/images/magic/general/deathless_behemoth.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/deathless_behemoth.jpg
Oracle:Vigilance\nSacrifice two Eldrazi Scions: Return Deathless Behemoth from your graveyard to your hand. Activate this ability only any time you could cast a sorcery. Oracle:Vigilance\nSacrifice two Eldrazi Scions: Return Deathless Behemoth from your graveyard to your hand. Activate this ability only any time you could cast a sorcery.

View File

@@ -1,15 +1,12 @@
package forge.limited; package forge.limited;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import forge.card.CardRulesPredicates; import forge.card.CardRulesPredicates;
import forge.card.DeckHints; import forge.card.DeckHints;
import forge.item.PaperCard; import forge.item.PaperCard;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import java.awt.print.Paper;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@@ -23,16 +20,23 @@ public class CardRanker {
* @param cards PaperCards to rank * @param cards PaperCards to rank
* @return List of beans with card rankings * @return List of beans with card rankings
*/ */
public List<Pair<Double, PaperCard>> rankCards(final Iterable<PaperCard> cards) { public List<PaperCard> rankCards(final Iterable<PaperCard> cards) {
final List<Pair<Double, PaperCard>> ranked = new ArrayList<Pair<Double, PaperCard>>(); List<Pair<Double, PaperCard>> cardScores = getScores(cards);
getInitialRankings(cards, ranked); Collections.sort(cardScores, Collections.reverseOrder(new CardRankingComparator()));
Collections.sort(ranked, Collections.reverseOrder(new CardRankingComparator())); List<PaperCard> rankedCards = new ArrayList<>(cardScores.size());
return ranked; for (Pair<Double, PaperCard> pair : cardScores) {
System.out.println(pair.getKey().toString() + " " + pair.getValue().getName());
rankedCards.add(pair.getValue());
} }
private void getInitialRankings(Iterable<PaperCard> cards, List<Pair<Double, PaperCard>> ranked) { return rankedCards;
}
private List<Pair<Double, PaperCard>> getScores(Iterable<PaperCard> cards) {
List<Pair<Double, PaperCard>> cardScores = new ArrayList<>();
List<PaperCard> cache = new ArrayList<>(); List<PaperCard> cache = new ArrayList<>();
for (PaperCard card : cards) { for (PaperCard card : cards) {
cache.add(card); cache.add(card);
@@ -42,6 +46,19 @@ public class CardRanker {
for (int i = 0; i < cache.size(); i++) { for (int i = 0; i < cache.size(); i++) {
final PaperCard card = cache.get(i); final PaperCard card = cache.get(i);
double score = getRawScore(card, customRankings);
List<PaperCard> otherCards = getCardsExcept(cache, i);
score += calculateSynergies(card, otherCards);
cardScores.add(Pair.of(score, card));
}
return cardScores;
}
private double getRawScore(PaperCard card, String customRankings) {
Double rkg; Double rkg;
if (customRankings != null) { if (customRankings != null) {
rkg = DraftRankCache.getCustomRanking(customRankings, card.getName()); rkg = DraftRankCache.getCustomRanking(customRankings, card.getName());
@@ -59,19 +76,16 @@ public class CardRanker {
} else { } else {
rawScore = 0.0; rawScore = 0.0;
} }
return rawScore;
}
double score = rawScore; private List<PaperCard> getCardsExcept(List<PaperCard> cache, int i) {
List<PaperCard> otherCards = new ArrayList<>(); List<PaperCard> otherCards = new ArrayList<>();
otherCards.addAll(cache.subList(0, i)); otherCards.addAll(cache.subList(0, i));
if (i + 1 < cache.size()) { if (i + 1 < cache.size()) {
otherCards.addAll(cache.subList(i + 1, cache.size())); otherCards.addAll(cache.subList(i + 1, cache.size()));
} }
return otherCards;
score += calculateSynergies(card, otherCards);
ranked.add(Pair.of(score, card));
}
} }
private double calculateSynergies(PaperCard card, Iterable<PaperCard> otherCards) { private double calculateSynergies(PaperCard card, Iterable<PaperCard> otherCards) {
@@ -83,6 +97,16 @@ public class CardRanker {
return synergyScore; return synergyScore;
} }
private double getScoreForDeckHints(PaperCard card, Iterable<PaperCard> otherCards) {
double score = 0.0;
final DeckHints hints = card.getRules().getAiHints().getDeckHints();
if (hints != null && hints.getType() != DeckHints.Type.NONE) {
final List<PaperCard> comboCards = hints.filter(otherCards);
score = comboCards.size() * 10;
}
return score;
}
private double getScoreForBuffedBy(PaperCard card, Iterable<PaperCard> otherCards) { private double getScoreForBuffedBy(PaperCard card, Iterable<PaperCard> otherCards) {
double matchBuffScore = 0.0; double matchBuffScore = 0.0;
Iterable<Map.Entry<String, String>> vars = card.getRules().getMainPart().getVariables(); Iterable<Map.Entry<String, String>> vars = card.getRules().getMainPart().getVariables();
@@ -91,20 +115,9 @@ public class CardRanker {
String buff = var.getValue(); String buff = var.getValue();
final Iterable<PaperCard> buffers = Iterables.filter(otherCards, final Iterable<PaperCard> buffers = Iterables.filter(otherCards,
Predicates.compose(CardRulesPredicates.subType(buff), PaperCard.FN_GET_RULES)); Predicates.compose(CardRulesPredicates.subType(buff), PaperCard.FN_GET_RULES));
System.out.println(Iterables.size(buffers)); matchBuffScore = Iterables.size(buffers) * 3;
matchBuffScore = Iterables.size(buffers) * 5;
} }
} }
return matchBuffScore; return matchBuffScore;
} }
private double getScoreForDeckHints(PaperCard card, Iterable<PaperCard> otherCards) {
double score = 0.0;
final DeckHints hints = card.getRules().getAiHints().getDeckHints();
if (hints != null && hints.getType() != DeckHints.Type.NONE) {
final List<PaperCard> comboCards = hints.filter(otherCards);
score = comboCards.size() * 3;
}
return score;
}
} }

View File

@@ -1,5 +1,6 @@
package forge.limited; package forge.limited;
import java.awt.print.Paper;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
@@ -63,11 +64,11 @@ public class LimitedDeckBuilder extends DeckGeneratorBase {
private final List<String> setsWithBasicLands = new ArrayList<String>(); private final List<String> setsWithBasicLands = new ArrayList<String>();
// Views for aiPlayable // Views for aiPlayable
private Iterable<PaperCard> colorList; protected CardRanker ranker = new CardRanker();
private Iterable<PaperCard> onColorCreatures; private Iterable<PaperCard> onColorCreatures;
private Iterable<PaperCard> onColorNonCreatures; private Iterable<PaperCard> onColorNonCreatures;
private static final boolean logToConsole = false; private static final boolean logToConsole = true;
/** /**
* *
@@ -84,14 +85,13 @@ public class LimitedDeckBuilder extends DeckGeneratorBase {
this.deckColors = pClrs; this.deckColors = pClrs;
this.colors = pClrs.getChosenColors(); this.colors = pClrs.getChosenColors();
// removeUnplayables(); // remove Unplayables
final Iterable<PaperCard> playables = Iterables.filter(availableList, final Iterable<PaperCard> playables = Iterables.filter(availableList,
Predicates.compose(CardRulesPredicates.IS_KEPT_IN_AI_DECKS, PaperCard.FN_GET_RULES)); Predicates.compose(CardRulesPredicates.IS_KEPT_IN_AI_DECKS, PaperCard.FN_GET_RULES));
this.aiPlayables = Lists.newArrayList(playables); this.aiPlayables = this.ranker.rankCards(playables);
this.availableList.removeAll(getAiPlayables()); this.availableList.removeAll(aiPlayables);
findBasicLandSets(); findBasicLandSets();
} }
/** /**
@@ -132,7 +132,9 @@ public class LimitedDeckBuilder extends DeckGeneratorBase {
public Deck buildDeck(final String landSetCode) { public Deck buildDeck(final String landSetCode) {
// 1. Prepare // 1. Prepare
hasColor = Predicates.or(new MatchColorIdentity(colors), COLORLESS_CARDS); hasColor = Predicates.or(new MatchColorIdentity(colors), COLORLESS_CARDS);
colorList = Iterables.filter(aiPlayables, Predicates.compose(hasColor, PaperCard.FN_GET_RULES)); Iterable<PaperCard> colorList = Iterables.filter(aiPlayables,
Predicates.compose(hasColor, PaperCard.FN_GET_RULES));
onColorCreatures = Iterables.filter(colorList, onColorCreatures = Iterables.filter(colorList,
Predicates.compose(CardRulesPredicates.Presets.IS_CREATURE, PaperCard.FN_GET_RULES)); Predicates.compose(CardRulesPredicates.Presets.IS_CREATURE, PaperCard.FN_GET_RULES));
onColorNonCreatures = Iterables.filter(colorList, onColorNonCreatures = Iterables.filter(colorList,
@@ -153,28 +155,27 @@ public class LimitedDeckBuilder extends DeckGeneratorBase {
} }
// 3. Add creatures, trying to follow mana curve // 3. Add creatures, trying to follow mana curve
addManaCurveCreatures(rankCards(onColorCreatures), 15); addManaCurveCreatures(onColorCreatures, 15);
// 4.Try to fill up to 22 with on-color non-creature cards // 4.Try to fill up to 22 with on-color non-creature cards
addNonCreatures(rankCards(onColorNonCreatures), numSpellsNeeded - deckList.size()); addNonCreatures(onColorNonCreatures, numSpellsNeeded - deckList.size());
// 5.If we couldn't get up to 22, try to fill up to 22 with on-color // 5.If we couldn't get up to 22, try to fill up to 22 with on-color
// creature cards // creature cards
addCreatures(rankCards(onColorCreatures), numSpellsNeeded - deckList.size()); addCreatures(onColorCreatures, numSpellsNeeded - deckList.size());
// 6. If there are still on-color cards, and the average cmc is low, add // 6. If there are still on-color cards, and the average cmc is low, add
// a 23rd card. // a 23rd card.
if (deckList.size() == numSpellsNeeded && getAverageCMC(deckList) < 3) {
final Iterable<PaperCard> nonLands = Iterables.filter(colorList, final Iterable<PaperCard> nonLands = Iterables.filter(colorList,
Predicates.compose(CardRulesPredicates.Presets.IS_NON_LAND, PaperCard.FN_GET_RULES)); Predicates.compose(CardRulesPredicates.Presets.IS_NON_LAND, PaperCard.FN_GET_RULES));
if (deckList.size() == numSpellsNeeded && getAverageCMC(deckList) < 3) { final PaperCard card = Iterables.getFirst(nonLands, null);
final List<Pair<Double, PaperCard>> list = rankCards(nonLands); if (card != null) {
if (!list.isEmpty()) { deckList.add(card);
final PaperCard c = list.get(0).getValue(); aiPlayables.remove(card);
deckList.add(c);
getAiPlayables().remove(c);
landsNeeded--; landsNeeded--;
if (logToConsole) { if (logToConsole) {
System.out.println("Low CMC: " + c.getName()); System.out.println("Low CMC: " + card.getName());
} }
} }
} }
@@ -243,7 +244,7 @@ public class LimitedDeckBuilder extends DeckGeneratorBase {
} }
i = 0; i = 0;
System.out.println("NOT PICKED"); System.out.println("NOT PICKED");
for (final PaperCard c : getAiPlayables()) { for (final PaperCard c : aiPlayables) {
i++; i++;
System.out.println(i + ". " + c.toString() + ": " + c.getRules().getManaCost().toString()); System.out.println(i + ". " + c.toString() + ": " + c.getRules().getManaCost().toString());
} }
@@ -265,7 +266,7 @@ public class LimitedDeckBuilder extends DeckGeneratorBase {
} }
final PaperCard c = deckList.get(MyRandom.getRandom().nextInt(deckList.size() - 1)); final PaperCard c = deckList.get(MyRandom.getRandom().nextInt(deckList.size() - 1));
deckList.remove(c); deckList.remove(c);
getAiPlayables().add(c); aiPlayables.add(c);
if (logToConsole) { if (logToConsole) {
System.out.println(" - Removed " + c.getName() + " randomly."); System.out.println(" - Removed " + c.getName() + " randomly.");
} }
@@ -275,17 +276,17 @@ public class LimitedDeckBuilder extends DeckGeneratorBase {
if (logToConsole) { if (logToConsole) {
System.out.println("WARNING: Fixing deck size, currently " + deckList.size() + " cards."); System.out.println("WARNING: Fixing deck size, currently " + deckList.size() + " cards.");
} }
if (getAiPlayables().size() > 1) { if (aiPlayables.size() > 1) {
final PaperCard c = getAiPlayables().get(MyRandom.getRandom().nextInt(getAiPlayables().size() - 1)); final PaperCard c = aiPlayables.get(MyRandom.getRandom().nextInt(aiPlayables.size() - 1));
deckList.add(c); deckList.add(c);
getAiPlayables().remove(c); aiPlayables.remove(c);
if (logToConsole) { if (logToConsole) {
System.out.println(" - Added " + c.getName() + " randomly."); System.out.println(" - Added " + c.getName() + " randomly.");
} }
} else if (getAiPlayables().size() == 1) { } else if (aiPlayables.size() == 1) {
final PaperCard c = getAiPlayables().get(0); final PaperCard c = aiPlayables.get(0);
deckList.add(c); deckList.add(c);
getAiPlayables().remove(c); aiPlayables.remove(c);
if (logToConsole) { if (logToConsole) {
System.out.println(" - Added " + c.getName() + " randomly."); System.out.println(" - Added " + c.getName() + " randomly.");
} }
@@ -429,39 +430,41 @@ public class LimitedDeckBuilder extends DeckGeneratorBase {
final List<String> inverseDuals = getInverseDualLandList(); final List<String> inverseDuals = getInverseDualLandList();
final Iterable<PaperCard> lands = Iterables.filter(aiPlayables, final Iterable<PaperCard> lands = Iterables.filter(aiPlayables,
Predicates.compose(CardRulesPredicates.Presets.IS_NONBASIC_LAND, PaperCard.FN_GET_RULES)); Predicates.compose(CardRulesPredicates.Presets.IS_NONBASIC_LAND, PaperCard.FN_GET_RULES));
final List<Pair<Double, PaperCard>> ranked = rankCards(lands); List<PaperCard> landsToAdd = new ArrayList<>();
for (final Pair<Double, PaperCard> bean : ranked) { for (final PaperCard card : lands) {
if (landsNeeded > 0) { if (landsNeeded > 0) {
// Throw out any dual-lands for the wrong colors. Assume // Throw out any dual-lands for the wrong colors. Assume
// everything else is either // everything else is either
// (a) dual-land of the correct two colors, or // (a) dual-land of the correct two colors, or
// (b) a land that generates colorless mana and has some other // (b) a land that generates colorless mana and has some other
// beneficial effect. // beneficial effect.
if (!inverseDuals.contains(bean.getValue().getName())) { if (!inverseDuals.contains(card.getName())) {
deckList.add(bean.getValue()); landsToAdd.add(card);
aiPlayables.remove(bean.getValue());
landsNeeded--; landsNeeded--;
if (logToConsole) { if (logToConsole) {
System.out.println("NonBasicLand[" + landsNeeded + "]:" + bean.getValue().getName()); System.out.println("NonBasicLand[" + landsNeeded + "]:" + card.getName());
} }
} }
} }
} }
deckList.addAll(landsToAdd);
aiPlayables.removeAll(landsToAdd);
} }
/** /**
* Add a third color to the deck. * Add a third color to the deck.
* *
* @param nCards * @param num
* number to add
*/ */
private void addThirdColorCards(int nCards) { private void addThirdColorCards(int num) {
if (nCards > 0) { if (num > 0) {
final Iterable<PaperCard> others = Iterables.filter(aiPlayables, final Iterable<PaperCard> others = Iterables.filter(aiPlayables,
Predicates.compose(CardRulesPredicates.Presets.IS_NON_LAND, PaperCard.FN_GET_RULES)); Predicates.compose(CardRulesPredicates.Presets.IS_NON_LAND, PaperCard.FN_GET_RULES));
List<Pair<Double, PaperCard>> ranked = rankCards(others); List<PaperCard> toAdd = new ArrayList<>(num);
for (final Pair<Double, PaperCard> bean : ranked) { for (final PaperCard card : others) {
// Want a card that has just one "off" color. // Want a card that has just one "off" color.
final ColorSet off = colors.getOffColors(bean.getValue().getRules().getColor()); final ColorSet off = colors.getOffColors(card.getRules().getColor());
if (off.isMonoColor()) { if (off.isMonoColor()) {
colors = ColorSet.fromMask(colors.getColor() | off.getColor()); colors = ColorSet.fromMask(colors.getColor() | off.getColor());
break; break;
@@ -472,45 +475,47 @@ public class LimitedDeckBuilder extends DeckGeneratorBase {
DeckGeneratorBase.COLORLESS_CARDS); DeckGeneratorBase.COLORLESS_CARDS);
final Iterable<PaperCard> threeColorList = Iterables.filter(aiPlayables, final Iterable<PaperCard> threeColorList = Iterables.filter(aiPlayables,
Predicates.compose(hasColor, PaperCard.FN_GET_RULES)); Predicates.compose(hasColor, PaperCard.FN_GET_RULES));
ranked = rankCards(threeColorList); for (final PaperCard card : threeColorList) {
for (final Pair<Double, PaperCard> bean : ranked) { if (num > 0) {
if (nCards > 0) { toAdd.add(card);
deckList.add(bean.getValue()); num--;
aiPlayables.remove(bean.getValue());
nCards--;
if (logToConsole) { if (logToConsole) {
System.out.println("Third Color[" + nCards + "]:" + bean.getValue().getName() + "(" System.out.println("Third Color[" + num + "]:" + card.getName() + "("
+ bean.getValue().getRules().getManaCost() + ")"); + card.getRules().getManaCost() + ")");
} }
} else { } else {
break; break;
} }
} }
deckList.addAll(toAdd);
aiPlayables.removeAll(toAdd);
} }
} }
/** /**
* Add random cards to the deck. * Add random cards to the deck.
* *
* @param nCards * @param num
* number to add
*/ */
private void addRandomCards(int nCards) { private void addRandomCards(int num) {
final Iterable<PaperCard> others = Iterables.filter(aiPlayables, final Iterable<PaperCard> others = Iterables.filter(aiPlayables,
Predicates.compose(CardRulesPredicates.Presets.IS_NON_LAND, PaperCard.FN_GET_RULES)); Predicates.compose(CardRulesPredicates.Presets.IS_NON_LAND, PaperCard.FN_GET_RULES));
final List<Pair<Double, PaperCard>> ranked = rankCards(others); List <PaperCard> toAdd = new ArrayList<>(num);
for (final Pair<Double, PaperCard> bean : ranked) { for (final PaperCard card : others) {
if (nCards > 0) { if (num > 0) {
deckList.add(bean.getValue()); toAdd.add(card);
aiPlayables.remove(bean.getValue()); num--;
nCards--;
if (logToConsole) { if (logToConsole) {
System.out.println("Random[" + nCards + "]:" + bean.getValue().getName() + "(" System.out.println("Random[" + num + "]:" + card.getName() + "("
+ bean.getValue().getRules().getManaCost() + ")"); + card.getRules().getManaCost() + ")");
} }
} else { } else {
break; break;
} }
} }
deckList.addAll(toAdd);
aiPlayables.removeAll(toAdd);
} }
/** /**
@@ -519,60 +524,24 @@ public class LimitedDeckBuilder extends DeckGeneratorBase {
* @param nonCreatures * @param nonCreatures
* cards to choose from * cards to choose from
* @param num * @param num
* number to add
*/ */
private void addNonCreatures(final List<Pair<Double, PaperCard>> nonCreatures, int num) { private void addNonCreatures(final Iterable<PaperCard> nonCreatures, int num) {
for (final Pair<Double, PaperCard> bean : nonCreatures) { List<PaperCard> toAdd = new ArrayList<>(num);
for (final PaperCard card : nonCreatures) {
if (num > 0) { if (num > 0) {
final PaperCard cardToAdd = bean.getValue(); toAdd.add(card);
deckList.add(cardToAdd);
num--; num--;
getAiPlayables().remove(cardToAdd);
if (logToConsole) { if (logToConsole) {
System.out.println("Others[" + num + "]:" + cardToAdd.getName() + " (" System.out.println("Others[" + num + "]:" + card.getName() + " ("
+ cardToAdd.getRules().getManaCost() + ")"); + card.getRules().getManaCost() + ")");
} }
num = addDeckHintsCards(cardToAdd, num);
} else { } else {
break; break;
} }
} }
} deckList.addAll(toAdd);
aiPlayables.removeAll(toAdd);
/**
* Add cards that work well with the given card.
*
* @param cardToAdd
* card being checked
* @param num
* number of cards
* @return number left after adding
*/
private int addDeckHintsCards(final PaperCard cardToAdd, int num) {
// cards with DeckHints will try to grab additional cards from the pool
final DeckHints hints = cardToAdd.getRules().getAiHints().getDeckHints();
if (hints != null && hints.getType() != DeckHints.Type.NONE) {
final Iterable<PaperCard> onColor = Iterables.filter(aiPlayables, Predicates.compose(hasColor, PaperCard.FN_GET_RULES));
final List<PaperCard> comboCards = hints.filter(onColor);
if (logToConsole) {
System.out.println("Found " + comboCards.size() + " cards for " + cardToAdd.getName());
}
for (final Pair<Double, PaperCard> comboBean : rankCards(comboCards)) {
if (num > 0) {
// This is not exactly right, because the
// rankedComboCards could include creatures and
// non-creatures.
// This code could add too many of one or the other.
final PaperCard combo = comboBean.getValue();
deckList.add(combo);
num--;
getAiPlayables().remove(combo);
} else {
break;
}
}
}
return num;
} }
/** /**
@@ -620,10 +589,10 @@ public class LimitedDeckBuilder extends DeckGeneratorBase {
} }
} }
if (numCreatures > 0) { if (numCreatures > 0) {
addCreatures(rankCards(onColorCreatures), numCreatures); addCreatures(onColorCreatures, numCreatures);
} }
if (numOthers > 0) { if (numOthers > 0) {
addNonCreatures(rankCards(onColorNonCreatures), numOthers); addNonCreatures(onColorNonCreatures, numOthers);
} }
// If we added some replacement cards, and we still have cards available // If we added some replacement cards, and we still have cards available
// in aiPlayables, call this function again in case the replacement // in aiPlayables, call this function again in case the replacement
@@ -639,22 +608,23 @@ public class LimitedDeckBuilder extends DeckGeneratorBase {
* @param creatures * @param creatures
* cards to choose from * cards to choose from
* @param num * @param num
* number to add
*/ */
private void addCreatures(final List<Pair<Double, PaperCard>> creatures, int num) { private void addCreatures(final Iterable<PaperCard> creatures, int num) {
for (final Pair<Double, PaperCard> bean : creatures) { List<PaperCard> creaturesToAdd = new ArrayList<>(num);
for (final PaperCard card : creatures) {
if (num > 0) { if (num > 0) {
final PaperCard c = bean.getValue(); creaturesToAdd.add(card);
deckList.add(c);
num--; num--;
getAiPlayables().remove(c);
if (logToConsole) { if (logToConsole) {
System.out.println("Creature[" + num + "]:" + c.getName() + " (" + c.getRules().getManaCost() + ")"); System.out.println("Creature[" + num + "]:" + card.getName() + " (" + card.getRules().getManaCost() + ")");
} }
num = addDeckHintsCards(c, num);
} else { } else {
break; break;
} }
} }
deckList.addAll(creaturesToAdd);
aiPlayables.removeAll(creaturesToAdd);
} }
/** /**
@@ -665,8 +635,9 @@ public class LimitedDeckBuilder extends DeckGeneratorBase {
* @param creatures * @param creatures
* cards to choose from * cards to choose from
* @param num * @param num
* number to add
*/ */
private void addManaCurveCreatures(final List<Pair<Double, PaperCard>> creatures, int num) { private void addManaCurveCreatures(final Iterable<PaperCard> creatures, int num) {
final Map<Integer, Integer> creatureCosts = new HashMap<Integer, Integer>(); final Map<Integer, Integer> creatureCosts = new HashMap<Integer, Integer>();
for (int i = 1; i < 7; i++) { for (int i = 1; i < 7; i++) {
creatureCosts.put(i, 0); creatureCosts.put(i, 0);
@@ -683,9 +654,9 @@ public class LimitedDeckBuilder extends DeckGeneratorBase {
creatureCosts.put(cmc, creatureCosts.get(cmc) + 1); creatureCosts.put(cmc, creatureCosts.get(cmc) + 1);
} }
for (final Pair<Double, PaperCard> bean : creatures) { List<PaperCard> creaturesToAdd = new ArrayList<>(num);
final PaperCard c = bean.getValue(); for (final PaperCard card : creatures) {
int cmc = c.getRules().getManaCost().getCMC(); int cmc = card.getRules().getManaCost().getCMC();
if (cmc < 1) { if (cmc < 1) {
cmc = 1; cmc = 1;
} else if (cmc > 6) { } else if (cmc > 6) {
@@ -708,58 +679,24 @@ public class LimitedDeckBuilder extends DeckGeneratorBase {
} }
if (willAddCreature) { if (willAddCreature) {
deckList.add(c); creaturesToAdd.add(card);
num--; num--;
getAiPlayables().remove(c);
creatureCosts.put(cmc, creatureCosts.get(cmc) + 1); creatureCosts.put(cmc, creatureCosts.get(cmc) + 1);
if (logToConsole) { if (logToConsole) {
System.out.println("Creature[" + num + "]:" + c.getName() + " (" + c.getRules().getManaCost() + ")"); System.out.println("Creature[" + num + "]:" + card.getName() + " (" + card.getRules().getManaCost() + ")");
} }
num = addDeckHintsCards(c, num);
} else { } else {
if (logToConsole) { if (logToConsole) {
System.out.println(c.getName() + " not added because CMC " + c.getRules().getManaCost().getCMC() System.out.println(card.getName() + " not added because CMC " + card.getRules().getManaCost().getCMC()
+ " has " + currentAtCmc + " already."); + " has " + currentAtCmc + " already.");
} }
} }
if (num <= 0) { if (num <= 0) {
break; break;
} }
} }
} deckList.addAll(creaturesToAdd);
aiPlayables.removeAll(creaturesToAdd);
/**
* Rank cards.
*
* @param cards
* CardPrinteds to rank
* @return List of beans with card rankings
*/
protected List<Pair<Double, PaperCard>> rankCards(final Iterable<PaperCard> cards) {
final List<Pair<Double, PaperCard>> ranked = new ArrayList<Pair<Double, PaperCard>>();
for (final PaperCard card : cards) {
Double rkg;
String customRankings = IBoosterDraft.CUSTOM_RANKINGS_FILE[0];
if (customRankings != null) {
rkg = DraftRankCache.getCustomRanking(customRankings, card.getName());
if (rkg == null) {
// try the default rankings if custom rankings contain no entry
rkg = DraftRankCache.getRanking(card.getName(), card.getEdition());
}
} else {
rkg = DraftRankCache.getRanking(card.getName(), card.getEdition());
}
if (rkg != null) {
ranked.add(Pair.of(rkg, card));
} else {
ranked.add(Pair.of(0.0, card));
}
}
Collections.sort(ranked, new CardRankingComparator());
return ranked;
} }
/** /**

View File

@@ -31,13 +31,11 @@ public class SealedDeckBuilder extends LimitedDeckBuilder {
* @return DeckColors * @return DeckColors
*/ */
private ColorSet chooseColors() { private ColorSet chooseColors() {
List<Pair<Double, PaperCard>> rankedCards = rankCards(getAiPlayables());
// choose colors based on top 33% of cards // choose colors based on top 33% of cards
final List<PaperCard> colorChooserList = new ArrayList<PaperCard>(); final List<PaperCard> colorChooserList = new ArrayList<PaperCard>();
double limit = rankedCards.size() * .33; double limit = getAiPlayables().size() * .33;
for (int i = 0; i < limit; i++) { for (int i = 0; i < limit; i++) {
PaperCard cp = rankedCards.get(i).getValue(); PaperCard cp = getAiPlayables().get(i);
colorChooserList.add(cp); colorChooserList.add(cp);
//System.out.println(cp.getName() + " " + cp.getRules().getManaCost().toString()); //System.out.println(cp.getName() + " " + cp.getRules().getManaCost().toString());
} }
@@ -64,8 +62,8 @@ public class SealedDeckBuilder extends LimitedDeckBuilder {
} }
} }
String color1 = MagicColor.Constant.GREEN; String color1;
String color2 = MagicColor.Constant.BLACK; String color2;
final Random r = MyRandom.getRandom(); final Random r = MyRandom.getRandom();
if (maxColors.size() > 1) { if (maxColors.size() > 1) {
int n = r.nextInt(maxColors.size()); int n = r.nextInt(maxColors.size());