mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 18:58:00 +00:00
Refactor to only rank cards once
This commit is contained in:
@@ -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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
|
return rankedCards;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getInitialRankings(Iterable<PaperCard> cards, List<Pair<Double, PaperCard>> ranked) {
|
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,36 +46,46 @@ 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 rkg;
|
double score = getRawScore(card, customRankings);
|
||||||
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
double rawScore;
|
List<PaperCard> otherCards = getCardsExcept(cache, i);
|
||||||
if (rkg != null) {
|
|
||||||
rawScore = 100 - (100 * rkg);
|
|
||||||
} else {
|
|
||||||
rawScore = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
double score = rawScore;
|
|
||||||
|
|
||||||
List<PaperCard> otherCards = new ArrayList<>();
|
|
||||||
otherCards.addAll(cache.subList(0, i));
|
|
||||||
if (i + 1 < cache.size()) {
|
|
||||||
otherCards.addAll(cache.subList(i + 1, cache.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
score += calculateSynergies(card, otherCards);
|
score += calculateSynergies(card, otherCards);
|
||||||
|
|
||||||
ranked.add(Pair.of(score, card));
|
cardScores.add(Pair.of(score, card));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return cardScores;
|
||||||
|
}
|
||||||
|
|
||||||
|
private double getRawScore(PaperCard card, String customRankings) {
|
||||||
|
Double rkg;
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
double rawScore;
|
||||||
|
if (rkg != null) {
|
||||||
|
rawScore = 100 - (100 * rkg);
|
||||||
|
} else {
|
||||||
|
rawScore = 0.0;
|
||||||
|
}
|
||||||
|
return rawScore;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<PaperCard> getCardsExcept(List<PaperCard> cache, int i) {
|
||||||
|
List<PaperCard> otherCards = new ArrayList<>();
|
||||||
|
otherCards.addAll(cache.subList(0, i));
|
||||||
|
if (i + 1 < cache.size()) {
|
||||||
|
otherCards.addAll(cache.subList(i + 1, cache.size()));
|
||||||
|
}
|
||||||
|
return otherCards;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
||||||
final Iterable<PaperCard> nonLands = Iterables.filter(colorList,
|
|
||||||
Predicates.compose(CardRulesPredicates.Presets.IS_NON_LAND, PaperCard.FN_GET_RULES));
|
|
||||||
if (deckList.size() == numSpellsNeeded && getAverageCMC(deckList) < 3) {
|
if (deckList.size() == numSpellsNeeded && getAverageCMC(deckList) < 3) {
|
||||||
final List<Pair<Double, PaperCard>> list = rankCards(nonLands);
|
final Iterable<PaperCard> nonLands = Iterables.filter(colorList,
|
||||||
if (!list.isEmpty()) {
|
Predicates.compose(CardRulesPredicates.Presets.IS_NON_LAND, PaperCard.FN_GET_RULES));
|
||||||
final PaperCard c = list.get(0).getValue();
|
final PaperCard card = Iterables.getFirst(nonLands, null);
|
||||||
deckList.add(c);
|
if (card != null) {
|
||||||
getAiPlayables().remove(c);
|
deckList.add(card);
|
||||||
|
aiPlayables.remove(card);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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());
|
||||||
|
|||||||
Reference in New Issue
Block a user