package forge; import forge.card.cardFactory.CardFactoryUtil; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import com.google.code.jyield.Generator; import com.google.code.jyield.Yieldable; /** * <p>CardList class.</p> * * @author Forge * @version $Id: $ */ public class CardList implements Iterable<Card> { /** * <p>iterator.</p> * * @return a {@link java.util.Iterator} object. */ public Iterator<Card> iterator() { return list.iterator(); } private ArrayList<Card> list = new ArrayList<Card>(); /** * <p>Constructor for CardList.</p> */ public CardList() { } /** * <p>Constructor for CardList.</p> * * @param c a {@link forge.Card} object. */ public CardList(Card... c) { addAll(c); } /** * <p>Constructor for CardList.</p> * * @param al a {@link java.util.ArrayList} object. */ public CardList(ArrayList<Card> al) { addAll(al.toArray()); } /** * Make a shallow copy of an Iterable's contents; this could be another * CardList. * * @param iterable we traverse this and copy its contents into a local * field. */ public CardList(Iterable<Card> iterable) { for (Card card : iterable) { add(card); } } /** * <p>Constructor for CardList.</p> * * @param c an array of {@link java.lang.Object} objects. */ public CardList(Object[] c) { addAll(c); } /** * Create a CardList from a finite generator of Card instances. * * We ignore null values produced by the generator. * * @param generator a non-infinite generator of Card instances. */ public CardList(Generator<Card> generator) { // Generators yield their contents to a Yieldable. Here, // we create a quick Yieldable that adds the information it // receives to this CardList's list field. Yieldable<Card> valueReceiver = new Yieldable<Card>() { @Override public void yield(Card card) { if (card != null) { list.add(card); } } }; generator.generate(valueReceiver); } /** * Create a cardlist with an initial estimate of its maximum size. * * @param size an initialize estimate of its maximum size */ public CardList(int size) { list = new ArrayList<Card>(size); } /** * <p>Get any cards that exist in the passed in sets list.</p> * * @param sets a {@link java.util.ArrayList} object. * @return a {@link forge.CardList} object. */ public CardList getSets(ArrayList<String> sets) { CardList list = new CardList(); for (Card c : this) { for (SetInfo set : c.getSets()) if (sets.contains(set.toString())) { list.add(c); break; } } return list; }//getSets() /** * <p>getColor.</p> * * @param cardColor a {@link java.lang.String} object. * @return a {@link forge.CardList} object. */ public CardList getColor(String cardColor) { CardList list = new CardList(); for (Card c : this) { if (cardColor.equals("Multicolor") && c.getColor().size() > 1) list.add(c); else if (c.isColor(cardColor) && c.getColor().size() == 1) list.add(c); } return list; }//getColor() /** * <p>getOnly2Colors.</p> * * @param clr1 a {@link java.lang.String} object. * @param clr2 a {@link java.lang.String} object. * @return a {@link forge.CardList} object. */ public CardList getOnly2Colors(final String clr1, final String clr2) { CardList list = new CardList(); list.addAll(this); CardListFilter clrF = new CardListFilter() { public boolean addCard(Card c) { ArrayList<Card_Color> cClrs = c.getColor(); for (int i = 0; i < cClrs.size(); i++) { if (!cClrs.get(i).toStringArray().get(0).equals(clr1) && !cClrs.get(i).toStringArray().get(0).equals(clr2)) return false; } return true; } }; return list.filter(clrF); } /** * <p>reverse.</p> */ public void reverse() { Collections.reverse(list); } /** {@inheritDoc} */ public boolean equals(Object a) { if (a instanceof CardList) { CardList b = (CardList) a; if (list.size() != b.size()) return false; for (int i = 0; i < list.size(); i++) if (!list.get(i).equals(b.get(i))) return false; return true; } else return false; } //removes one copy of that card /** * <p>remove.</p> * * @param cardName a {@link java.lang.String} object. */ public void remove(final String cardName) { CardList find = this.filter(new CardListFilter() { public boolean addCard(Card c) { return c.getName().equals(cardName); } }); if (0 < find.size()) this.remove(find.get(0)); else throw new RuntimeException("CardList : remove(String cardname), error - card name not found: " + cardName + " - contents of Arraylist:" + list); }//remove(String cardName) /** * <p>size.</p> * * @return a int. */ public int size() { return list.size(); } /** * <p>add.</p> * * @param c a {@link forge.Card} object. */ public void add(Card c) { list.add(c); } /** * <p>add.</p> * * @param n a int. * @param c a {@link forge.Card} object. */ public void add(int n, Card c) { list.add(n, c); } /** * addAll(CardList) - lets you add one CardList to another directly * * @param in - CardList to add to the current CardList */ public void addAll(CardList in) { addAll(in.toArray()); } /** * <p>contains.</p> * * @param c a {@link forge.Card} object. * @return a boolean. */ public boolean contains(Card c) { return list.contains(c); } //probably remove getCard() in the future /** * <p>getCard.</p> * * @param index a int. * @return a {@link forge.Card} object. */ public Card getCard(int index) { return list.get(index); } /** * <p>get.</p> * * @param i a int. * @return a {@link forge.Card} object. */ public Card get(int i) { return getCard(i); } /** * <p>addAll.</p> * * @param c an array of {@link java.lang.Object} objects. */ public void addAll(Object c[]) { for (int i = 0; i < c.length; i++) list.add((Card) c[i]); } /** * <p>containsName.</p> * * @param c a {@link forge.Card} object. * @return a boolean. */ public boolean containsName(Card c) { return containsName(c.getName()); } /** * <p>containsName.</p> * * @param name a {@link java.lang.String} object. * @return a boolean. */ public boolean containsName(String name) { for (int i = 0; i < size(); i++) if (getCard(i).getName().equals(name)) return true; return false; } //returns new subset of all the cards with the same name /** * <p>getName.</p> * * @param name a {@link java.lang.String} object. * @return a {@link forge.CardList} object. */ public CardList getName(String name) { CardList c = new CardList(); for (int i = 0; i < size(); i++) if (getCard(i).getName().equals(name)) c.add(getCard(i)); return c; } //returns new subset of all the cards that have a different name /** * <p>getNotName.</p> * * @param name a {@link java.lang.String} object. * @return a {@link forge.CardList} object. */ public CardList getNotName(String name) { CardList c = new CardList(); for (int i = 0; i < size(); i++) if (!getCard(i).getName().equals(name)) c.add(getCard(i)); return c; } /** * <p>getImageName.</p> * * @param name a {@link java.lang.String} object. * @return a {@link forge.CardList} object. */ public CardList getImageName(String name) { CardList c = new CardList(); for (int i = 0; i < size(); i++) if (getCard(i).getImageName().equals(name)) c.add(getCard(i)); return c; } /** * <p>getController.</p> * * @param player a {@link forge.Player} object. * @return a {@link forge.CardList} object. */ public CardList getController(final Player player) { return this.filter(new CardListFilter() { public boolean addCard(Card c) { return c.getController().isPlayer(player); } }); } /** * <p>getOwner.</p> * * @param player a {@link forge.Player} object. * @return a {@link forge.CardList} object. */ public CardList getOwner(final Player player) { return this.filter(new CardListFilter() { public boolean addCard(Card c) { return c.getOwner().isPlayer(player); } }); } /** * <p>getRarity.</p> * * @param rarity a {@link java.lang.String} object. * @return a {@link forge.CardList} object. */ public CardList getRarity(final String rarity) { return this.filter(new CardListFilter() { public boolean addCard(Card c) { // TODO spin off Mythic from Rare when the time comes String r = c.getSVar("Rarity"); return r.equals(rarity) || rarity.equals(Constant.Rarity.Rare) && r.equals(Constant.Rarity.Mythic); } }); } //cardType is like "Land" or "Goblin", returns a new CardList that is a subset of current CardList /** * <p>getType.</p> * * @param cardType a {@link java.lang.String} object. * @return a {@link forge.CardList} object. */ public CardList getType(final String cardType) { return this.filter(new CardListFilter() { public boolean addCard(Card c) { return c.isType(cardType); } }); } //cardType is like "Land" or "Goblin", returns a new CardList with cards that do not have this type /** * <p>getNotType.</p> * * @param cardType a {@link java.lang.String} object. * @return a {@link forge.CardList} object. */ public CardList getNotType(final String cardType) { return this.filter(new CardListFilter() { public boolean addCard(Card c) { return !c.isType(cardType); } }); } /** * <p>getPermanents.</p> * * @return a {@link forge.CardList} object. */ public CardList getPermanents() { return this.filter(new CardListFilter() { public boolean addCard(Card c) { return c.isPermanent(); } }); } /** * <p>getKeyword.</p> * * @param keyword a {@link java.lang.String} object. * @return a {@link forge.CardList} object. */ public CardList getKeyword(final String keyword) { return this.filter(new CardListFilter() { public boolean addCard(Card c) { return c.hasKeyword(keyword); } }); } /** * <p>getNotKeyword.</p> * * @param keyword a {@link java.lang.String} object. * @return a {@link forge.CardList} object. */ public CardList getNotKeyword(final String keyword) { return this.filter(new CardListFilter() { public boolean addCard(Card c) { return !c.hasKeyword(keyword); } }); } //get all cards that have this string in their keywords /** * <p>getKeywordsContain.</p> * * @param keyword a {@link java.lang.String} object. * @return a {@link forge.CardList} object. */ public CardList getKeywordsContain(final String keyword) { return this.filter(new CardListFilter() { public boolean addCard(Card c) { return c.keywordsContain(keyword); } }); } //get all cards that don't have this string in their keywords /** * <p>getKeywordsDontContain.</p> * * @param keyword a {@link java.lang.String} object. * @return a {@link forge.CardList} object. */ public CardList getKeywordsDontContain(final String keyword) { return this.filter(new CardListFilter() { public boolean addCard(Card c) { return !c.keywordsContain(keyword); } }); } /** * <p>getTokens.</p> * * @return a {@link forge.CardList} object. */ public CardList getTokens() { return this.filter(new CardListFilter() { public boolean addCard(Card c) { return c.isToken(); } }); } /** * Create a new list of cards by applying a filter to this one. * * @param filt determines which cards are present in the resulting list * * @return a subset of this CardList whose items meet the filtering * criteria; may be empty, but never null. */ public CardList filter(CardListFilter filt) { return CardFilter.filter(this, filt); } /** * <p>toArray.</p> * * @return an array of {@link forge.Card} objects. */ public final Card[] toArray() { Card[] c = new Card[list.size()]; list.toArray(c); return c; } /** {@inheritDoc} */ @Override public String toString() { return list.toString(); } /** * <p>isEmpty.</p> * * @return a boolean. */ public boolean isEmpty() { return list.isEmpty(); } /** * <p>remove.</p> * * @param i a int. * @return a {@link forge.Card} object. */ public Card remove(int i) { return list.remove(i); } /** * <p>remove.</p> * * @param c a {@link forge.Card} object. */ public void remove(Card c) { list.remove(c); } /** * <p>clear.</p> */ public void clear() { list.clear(); } /** * <p>shuffle.</p> */ public void shuffle() { // reseed Random each time we want to Shuffle //MyRandom.random = MyRandom.random; Collections.shuffle(list, MyRandom.random); Collections.shuffle(list, MyRandom.random); Collections.shuffle(list, MyRandom.random); } /** * <p>sort.</p> * * @param c a {@link java.util.Comparator} object. */ public void sort(Comparator<Card> c) { Collections.sort(list, c); } /** * <p>getTargetableCards.</p> * * @param Source a {@link forge.Card} object. * @return a {@link forge.CardList} object. */ public CardList getTargetableCards(final Card Source) { return this.filter(new CardListFilter() { public boolean addCard(Card c) { return CardFactoryUtil.canTarget(Source, c); } }); } /** * <p>getValidCards.</p> * * @param Restrictions a {@link java.lang.String} object. * @param sourceController a {@link forge.Player} object. * @param source a {@link forge.Card} object. * @return a {@link forge.CardList} object. */ public CardList getValidCards(String Restrictions, final Player sourceController, final Card source) { return getValidCards(Restrictions.split(","), sourceController, source); } /** * <p>getValidCards.</p> * * @param Restrictions a {@link java.lang.String} object. * @param sourceController a {@link forge.Player} object. * @param source a {@link forge.Card} object. * @return a {@link forge.CardList} object. */ public CardList getValidCards(final String Restrictions[], final Player sourceController, final Card source) { return this.filter(new CardListFilter() { public boolean addCard(Card c) { return c.isValidCard(Restrictions, sourceController, source); } }); } /** * <p>getEquipMagnets.</p> * * @return a {@link forge.CardList} object. */ public CardList getEquipMagnets() { return this.filter(new CardListFilter() { public boolean addCard(Card c) { return (c.isCreature() && (c.getSVar("EquipMe").equals("Multiple") || (c.getSVar("EquipMe").equals("Once") && !c.isEquipped()))); } }); } /** * <p>getEnchantMagnets.</p> * * @return a {@link forge.CardList} object. */ public CardList getEnchantMagnets() { return this.filter(new CardListFilter() { public boolean addCard(Card c) { return (c.isCreature() && (c.getSVar("EnchantMe").equals("Multiple") || (c.getSVar("EnchantMe").equals("Once") && !c.isEnchanted()))); } }); } /** * <p>getTotalConvertedManaCost.</p> * * @return a int. */ public int getTotalConvertedManaCost() { int total = 0; for (int i = 0; i < size(); i++) { total += get(i).getCMC(); } return total; } /** * <p>getHighestConvertedManaCost.</p> * * @return a int. * @since 1.0.15 */ public int getHighestConvertedManaCost() { int total = 0; for (int i = 0; i < size(); i++) { total = Math.max(total, get(i).getCMC()); } return total; } /** * <p>getColored.</p> * * @return a {@link forge.CardList} object. */ public CardList getColored() { return this.filter(new CardListFilter() { public boolean addCard(Card c) { return (!c.isColorless()); } }); } }//end class CardList