"Poker" AI Results

This is a discussion on "Poker" AI Results within the Contests Board forums, part of the Community Boards category; This is the results thread for the contest at: at http://cboard.cprogramming.com/conte...mpetition.html Three programmers participated: Daved, jdragyn and whiteflags. Here's a ...

  1. #1
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072

    "Poker" AI Results

    This is the results thread for the contest at: at "Poker" AI competition

    Three programmers participated: Daved, jdragyn and whiteflags.

    Here's a result from a sample round:
    Code:
    +-------------+
    | Hand #1     |
    +-------------+
    Daved with $1000 is dealt 0.0843532
    jdragyn with $1000 is dealt 0.431715
    whiteflags with $1000 is dealt 0.159581
    jdragyn puts in $1 (blind) for a total of 1
    whiteflags folds.
    Daved folds.
    jdragyn takes the $1 pot.
    +-------------+
    | Hand #2     |
    +-------------+
    Daved with $1000 is dealt 0.429426
    jdragyn with $1000 is dealt 0.470077
    whiteflags with $1000 is dealt 0.666311
    whiteflags puts in $1 (blind) for a total of 1
    Daved folds.
    jdragyn folds.
    whiteflags takes the $1 pot.
    +-------------+
    | Hand #3     |
    +-------------+
    Daved with $1000 is dealt 0.0170904
    jdragyn with $1000 is dealt 0.964019
    whiteflags with $1000 is dealt 0.17185
    Daved puts in $1 (blind) for a total of 1
    jdragyn goes all-in with $1000 to 1000
    whiteflags folds.
    Daved folds.
    jdragyn takes the $1001 pot.
    +-------------+
    | Hand #4     |
    +-------------+
    Daved with $999 is dealt 0.763573
    jdragyn with $1001 is dealt 0.760033
    whiteflags with $1000 is dealt 0.703452
    jdragyn puts in $1 (blind) for a total of 1
    whiteflags folds.
    Daved folds.
    jdragyn takes the $1 pot.
    +-------------+
    | Hand #5     |
    +-------------+
    Daved with $999 is dealt 0.832331
    jdragyn with $1001 is dealt 0.796228
    whiteflags with $1000 is dealt 0.668783
    whiteflags puts in $1 (blind) for a total of 1
    Daved folds.
    jdragyn goes all-in with $1001 to 1001
    whiteflags goes all-in with $999 to 1000
    Show your cards!
    Total size of the pot is 2001
    jdragyn shows 0.796228
    whiteflags shows 0.668783
    jdragyn (all-in) wins $1000 from whiteflags
    +-------------+
    | Hand #6     |
    +-------------+
    Daved with $999 is dealt 0.810694
    jdragyn with $2001 is dealt 0.449477
    whiteflags is out.
    Daved puts in $1 (blind) for a total of 1
    jdragyn folds.
    Daved takes the $1 pot.
    +-------------+
    | Hand #7     |
    +-------------+
    Daved with $999 is dealt 0.987976
    jdragyn with $2001 is dealt 0.907956
    whiteflags is out.
    jdragyn puts in $1 (blind) for a total of 1
    Daved goes all-in with $999 to 999
    jdragyn goes all-in with $2000 to 2001
    Show your cards!
    Total size of the pot is 3000
    Daved shows 0.987976
    jdragyn shows 0.907956
    Daved (all-in) wins $999 from jdragyn
    jdragyn shows 0.907956
    +-------------+
    | Hand #8     |
    +-------------+
    Daved with $1998 is dealt 0.311747
    jdragyn with $1002 is dealt 0.0845668
    whiteflags is out.
    Daved puts in $1 (blind) for a total of 1
    jdragyn folds.
    Daved takes the $1 pot.
    +-------------+
    | Hand #9     |
    +-------------+
    Daved with $1998 is dealt 0.0577715
    jdragyn with $1002 is dealt 0.371441
    whiteflags is out.
    Daved puts in $1 (blind) for a total of 1
    jdragyn folds.
    Daved takes the $1 pot.
    +-------------+
    | Hand #10    |
    +-------------+
    Daved with $1998 is dealt 0.260201
    jdragyn with $1002 is dealt 0.0758385
    whiteflags is out.
    jdragyn puts in $1 (blind) for a total of 1
    Daved folds.
    jdragyn takes the $1 pot.
    +-------------+
    | Hand #11    |
    +-------------+
    Daved with $1998 is dealt 0.0833766
    jdragyn with $1002 is dealt 0.572375
    whiteflags is out.
    Daved puts in $1 (blind) for a total of 1
    jdragyn folds.
    Daved takes the $1 pot.
    +-------------+
    | Hand #12    |
    +-------------+
    Daved with $1998 is dealt 0.882473
    jdragyn with $1002 is dealt 0.268258
    whiteflags is out.
    Daved puts in $1 (blind) for a total of 1
    jdragyn folds.
    Daved takes the $1 pot.
    +-------------+
    | Hand #13    |
    +-------------+
    Daved with $1998 is dealt 0.916196
    jdragyn with $1002 is dealt 0.368267
    whiteflags is out.
    jdragyn puts in $1 (blind) for a total of 1
    Daved folds.
    jdragyn takes the $1 pot.
    +-------------+
    | Hand #14    |
    +-------------+
    Daved with $1998 is dealt 0.366405
    jdragyn with $1002 is dealt 0.798425
    whiteflags is out.
    Daved puts in $1 (blind) for a total of 1
    jdragyn goes all-in with $1002 to 1002
    Daved folds.
    jdragyn takes the $1003 pot.
    +-------------+
    | Hand #15    |
    +-------------+
    Daved with $1997 is dealt 0.704672
    jdragyn with $1003 is dealt 0.465835
    whiteflags is out.
    Daved puts in $1 (blind) for a total of 1
    jdragyn folds.
    Daved takes the $1 pot.
    +-------------+
    | Hand #16    |
    +-------------+
    Daved with $1997 is dealt 0.37611
    jdragyn with $1003 is dealt 0.875057
    whiteflags is out.
    jdragyn puts in $1 (blind) for a total of 1
    Daved folds.
    jdragyn takes the $1 pot.
    +-------------+
    | Hand #17    |
    +-------------+
    Daved with $1997 is dealt 0.755913
    jdragyn with $1003 is dealt 0.0829493
    whiteflags is out.
    Daved puts in $1 (blind) for a total of 1
    jdragyn folds.
    Daved takes the $1 pot.
    +-------------+
    | Hand #18    |
    +-------------+
    Daved with $1997 is dealt 0.438826
    jdragyn with $1003 is dealt 0.973266
    whiteflags is out.
    Daved puts in $1 (blind) for a total of 1
    jdragyn goes all-in with $1003 to 1003
    Daved folds.
    jdragyn takes the $1004 pot.
    +-------------+
    | Hand #19    |
    +-------------+
    Daved with $1996 is dealt 0.680746
    jdragyn with $1004 is dealt 0.915342
    whiteflags is out.
    jdragyn puts in $1 (blind) for a total of 1
    Daved folds.
    jdragyn takes the $1 pot.
    +-------------+
    | Hand #20    |
    +-------------+
    Daved with $1996 is dealt 0.887082
    jdragyn with $1004 is dealt 0.14481
    whiteflags is out.
    Daved puts in $1 (blind) for a total of 1
    jdragyn folds.
    Daved takes the $1 pot.
    +-------------+
    | Hand #21    |
    +-------------+
    Daved with $1996 is dealt 0.648823
    jdragyn with $1004 is dealt 0.680105
    whiteflags is out.
    Daved puts in $1 (blind) for a total of 1
    jdragyn goes all-in with $1004 to 1004
    Daved folds.
    jdragyn takes the $1005 pot.
    +-------------+
    | Hand #22    |
    +-------------+
    Daved with $1995 is dealt 0.305795
    jdragyn with $1005 is dealt 0.345225
    whiteflags is out.
    jdragyn puts in $1 (blind) for a total of 1
    Daved folds.
    jdragyn takes the $1 pot.
    +-------------+
    | Hand #23    |
    +-------------+
    Daved with $1995 is dealt 0.354656
    jdragyn with $1005 is dealt 0.182348
    whiteflags is out.
    Daved puts in $1 (blind) for a total of 1
    jdragyn folds.
    Daved takes the $1 pot.
    +-------------+
    | Hand #24    |
    +-------------+
    Daved with $1995 is dealt 0.498489
    jdragyn with $1005 is dealt 0.483902
    whiteflags is out.
    Daved puts in $1 (blind) for a total of 1
    jdragyn folds.
    Daved takes the $1 pot.
    +-------------+
    | Hand #25    |
    +-------------+
    Daved with $1995 is dealt 0.555864
    jdragyn with $1005 is dealt 0.0715354
    whiteflags is out.
    jdragyn puts in $1 (blind) for a total of 1
    Daved folds.
    jdragyn takes the $1 pot.
    +-------------+
    | Hand #26    |
    +-------------+
    Daved with $1995 is dealt 0.973663
    jdragyn with $1005 is dealt 0.945647
    whiteflags is out.
    Daved puts in $1 (blind) for a total of 1
    jdragyn goes all-in with $1005 to 1005
    Daved puts in $1004 (check) for a total of 1005
    Show your cards!
    Total size of the pot is 2010
    Daved shows 0.973663
    jdragyn shows 0.945647
    Daved wins the $2010 pot.
    +-------------+
    | Hand #27    |
    +-------------+
    Daved with $3000 is dealt 0.413862
    jdragyn is out.
    whiteflags is out.
    
    
    Daved has 1 wins.
    jdragyn has 0 wins.
    whiteflags has 0 wins.
    To determine the winner, I ran 100 games to see who won the most. The result was:
    Code:
    Daved has 85 wins.
    jdragyn has 8 wins.
    whiteflags has 7 wins.
    I conclude that the winner is Daved! Congratulations!
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

  2. #2
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    With the contestants permissions, I can post the source code of the competition program and the computer players.
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

  3. #3
    Registered User
    Join Date
    Jan 2005
    Posts
    7,317
    Thanks for running the competition, Sang-drax. It was a fun diversion.

    >> With the contestants permissions, I can post the source code
    That's fine with me, although if anybody wanted to tweak the rules and try to get a few more contestants in to play again I would be up for that.

    Actually, even then I guess I wouldn't mind my submission being posted.

  4. #4
    Registered User jdragyn's Avatar
    Join Date
    Sep 2009
    Posts
    93
    Looks like Daved's is a wee bit smarter than mine. You takin' your bot to Vegas, Daved?

    Thank you Sang-drax. It was neat to see my bot in action, even if it lost. You can post my bot if you like.
    C+/- programmer extraordinaire

  5. #5
    Registered User whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    7,700
    I didn't expect to be foiled by an all-in all the time guy, but it's not like I tested anything. I'm chomping at the bit to make the thing smarter than it turned out to be. Go ahead and post it, it's old.

  6. #6
    Registered User
    Join Date
    Jan 2005
    Posts
    7,317
    I wouldn't mind a rematch after the algorithms are posted.

  7. #7
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by whiteflags View Post
    I didn't expect to be foiled by an all-in all the time guy,
    I'm guessing you mean yourself:
    Daved with $999 is dealt 0.832331
    jdragyn with $1001 is dealt 0.796228
    whiteflags with $1000 is dealt 0.668783
    whiteflags puts in $1 (blind) for a total of 1
    Daved folds.
    jdragyn goes all-in with $1001 to 1001
    whiteflags goes all-in with $999 to 1000
    Show your cards!
    Total size of the pot is 2001
    jdragyn shows 0.796228
    whiteflags shows 0.668783
    jdragyn (all-in) wins $1000 from whiteflags
    If everyone is bluffing all the time, whiteflags would win
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  8. #8
    Registered User whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    7,700
    That was the hand I was the big blind.

    Code:
    // whiteflags.cpp - Program Poker AI Contest 1-Mar-2010
    #include <cmath>
    
    struct GameInfo
    {
    int num_players;
    
    int* money; //Chip count for each player (including myself) 
    bool* has_folded; //What players are still in play
    int* has_betted; //What each player has betted
    int curr_max_bet; //Current highest bet
    };
    
    
    namespace whiteflags {
    	int make_bet(int my_id, float my_hand, const GameInfo&  game_info);
    }
    
    int whiteflags::make_bet(int my_id , float my_hand , const GameInfo& game_info)
    {
    	using std::floor;
    	using std::fabs;
    	static int max_bet;
    	
    	int check = game_info.curr_max_bet - game_info.has_betted[my_id];
    	int fold = check - 1;
    	
    	if(game_info.has_betted[my_id] > 0) {
    		if(fabs(1.0f - my_hand) < 0.03f) {
    			return game_info.money[my_id];
    		}
    
    		int call = game_info.curr_max_bet;
    		
    		if(call <= 0) { 
    			return check;
    		}
    		else if(max_bet >= call) {
    			max_bet -= call;
    			return call;
    		}
    		else {
    			return fold;
    		}
    	}
    	else {
    		float close_enuf = 0.24444f;
    		if(fabs(1.0f - my_hand) < close_enuf) {
    			max_bet = int(floor(my_hand * game_info.money[my_id]));
    			int bet = int(floor(max_bet * 0.125f));
    			if(game_info.curr_max_bet > bet) return fold;
    			max_bet -= bet;
    			return bet;
    		}
    		else {
    			return fold;
    		}
    	}
    }
    I'm not entirely sure what happened, as I don't play poker. I only explicitly go all in when my hand was 0.9-something. I guess blinds count as bets, and I couldn't properly assess my risk that time.
    Last edited by whiteflags; 04-09-2010 at 02:09 PM.

  9. #9
    Registered User
    Join Date
    Jan 2005
    Posts
    7,317
    Code:
    /* Daved's entry */
    
    int make_bet(int my_id, float my_hand, const GameInfo&  game_info)
    {
        static int intital_chip_count = game_info.money[my_id] + game_info.has_bet[my_id];
        static float intital_call_num = intital_chip_count/10.f;
        static float intital_all_in_num = intital_chip_count/50.f;
        static float my_prev_hand = my_hand;
        if (my_hand - my_prev_hand > 0.0001f || my_prev_hand - my_hand > 0.0001f)
        {
            intital_chip_count = game_info.money[my_id] + game_info.has_bet[my_id];
            my_prev_hand = my_hand;
        }
    
        float call_value = 1.f - (intital_call_num / intital_chip_count);
        float all_in_value = 1.f - (intital_all_in_num / intital_chip_count);
        if (my_hand < call_value)
            return 0;
        int my_call_bet = ((game_info.curr_max_bet - game_info.has_bet[my_id]) > game_info.money[my_id])
                          ? game_info.money[my_id] : (game_info.curr_max_bet - game_info.has_bet[my_id]);
        if (my_hand < all_in_value)
            return my_call_bet;
        return INT_MAX;
    }
    My basic algorithm is fold if my hand is worse than 0.90, go all in if it is better than 0.95, and call otherwise. All that extra stuff is some tweaking I did because I didn't know if the initial chip count was 1000 or something else, and also I wanted to be more liberal with my calls and all-ins as my chip count got lower.

    I had tried some other algorithms, including one that used numbers like 0.65 and 0.85 and one that paid attention to pot odds. But when I put those up against this algorithm they always lost badly, so I stuck with this in the end. I guess playing tight really helps in a game like this, especially without an increasing blind structure.

    Oh, and thanks Sang-drax for fixing my code so it would compile. It appears I changed some official variables names and forgot to change them to fit the specs.

  10. #10
    Registered User jdragyn's Avatar
    Join Date
    Sep 2009
    Posts
    93
    Mine was pretty similar to yours, Daved, except my auto-fold was pretty low, my auto-all-in was .92 and everything in between was calculated based on EV (and a very simplistic EV calculation at that). My logic was that if I had a hand worth playing, I'd just go all-in (which kinda defeats the EV calculation I did). Turns out that I got lucky against whiteflags and then your tighter play beat out mine in the long run.

    I'll post mine when I get home from work unless Sang-drax posts it first. I too wouldn't mind a rematch. Maybe make something a wee bit smarter, too.

    <EDIT> Here's my implementation. Don't laugh too hard.

    Code:
    int make_bet(int my_id, float my_hand, const GameInfo& game_info)
    {
        // Check some basics
        if (my_hand > 0.94f) return INT_MAX; // all-in if great hand
        if (my_hand < 0.16f) return INT_MIN; // fold if 7-2 off-suit
    
        // count players and calculate pot size
        int num_pl = 0;
        int pot = 0;
        for (int i = 0; i < game_info.num_players; ++i)
        {
            if (!game_info.has_folded[i]) ++num_pl;
            pot += game_info.has_bet[i];
        }
    
        // Calculate EV.  -EV and we should probably fold
        float bet_value = (float)game_info.curr_max_bet / (float)pot;
        float EV = my_hand - bet_value;
        if (!(EV < 0)) return INT_MAX;
    
        // -EV so look at our exceptions before we fold
    
        //   short handed with a decent hand?  Go all-in
        if ((num_pl < 4) && (my_hand > 0.6f)) return INT_MAX;
    
        //   middle handed, good hand and no one has bet too high
        if ((num_pl < 7) && (my_hand > 0.85f) &&
            (game_info.curr_max_bet < game_info.money[my_id]))
            return INT_MAX;
    
        // Nope, too risky.  Just fold.
        return INT_MIN;    
    }
    Last edited by jdragyn; 04-09-2010 at 09:17 PM. Reason: added my bot
    C+/- programmer extraordinaire

  11. #11
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    Here are the first 5 files used for running the contest. CBoard won't let me upload a .zip file.
    Attached Files Attached Files
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

  12. #12
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    And here are the last two files.


    Study these three simple AIs and try to beat them! This competition will be held again and now you have programs to practice against!

    Let me know if you want changed rules or changed interface for the next competition. The next time I want the interface to be class-based.
    Attached Files Attached Files
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

  13. #13
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Sang-drax View Post
    The next time I want the interface to be class-based.
    Don't do that! If you stick with a function, you can call all the classes you want. There is nothing about this which "requires" C++ or OO.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  14. #14
    Registered User jdragyn's Avatar
    Join Date
    Sep 2009
    Posts
    93
    Actually, the const reference to the GameInfo struct is C++, but it's such a relatively small struct that we could probably do with a copy of it without a significant performance impact:
    Code:
    int make_bet(int my_id, float my_hand, struct GameInfo game_info);
    Then it really wouldn't matter about C or C++ (except for the little things like casting malloc).

    I agree that, in this particular application, there really is not a compelling reason to go with a class based approach over simply having a few individual functions to implement. However, class based would probably make Sang-drax's framework easier to design if he provides a virtual base class for us to inherit from. For that reason, I would be all for a class-based approach, especially if it encourages him to design in additional ways for our AI to gather more complete information.
    Last edited by jdragyn; 04-10-2010 at 04:38 PM.
    C+/- programmer extraordinaire

  15. #15
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    Quote Originally Posted by MK27 View Post
    Don't do that! If you stick with a function, you can call all the classes you want. There is nothing about this which "requires" C++ or OO.
    Actually the struct is passed by reference, which requires C++. Well, if anyone wants to write a function only, I could convert it myself. I don't like the solution with all the namespaces.
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

Page 1 of 2 12 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. "Poker" AI competition
    By Sang-drax in forum Contests Board
    Replies: 30
    Last Post: 04-08-2010, 03:55 PM
  2. application of AI in gaming
    By sun and moon in forum General AI Programming
    Replies: 2
    Last Post: 04-04-2007, 11:32 AM
  3. chess ai contest
    By Raven Arkadon in forum Contests Board
    Replies: 7
    Last Post: 07-09-2005, 06:38 AM
  4. Same seed for srand yields different results
    By codegirl in forum C++ Programming
    Replies: 3
    Last Post: 06-23-2003, 02:39 PM
  5. Game Design Topic #1 - AI Behavior
    By TechWins in forum Game Programming
    Replies: 13
    Last Post: 10-11-2002, 10:35 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21