It is currently 14 Sep 2025, 14:39
   
Text Size

Drafting

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

Re: Drafting

Postby delirimouse » 19 Dec 2011, 05:35

It is my understanding that no one has taught the AI to decide which non-basic lands are good for the deck. Thus it might throw a Badlands into its UW deck not realizing this is a bad idea.

(But this could easily be incorrect, I in no way program for Forge)
delirimouse
 
Posts: 39
Joined: 30 Aug 2011, 23:33
Has thanked: 0 time
Been thanked: 3 times

Re: Drafting

Postby Sloth » 19 Dec 2011, 07:21

delirimouse wrote:It is my understanding that no one has taught the AI to decide which non-basic lands are good for the deck. Thus it might throw a Badlands into its UW deck not realizing this is a bad idea.

(But this could easily be incorrect, I in no way program for Forge)
You are correct delirimouse. And I've already answered this question, juzamjedi:

Sloth wrote:
juzamjedi wrote:Slightly less important but worth asking: does AI draft lands in its colors now too?
Unfortunately the AI will not recognize lands in it's colors, which is not unimportand since in my testing the AI did include some drafted (late picked) lands in the decks and most of them were pretty useless (off color duals and manlands). So if you want to make your cube really is AI friendly, color aligned lands would have to go. :(
User avatar
Sloth
Programmer
 
Posts: 3498
Joined: 23 Jun 2009, 19:40
Has thanked: 125 times
Been thanked: 507 times

Re: Drafting

Postby juzamjedi » 19 Dec 2011, 23:08

I am VERY hesitant to remove dual lands and fetchlands. They do so much to make your mana better and allow you to play greedy color cards (2UUU for Future Sight in the same deck with 2WW for Wrath of God, etc.). Mana (and the color wheel) is THE defining feature of MTG and mana fixing is so important to casting your spells.

I could see the point of taking out some of the color-aligned tap-lands. They're powerful and will help your mana a lot, but coming into play tapped is bad and AI has a tendency to animate manlands more often than it should.

I think at this point we should try to improve AI to draft mana-fixing lands. Is mana coded in a special way like {W} {U} etc so that AI can pick lands that produce the colors they are drafting? Also have the AI pick lands that have a land type in its rules text that matches what colors are drafted {Plains} etc

Edit: humorously, I just found out that when you put {} around W you get {W}
juzamjedi
Tester
 
Posts: 575
Joined: 13 Nov 2008, 08:35
Has thanked: 6 times
Been thanked: 8 times

Re: Drafting

Postby Rob Cashwalker » 20 Dec 2011, 06:25

Here's the beginning of a revised draft rating alorithm:
Code: Select all
public class LiveDraftRatings {
    private Map<String,CardRules> myDraftedCards = new HashMap<String, CardRules>();
    private Map<String, Integer> myDraftedRatings = new HashMap<String, Integer>();
    private int ColorCounts[] = {0,0,0,0,0,0};
   
