Allow multiple deck hints in a card

This commit is contained in:
mcrawford620
2016-07-12 04:43:31 +00:00
parent 83d93c4436
commit 3678e6a870
6 changed files with 101 additions and 101 deletions

View File

@@ -1,7 +1,7 @@
package forge.card;
/**
* TODO: Write javadoc for this type.
* CardAiHints holds all the different types of card hints for AI decks.
*
*/
public class CardAiHints {

View File

@@ -7,6 +7,7 @@ import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import forge.item.PaperCard;
import forge.util.PredicateString.StringOp;
import org.apache.commons.lang3.tuple.Pair;
import java.util.ArrayList;
import java.util.Collection;
@@ -22,7 +23,7 @@ public class DeckHints {
/**
* Enum of types of DeckHints.
*/
public enum Type {
private enum Type {
/** The Color. */
COLOR,
@@ -36,84 +37,98 @@ public class DeckHints {
NONE
}
private Type type = Type.NONE;
private String filterParam = null;
private boolean valid = false;
private List<Pair<Type, String>> filters = null;
/**
* Construct a DeckHints from the SVar string.
*
* @param wants
* @param hints
* SVar for DeckHints
*/
public DeckHints(String wants) {
String[] pieces = wants.split("\\$");
public DeckHints(String hints) {
String[] pieces = hints.split("\\&");
if (pieces.length > 0) {
for (String piece : pieces) {
Pair<Type, String> pair = parseHint(piece.trim());
if (pair != null) {
if (filters == null) {
filters = new ArrayList<>();
}
filters.add(pair);
valid = true;
}
}
}
}
private Pair<Type, String> parseHint(String hint) {
Pair<Type, String> pair = null;
String[] pieces = hint.split("\\$");
if (pieces.length == 2) {
try {
Type typeValue = Type.valueOf(pieces[0].toUpperCase());
for (Type t : Type.values()) {
if (typeValue == t) {
type = t;
pair = Pair.of(t, pieces[1]);
break;
}
}
} catch (IllegalArgumentException e) {
// type will remain NONE
// will remain null
}
filterParam = pieces[1];
}
return pair;
}
public boolean isValid() {
return valid;
}
/**
* @return the type
*/
public Type getType() {
return type;
}
/**
* Returns a list of Cards from the given List<Card> that match this
* Returns a list of Cards from the given List<PaperCard> that match this
* DeckHints. I.e., other cards that this Card needs in its deck.
*
* @param cardList
* list of cards to be filtered
* @return List<Card> of Cards that match this DeckHints.
* @return List<PaperCard> of Cards that match this DeckHints.
*/
public List<PaperCard> filter(Iterable<PaperCard> cardList) {
List<PaperCard> ret;
switch (type) {
case TYPE:
ret = new ArrayList<PaperCard>();
String[] types = filterParam.split("\\|");
for (String type : types) {
addMatchingItems(ret, cardList, CardRulesPredicates.subType(type), PaperCard.FN_GET_RULES);
List<PaperCard> ret = new ArrayList<>();
for (Pair<Type, String> pair : filters) {
Type type = pair.getLeft();
String param = pair.getRight();
switch (type) {
case TYPE:
String[] types = param.split("\\|");
for (String t : types) {
addMatchingItems(ret, cardList, CardRulesPredicates.subType(t), PaperCard.FN_GET_RULES);
}
break;
case COLOR:
String[] colors = param.split("\\|");
for (String color : colors) {
ColorSet cc = ColorSet.fromNames(color);
if (cc.isColorless()) {
addMatchingItems(ret, cardList, CardRulesPredicates.Presets.IS_COLORLESS, PaperCard.FN_GET_RULES);
} else {
addMatchingItems(ret, cardList, CardRulesPredicates.isColor(cc.getColor()), PaperCard.FN_GET_RULES);
}
}
break;
case KEYWORD:
String[] keywords = param.split("\\|");
for (String keyword : keywords) {
addMatchingItems(ret, cardList, CardRulesPredicates.hasKeyword(keyword), PaperCard.FN_GET_RULES);
}
break;
case NAME:
String[] names = param.split("\\|");
for (String name : names) {
addMatchingItems(ret, cardList, CardRulesPredicates.name(StringOp.EQUALS, name), PaperCard.FN_GET_RULES);
}
break;
}
break;
case COLOR:
ret = new ArrayList<PaperCard>();
String[] colors = filterParam.split("\\|");
for (String color : colors) {
ColorSet cc = ColorSet.fromNames(color);
addMatchingItems(ret, cardList, CardRulesPredicates.isColor(cc.getColor()), PaperCard.FN_GET_RULES);
}
break;
case KEYWORD:
ret = new ArrayList<PaperCard>();
String[] keywords = filterParam.split("\\|");
for (String keyword : keywords) {
addMatchingItems(ret, cardList, CardRulesPredicates.hasKeyword(keyword), PaperCard.FN_GET_RULES);
}
break;
case NAME:
ret = new ArrayList<PaperCard>();
String[] names = filterParam.split("\\|");
for (String name : names) {
addMatchingItems(ret, cardList, CardRulesPredicates.name(StringOp.EQUALS, name), PaperCard.FN_GET_RULES);
}
break;
default:
ret = Lists.newArrayList(cardList);
break;
}
return ret;
}

View File

@@ -38,13 +38,11 @@ public class DeckHintsTest {
Assert.assertEquals("Griffin Rider", cp.getName());
DeckHints hints = cp.getRules().getAiHints().getDeckHints();
Assert.assertNotNull(hints);
Assert.assertEquals(DeckHints.Type.TYPE, hints.getType());
Assert.assertTrue(hints.isValid());
List<PaperCard> list = new ArrayList<PaperCard>();
PaperCard c0 = readCard("assault_griffin.txt");
list.add(c0);
PaperCard c1 = readCard("auramancer.txt");
list.add(c1);
list.add(readCard("assault_griffin.txt"));
list.add(readCard("auramancer.txt"));
Assert.assertEquals(1, hints.filter(list).size());
Assert.assertEquals("Assault Griffin", hints.filter(list).get(0).getName());
@@ -59,15 +57,12 @@ public class DeckHintsTest {
Assert.assertEquals("Throne of Empires", cp.getName());
DeckHints hints = cp.getRules().getAiHints().getDeckHints();
Assert.assertNotNull(hints);
Assert.assertEquals(DeckHints.Type.NAME, hints.getType());
Assert.assertTrue(hints.isValid());
List<PaperCard> list = new ArrayList<PaperCard>();
PaperCard c0 = readCard("assault_griffin.txt");
list.add(c0);
PaperCard c1 = readCard("scepter_of_empires.txt");
list.add(c1);
PaperCard c2 = readCard("crown_of_empires.txt");
list.add(c2);
list.add(readCard("assault_griffin.txt"));
list.add(readCard("scepter_of_empires.txt"));
list.add(readCard("crown_of_empires.txt"));
Assert.assertEquals(2, hints.filter(list).size());
}
@@ -80,13 +75,11 @@ public class DeckHintsTest {
IPaperCard cp = readCard("mwonvuli_beast_tracker.txt");
DeckHints hints = cp.getRules().getAiHints().getDeckHints();
Assert.assertNotNull(hints);
Assert.assertEquals(DeckHints.Type.KEYWORD, hints.getType());
Assert.assertTrue(hints.isValid());
List<PaperCard> list = new ArrayList<PaperCard>();
PaperCard c0 = readCard("acidic_slime.txt");
list.add(c0);
PaperCard c1 = readCard("ajanis_sunstriker.txt");
list.add(c1);
list.add(readCard("acidic_slime.txt"));
list.add(readCard("ajanis_sunstriker.txt"));
Assert.assertEquals(1, hints.filter(list).size());
}
@@ -99,13 +92,11 @@ public class DeckHintsTest {
IPaperCard cp = readCard("wurms_tooth.txt");
DeckHints hints = cp.getRules().getAiHints().getDeckNeeds();
Assert.assertNotNull(hints);
Assert.assertEquals(DeckHints.Type.COLOR, hints.getType());
Assert.assertTrue(hints.isValid());
List<PaperCard> list = new ArrayList<PaperCard>();
PaperCard c0 = readCard("llanowar_elves.txt");
list.add(c0);
PaperCard c1 = readCard("unsummon.txt");
list.add(c1);
list.add(readCard("llanowar_elves.txt"));
list.add(readCard("unsummon.txt"));
Assert.assertEquals(1, hints.filter(list).size());
}
@@ -114,19 +105,30 @@ public class DeckHintsTest {
*
* Test for no wants.
*/
@Test(timeOut = 1000, enabled = false)
@Test(timeOut = 1000, enabled = true)
void testNoFilter() {
PaperCard cp = readCard("assault_griffin.txt");
DeckHints hints = cp.getRules().getAiHints().getDeckHints();
Assert.assertEquals("Assault Griffin", cp.getName());
Assert.assertNull(hints);
}
/**
* Test for multiple.
*/
@Test(timeOut = 1000, enabled = true)
void testMultiple() {
PaperCard pc = readCard("ruination_guide.txt");
DeckHints hints = pc.getRules().getAiHints().getDeckHints();
Assert.assertNotNull(hints);
Assert.assertEquals(DeckHints.Type.NONE, hints.getType());
Assert.assertTrue(hints.isValid());
List<PaperCard> list = new ArrayList<PaperCard>();
PaperCard c0 = readCard("assault_griffin.txt");
list.add(c0);
list.add(readCard("assault_griffin.txt"));
list.add(readCard("breaker_of_armies.txt"));
list.add(readCard("benthic_infiltrator.txt"));
Assert.assertEquals(1, hints.filter(list).size());
Assert.assertEquals(2, hints.filter(list).size());
}
/**

View File

@@ -6,6 +6,6 @@ K:Devoid
K:Ingest
S:Mode$ Continuous | Affected$ Creature.Colorless+Other+YouCtrl | AddPower$ 1 | Description$ Other colorless creatures you control get +1/+0.
SVar:PlayMain1:TRUE
DeckHints:Type$Processor
DeckHints:Type$Processor & Keyword$Devoid & Color$Colorless
SVar:Picture:http://www.wizards.com/global/images/magic/general/ruination_guide.jpg
Oracle:Devoid (This card has no color.)\nIngest (Whenever this creature deals combat damage to a player, that player exiles the top card of his or her library.)\nOther colorless creatures you control get +1/+0.

View File

@@ -127,7 +127,6 @@ public class CardRanker {
double synergyScore = 0.0;
synergyScore += getScoreForDeckHints(card, otherCards);
synergyScore += getScoreForBuffedBy(card, otherCards);
return synergyScore;
}
@@ -135,7 +134,7 @@ public class CardRanker {
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) {
if (hints != null && hints.isValid()) {
final List<PaperCard> comboCards = hints.filter(otherCards);
if (comboCards.size() > 0) {
score = comboCards.size() * 10;
@@ -144,22 +143,6 @@ public class CardRanker {
return score;
}
private double getScoreForBuffedBy(PaperCard card, Iterable<PaperCard> otherCards) {
double matchBuffScore = 0.0;
Iterable<Map.Entry<String, String>> vars = card.getRules().getMainPart().getVariables();
for (Map.Entry<String, String> var : vars) {
if (var.getKey().equals("BuffedBy")) {
String buff = var.getValue();
final Iterable<PaperCard> buffers = Iterables.filter(otherCards,
Predicates.compose(CardRulesPredicates.subType(buff), PaperCard.FN_GET_RULES));
if (Iterables.size(buffers) > 0) {
matchBuffScore = Iterables.size(buffers) * 3;
}
}
}
return matchBuffScore;
}
private List<PaperCard> sortAndCreateList(List<Pair<Double, PaperCard>> cardScores) {
Collections.sort(cardScores, Collections.reverseOrder(new CardRankingComparator()));

View File

@@ -558,12 +558,12 @@ public class LimitedDeckBuilder extends DeckGeneratorBase {
if (ai.getRemRandomDecks()) {
final List<PaperCard> comboCards = new ArrayList<PaperCard>();
if (ai.getDeckNeeds() != null
&& ai.getDeckNeeds().getType() != DeckHints.Type.NONE) {
&& ai.getDeckNeeds().isValid()) {
final DeckHints needs = ai.getDeckNeeds();
comboCards.addAll(needs.filter(deckList));
}
if (ai.getDeckHints() != null
&& ai.getDeckHints().getType() != DeckHints.Type.NONE) {
&& ai.getDeckHints().isValid()) {
final DeckHints hints = ai.getDeckHints();
comboCards.addAll(hints.filter(deckList));
}