It is currently 10 Sep 2025, 23:22
   
Text Size

CardPrinted, Preicates and The good old fashioned filter?

Post MTG Forge Related Programming Questions Here

Moderators: timmermac, Blacksmith, KrazyTheFox, Agetian, friarsol, CCGHQ Admins

CardPrinted, Preicates and The good old fashioned filter?

Postby Rob Cashwalker » 26 Sep 2011, 16:44

As I'm about to begin revising the draft, I come up to a TODO, that says it should be converted from using heavy Card objects....

How do I filter a List<CardPrinted>? I want to pull out cards based on the AI SVars, and then filter for card types and chosen colors.
The Force will be with you, Always.
User avatar
Rob Cashwalker
Programmer
 
Posts: 2167
Joined: 09 Sep 2008, 15:09
Location: New York
Has thanked: 5 times
Been thanked: 40 times

Re: CardPrinted, Preicates and The good old fashioned filter

Postby Max mtg » 26 Sep 2011, 19:15

Code: Select all
List<CardPrinted> source = getSourceList();
Predicate<CardRules> filterAllowAiDeck = CardRules.Predicates.isKeptInAiDecks;
Predicate<CardRules> filterGreen = CardRules.Predicates.Presets.isGreen;
Predicate<CardRules> filterCreatures = CardRules.Predicates.Presets.isCreature;

List<CardPrinted> cardsAiSupports = filterAllowAiDeck.select(CardDb.getAllUniqueCards(), CardPrinted.fnGetRules); // without reprints
List<CardPrinted> mightWantToPutIntoDeck = Predicate.and(filterGreen, filterCreatures).select(cardsAiSupports, CardPrinted.fnGetRules);
Predicates are like filters, but more versatile - they allow you to build an expression tree and filter the cards you need in a single pass.

Once you have built a predicate, you may filter with select method. There are some variations of select: top() - will return the 1st matching object, any() will return true as soon as a matching object is found, split() will divide objects into two lists - one with matching elements, other with non-matching ones.

There some are situations when you want to filter types that contain the one you would like to make checks about, as in this expample want to check properties of CardRules, but have a list of CardPrinted. In that case use the second overload of select which accepts a lambda besides the Iterable to be filtered. That lambda should hold a function that accesses the type the predicate was build for.

The third overload allows not only access the type inside a container, but get a list of some different types, not the container itself, for instance one can select only the names of cards that are red instants.
Single class for single responsibility.
Max mtg
Programmer
 
Posts: 1997
Joined: 02 Jul 2011, 14:26
Has thanked: 173 times
Been thanked: 334 times

Re: CardPrinted, Preicates and The good old fashioned filter

Postby Rob Cashwalker » 26 Sep 2011, 20:31

So I see in the CardPrinted Object are some of the Preset Predicates for rarity and name... trying to add my own preset based on the ones present didn't compile.. complained I didn't have a constructor or something. From your example, I guess the CardRules class contains a preset to do filter by card type? isCreature is fine and dandy, but what about looking for zombies? (Note I tried to dig around in the Deck Editor filtering but it seemed like it wasn't filtered the same way.
The Force will be with you, Always.
User avatar
Rob Cashwalker
Programmer
 
Posts: 2167
Joined: 09 Sep 2008, 15:09
Location: New York
Has thanked: 5 times
Been thanked: 40 times

Re: CardPrinted, Preicates and The good old fashioned filter

Postby Max mtg » 26 Sep 2011, 20:51

Yes, CardPrinted itself holds no other information, cause the rest is kept in CardRules (a common part shared by all the prints of a single card). So CardPrinted has only predicate templates for name, rarity and sets.
The cases I met frequently were moved to presets (to avoid creating the same filter over and over). To filter cards by a subtype use
Code: Select all
Predicate<CardRules> f111 = CardRules.Predicates.subType("Goblin");
do svn up for CardRules - I've just commined the version with default string operator (before that there was only a version of subType(...) with 2 parameters)

DeckEditor filters cards differently, it just takes the full type string from each card and looks for substring user typed.

Which preset were you trying to add and where?
Single class for single responsibility.
Max mtg
Programmer
 
Posts: 1997
Joined: 02 Jul 2011, 14:26
Has thanked: 173 times
Been thanked: 334 times

Re: CardPrinted, Preicates and The good old fashioned filter

Postby Rob Cashwalker » 27 Sep 2011, 00:01

OK, I think I get it...

Now I know why it failed.. I was trying to add the predicate to CardPrinted, when it should be CardRules... Not that it needed to be added of course, I just couldn't find the card type as an existing predicate...
The Force will be with you, Always.
User avatar
Rob Cashwalker
Programmer
 
Posts: 2167
Joined: 09 Sep 2008, 15:09
Location: New York
Has thanked: 5 times
Been thanked: 40 times

Re: CardPrinted, Preicates and The good old fashioned filter

Postby Max mtg » 27 Sep 2011, 00:41

Alright, and grats on post 2000!

The what really needs to be added to CardRules is the flag of card having two sides. Will need this for for booster generation at least.
Single class for single responsibility.
Max mtg
Programmer
 
Posts: 1997
Joined: 02 Jul 2011, 14:26
Has thanked: 173 times
Been thanked: 334 times

Re: CardPrinted, Preicates and The good old fashioned filter

Postby Rob Cashwalker » 27 Sep 2011, 04:07

Still stuck....

What exact code would replace the following: (from BoosterDraftAI.choose, assume chooseFrom parameter becomes a List<CardPrinted> passed from the internals of the draft)
Code: Select all
CardList AIPlayables = chooseFrom.filter(new CardListFilter() {
            public boolean addCard(Card c) {
               if (c.getSVar("RemAIDeck").equals("True") || c.getSVar("RemRandomDeck").equals("True"))
                  return false;
                return true;
            }
        });
How are the lists sorted? How to implement a sorting method?
The Force will be with you, Always.
User avatar
Rob Cashwalker
Programmer
 
Posts: 2167
Joined: 09 Sep 2008, 15:09
Location: New York
Has thanked: 5 times
Been thanked: 40 times

Re: CardPrinted, Preicates and The good old fashioned filter

Postby Max mtg » 27 Sep 2011, 10:51

Rob Cashwalker wrote:Still stuck....

What exact code would replace the following: (from BoosterDraftAI.choose, assume chooseFrom parameter becomes a List<CardPrinted> passed from the internals of the draft)
Code: Select all
CardList AIPlayables = chooseFrom.filter(new CardListFilter() {
            public boolean addCard(Card c) {
               if (c.getSVar("RemAIDeck").equals("True") || c.getSVar("RemRandomDeck").equals("True"))
                  return false;
                return true;
            }
        });
How are the lists sorted? How to implement a sorting method?
Predicate<CardRules> aiPlayablesFilter = Predicates.and(CardRules.Predicates.isKeptInAiDecks, CardRules.Predicates.isKeptInRandomDecks);
List<CardPrinted> aiPlayablesList = aiPlayablesFilter.select(someCards, CardPrinted.fnGetRules)


If you really asked about sorting, then use Collections.sort
Single class for single responsibility.
Max mtg
Programmer
 
Posts: 1997
Joined: 02 Jul 2011, 14:26
Has thanked: 173 times
Been thanked: 334 times


Return to Developer's Corner

Who is online

Users browsing this forum: No registered users and 50 guests

Main Menu

User Menu

Our Partners


Who is online

In total there are 50 users online :: 0 registered, 0 hidden and 50 guests (based on users active over the past 10 minutes)
Most users ever online was 7967 on 09 Sep 2025, 23:08

Users browsing this forum: No registered users and 50 guests

Login Form