    public void addCard (CardRules crCard, String fmtID) {
        String cardName = crCard.getName() + "|" + fmtID;
        int cardRating = 50;    // base rating
       
        boolean cardNotPresent = true;
        if (myDraftedRatings.size() > 0) {
            if (myDraftedRatings.containsKey(cardName)) {
                cardRating = myDraftedRatings.get(cardName);
                cardRating += 8;   // bonus this card when drafted in multiples
                cardNotPresent = false;
            }
           
            boolean noSharedColor = true;
            boolean noSharedSubType = true;
            for (String cn : myDraftedCards.keySet()) {
                CardRules cr = myDraftedCards.get(cn);
                CardColor cc = cr.getColor();
               
                if (crCard.getColor().sharesColorWith(cc)) {
                    myDraftedRatings.put(cn, myDraftedRatings.get(cn) + 1); // bonus other cards that share a color
                   
                    noSharedColor = false;
                }
               
               CardType ct = cr.getType();
               if (crCard.getType().sharesSubTypeWith(ct)) {
                   myDraftedRatings.put(cn,  myDraftedRatings.get(cn) + 1); // bonus other cards that share a sub type
                   cardRating += 2;     // bonus this card when drafted with like sub types (detects themes)
               }
            }
           
            if (noSharedColor && !crCard.getColor().isColorless()) {
                cardRating -= 2;    // deduct for off-color picks
            }
           
            if (noSharedSubType && !crCard.getType().getSubTypes().isEmpty()) {
                cardRating -= 2;    // deduct for not sharing sub types (a theme indicator)
            }
        }
       
        // count colors and bonus this card when drafted with like colors
        if (crCard.getColor().isWhite()) {
            ColorCounts[0] += 1;
           
            if (ColorCounts[0] > 4)
                cardRating += 1;
            if (ColorCounts[0] > 8)
                cardRating += 2;
            if (ColorCounts[0] > 16)
                cardRating += 4;
        }
        if (crCard.getColor().isBlue()) {
            ColorCounts[1] += 1;
           
            if (ColorCounts[1] > 4)
                cardRating += 1;
            if (ColorCounts[1] > 8)
                cardRating += 2;
            if (ColorCounts[1] > 16)
                cardRating += 4;
        }
        if (crCard.getColor().isBlack()) {
            ColorCounts[2] += 1;
           
            if (ColorCounts[2] > 4)
                cardRating += 1;
            if (ColorCounts[2] > 8)
                cardRating += 2;
            if (ColorCounts[2] > 16)
                cardRating += 4;           
        }
        if (crCard.getColor().isRed()) {
            ColorCounts[3] += 1;
           
            if (ColorCounts[3] > 4)
                cardRating += 1;
            if (ColorCounts[3] > 8)
                cardRating += 2;
            if (ColorCounts[3] > 16)
                cardRating += 4;
        }
        if (crCard.getColor().isGreen()) {
            ColorCounts[4] += 1;
           
            if (ColorCounts[4] > 4)
                cardRating += 1;
            if (ColorCounts[4] > 8)
                cardRating += 2;
            if (ColorCounts[4] > 16)
                cardRating += 4;
        }
        if (crCard.getColor().isColorless()) {
            ColorCounts[5] += 1;
           
            if (ColorCounts[5] > 4)
                cardRating += 1;
            if (ColorCounts[5] > 8)
                cardRating += 2;
            if (ColorCounts[5] > 16)
                cardRating += 4;
        }

       
        if (myDraftedCards.size() > 10)
            cardRating += 2;    // bonus after a draft strategy has been developed
           
        if (myDraftedCards.size() > 20) // more bonus for later picks
            cardRating += 2;
       
        if (cardNotPresent)
            myDraftedCards.put(cardName, crCard);
       
        myDraftedRatings.put(cardName, cardRating);
    }
}
What other kinds of metrics do you think I could consider?
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: Drafting

Postby Sloth » 20 Dec 2011, 12:18

Rob Cashwalker wrote:Here's the beginning of a revised draft rating alorithm:
Code: Select all
public class LiveDraftRatings {
    private Map<String,CardRules> myDraftedCards = new HashMap<String, CardRules>();
    private Map<String, Integer> myDraftedRatings = new HashMap<String, Integer>();
    private int ColorCounts[] = {0,0,0,0,0,0};
   
    public void addCard (CardRules crCard, String fmtID) {
        String cardName = crCard.getName() + "|" + fmtID;
        int cardRating = 50;    // base rating
       
        boolean cardNotPresent = true;
        if (myDraftedRatings.size() > 0) {
            if (myDraftedRatings.containsKey(cardName)) {
                cardRating = myDraftedRatings.get(cardName);
                cardRating += 8;   // bonus this card when drafted in multiples
                cardNotPresent = false;
            }
           
            boolean noSharedColor = true;
            boolean noSharedSubType = true;
            for (String cn : myDraftedCards.keySet()) {
                CardRules cr = myDraftedCards.get(cn);
                CardColor cc = cr.getColor();
               
                if (crCard.getColor().sharesColorWith(cc)) {
                    myDraftedRatings.put(cn, myDraftedRatings.get(cn) + 1); // bonus other cards that share a color
                   
                    noSharedColor = false;
                }
               
               CardType ct = cr.getType();
               if (crCard.getType().sharesSubTypeWith(ct)) {
                   myDraftedRatings.put(cn,  myDraftedRatings.get(cn) + 1); // bonus other cards that share a sub type
                   cardRating += 2;     // bonus this card when drafted with like sub types (detects themes)
               }
            }
           
            if (noSharedColor && !crCard.getColor().isColorless()) {
                cardRating -= 2;    // deduct for off-color picks
            }
           
            if (noSharedSubType && !crCard.getType().getSubTypes().isEmpty()) {
                cardRating -= 2;    // deduct for not sharing sub types (a theme indicator)
            }
        }
       
        // count colors and bonus this card when drafted with like colors
        if (crCard.getColor().isWhite()) {
            ColorCounts[0] += 1;
           
            if (ColorCounts[0] > 4)
                cardRating += 1;
            if (ColorCounts[0] > 8)
                cardRating += 2;
            if (ColorCounts[0] > 16)
                cardRating += 4;
        }
        if (crCard.getColor().isBlue()) {
            ColorCounts[1] += 1;
           
            if (ColorCounts[1] > 4)
                cardRating += 1;
            if (ColorCounts[1] > 8)
                cardRating += 2;
            if (ColorCounts[1] > 16)
                cardRating += 4;
        }
        if (crCard.getColor().isBlack()) {
            ColorCounts[2] += 1;
           
            if (ColorCounts[2] > 4)
                cardRating += 1;
            if (ColorCounts[2] > 8)
                cardRating += 2;
            if (ColorCounts[2] > 16)
                cardRating += 4;           
        }
        if (crCard.getColor().isRed()) {
            ColorCounts[3] += 1;
           
            if (ColorCounts[3] > 4)
                cardRating += 1;
            if (ColorCounts[3] > 8)
                cardRating += 2;
            if (ColorCounts[3] > 16)
                cardRating += 4;
        }
        if (crCard.getColor().isGreen()) {
            ColorCounts[4] += 1;
           
            if (ColorCounts[4] > 4)
                cardRating += 1;
            if (ColorCounts[4] > 8)
                cardRating += 2;
            if (ColorCounts[4] > 16)
                cardRating += 4;
        }
        if (crCard.getColor().isColorless()) {
            ColorCounts[5] += 1;
           
            if (ColorCounts[5] > 4)
                cardRating += 1;
            if (ColorCounts[5] > 8)
                cardRating += 2;
            if (ColorCounts[5] > 16)
                cardRating += 4;
        }

       
        if (myDraftedCards.size() > 10)
            cardRating += 2;    // bonus after a draft strategy has been developed
           
        if (myDraftedCards.size() > 20) // more bonus for later picks
            cardRating += 2;
       
        if (cardNotPresent)
            myDraftedCards.put(cardName, crCard);
       
        myDraftedRatings.put(cardName, cardRating);
    }
}
What other kinds of metrics do you think I could consider?
What's the goal of myDraftedRatings? What do you want to use it for?
User avatar
Sloth
Programmer
 
Posts: 3498
Joined: 23 Jun 2009, 19:40
Has thanked: 125 times
Been thanked: 507 times

Re: Drafting

Postby Rob Cashwalker » 20 Dec 2011, 15:13

OK, I'll try to do some 'splaining....

This class, LiveDraftRatings will only exist during the time the player is drafting. Each card picked will be sent through the addCard method for analysis. Short of doing some funky wrapper-class, I use the two hash maps to store the two main things I need to know about each time a card comes through.

myDraftedCards simply associates the cardName (which may also include a set code or a cube name) with a reference to the card object which lets me examine things like color and type.

myDraftedRatings associates the cardName (same one) with a temporary rating.

As cards get picked, cards start at a default rating. (may swap the 50 for a lookup in the CardRatingsData class (mental note, rename that class)) Based on some ideas we had about rating the cards against the other cards picked, the temporary ratings have the opportunity to swing higher or lower, based on the criteria I commented on. I need more reasons to lower a rating....

I added a method to CardColor, sharesColorWith. It basically does this:
Code: Select all
boolean sharesColorWith(CardColor ccOther) {
  if (this.isWhite && ccOther.isWhite)
    return true;
  if (this.isBlue && ccOther.isBlue)
    return true;
  ...

  return false;
}
A similar kind of check was added to CardType, to check sub types. Together, this will hopefully detect the player drafting a Green Elf deck, for example.

If the card wasn't already picked, add it to the myDraftedCards. After examining all aspects of a picked card, its new temporary rating is put into myDraftedRatings.

When the draft is done, another method will be used to massage the ratings (enforce min/max 0/100) and integrate them into the main CardRatingsData class. (which will get uploaded to cardforge.org on a periodic basis, not during draft)

Right now, it's for analyzing the human's picks. HOWEVER, the essence of this algorithm can be used in the AI side. For each base rating of the cards presented in a pack, this algorithm could adjust the perception of the ratings based on what it has already picked. I will probably split the rating algorithm into its own 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: Drafting

Postby friarsol » 20 Dec 2011, 15:31

In this drafting AI, where's the best place to consider the Color Identity (Color of Mana in Activated Abilities, or Produced by Mana Abilities)? I thought I had seen a color identity function floating around at some point, and it would be the easiest way to allow Moxen and On-Color Lands to not be removed from Draft Cubes.
friarsol
Global Moderator
 
Posts: 7593
Joined: 15 May 2010, 04:20
Has thanked: 243 times
Been thanked: 965 times

Re: Drafting

Postby Rob Cashwalker » 20 Dec 2011, 15:39

Yeah, that's something I'd like to consider.

I recall in the drafting AI, I had some means of identifying in-color lands by iterating their ManaAbilities or something. It was cumbersome. If that method was available for the CardRules object, that would be very good. It also would identify in-color artifacts.

I also would try to match keywords... bonus when drafting multiple flyers...
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: Drafting

Postby Sloth » 20 Dec 2011, 16:36

Rob Cashwalker wrote:When the draft is done, another method will be used to massage the ratings (enforce min/max 0/100) and integrate them into the main CardRatingsData class. (which will get uploaded to cardforge.org on a periodic basis, not during draft)
I don't understand the point in making most of these calculatings for the rating data base. For example: Why do all picked cards get a +2 ranking after the 10th pick?

Rob Cashwalker wrote:Right now, it's for analyzing the human's picks. HOWEVER, the essence of this algorithm can be used in the AI side. For each base rating of the cards presented in a pack, this algorithm could adjust the perception of the ratings based on what it has already picked. I will probably split the rating algorithm into its own method.
This is the place, where most of the function makes sense.
User avatar
Sloth
Programmer
 
Posts: 3498
Joined: 23 Jun 2009, 19:40
Has thanked: 125 times
Been thanked: 507 times

Re: Drafting

Postby Rob Cashwalker » 20 Dec 2011, 16:58

I don't understand the point in making most of these calculatings for the rating data base. For example: Why do all picked cards get a +2 ranking after the 10th pick?
I figure by that that time, the cards being picked are probably important cards. Mind you, if it was a default last-pick-of-a-pack, then the off color and off-type deductions would likely negate the +2 for being more than 10picks. BTW, it's not exactly the 10th pick.. if you picked multiples of a card during the first 10 picks, the size of the temporary ratings list isn't 10, it may be more like 8 or 9....

The question becomes, how should we score a card that the human picks early and how should that score be any different if it's picked again later, or if it's picked because it's on-theme with the other picks. The old way gave the highest score to the early picks and lowest score to the last pick. The method I propose now is to allow the later picks to influence the rating of earlier picks. Cards that work together get better ratings during this draft than the cards that don't.
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: Drafting

Postby Sloth » 20 Dec 2011, 19:03

Rob Cashwalker wrote:I figure by that that time, the cards being picked are probably important cards. Mind you, if it was a default last-pick-of-a-pack, then the off color and off-type deductions would likely negate the +2 for being more than 10picks. BTW, it's not exactly the 10th pick.. if you picked multiples of a card during the first 10 picks, the size of the temporary ratings list isn't 10, it may be more like 8 or 9....
The first pick in the second booster is important, because it has to compete with 14 other cards, the last pick of booster one holds no information at all.

Rob Cashwalker wrote:The question becomes, how should we score a card that the human picks early and how should that score be any different if it's picked again later, ...
I don't know if it has been discussed before, but a simple system would be to give each card that was not picked -1 to its score and each card picked +X where X is the number of other cards in the pack.

Rob Cashwalker wrote:Cards that work together get better ratings during this draft than the cards that don't.
If the product is a draft rating for each card, the whole working together information is lost. It should actually be the reverse: if the human late-picks the mediocre elf card A into a pool of elf cards, the rating of card A should be lower than normal.
User avatar
Sloth
Programmer
 
Posts: 3498
Joined: 23 Jun 2009, 19:40
Has thanked: 125 times
Been thanked: 507 times

Re: Drafting

Postby delirimouse » 20 Dec 2011, 22:30

There are a lot of linear keywords, i.e. keywords that work better if you have a lot of them (for example, you listed flying, which definitely has that). Would you like me to make a list of all the keywords I think are linear, perhaps with a numerical indication of how linear they are, so that you can encourage clumping of that sort of thing?

Edited to add:

Okay I went and made something like that for the past few blocks and evergreen keywords. Below I draw attention to the relevant linear mechanics and creature types that I think are relevant. I tried to rate the importance of the linearity on a scale from 1 to 5.

Even in the most extreme case (Infect), these ratings should not completely overshadow the base pick rating. Something like this might work:

Scale the inherent rating of cards from draft pick data to a 0 to 10 scale so that the distribution is uniform. After filtering based on color, the perceived rating of a card to a bot should then be something like 2^base_rating + (Modifier for synergy), where the modifier can be positive or negative of course.

This way if a card is truly exceptional, it will be picked regardless of synergy, e.g., no matter how many fliers I have I should always pick Batterskull.



Evergreen:

First Strike - 2

Flying - 2

Reach - value inversely proportionate to the number of fliers you have

Innistrad:

Type: Zombie -- 2
Type: Spirit -- 1
Type: Human -- 3 (also likes equipment)
Type: Vampire -- 1
Type: Werewolf -- 1


Scars of Mirrodin:

Infect - 5 - also increases in value with equipment

Equipment - increases in value with infect

Metalcraft - value proportional to the number of artifacts you have


Zendikar:

Type: Ally - 5

Shards of Alara:

Exalted - 3


----------------------------------

I would discourage rewarding clumping creature types except those specifically encouraged within the blocks, as it is worthless 99% of the time. Recent notable exceptions are listed above.
delirimouse
 
Posts: 39
Joined: 30 Aug 2011, 23:33
Has thanked: 0 time
Been thanked: 3 times

Re: Drafting

Postby juzamjedi » 23 Dec 2011, 21:36

Yes - some cards are so good you take them no matter what your deck already has in it. Maybe think of this as the Base Value for the draft pick.

Supporting linears is good, but I think we could do it all more systematically by just using covariance of cards already selected during a draft. Something like:
Draft Value = Base Value + Covariance(Card1) + Covariance(Card2)...

Covariance could be estimated by human draft picks, after the end of the draft (and updated each draft). Then this is used for future AI draft picks.

An example that is obvious if you draft often, but would not be obvious to computer: there is a very strong, positive correlation between Wild Nacatl and Taiga.
juzamjedi
Tester
 
Posts: 575
Joined: 13 Nov 2008, 08:35
Has thanked: 6 times
Been thanked: 8 times

Re: Drafting

Postby delirimouse » 23 Dec 2011, 23:21

Computing the covariance would indeed be a very smart way to get the computer to learn to draft smart decks. I don't, however, think the draft data collector actually takes this information (Rob will tell me if I am wrong).

I think it is important to just get some system that uses human pick data in place so that we stop getting last pick Garruks, and then as people play a bunch they can observe things the AI does well and poorly and then the various knobs can be tuned accordingly.

Also, is it possible to see the current ratings of cards based on data submission so that it can be verified that is working correctly? I recall something like this was posted before for the old algorithm, but there was a problem with the algorithm that made it produce less useful numbers.
delirimouse
 
Posts: 39
Joined: 30 Aug 2011, 23:33
Has thanked: 0 time
Been thanked: 3 times

Re: Drafting

Postby Rob Cashwalker » 26 Dec 2011, 02:38

No matter what the rating algorithm will be, the MySQL database portion is ready, with an average of 8 data points per card. There is a page for viewing the data (just dumps the averaged data).
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

PreviousNext

Return to Forge

Who is online

Users browsing this forum: No registered users and 79 guests

Main Menu

User Menu

Our Partners


Who is online

In total there are 79 users online :: 0 registered, 0 hidden and 79 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 79 guests

Login Form