selecting and working with appropriate data type

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • lane straatman

    selecting and working with appropriate data type

    I'm trying to figure out what data type is appropriate to represent a
    card in a game. The idea that I thought was going to work was a
    struct, foo, with two integer fields and two fields of char arrays:
    index cardno description suit
    ( 1, 1,Two of clubs ,'c')
    ( 2, 2,Three of clubs ,'c')
    ( 3, 3,Four of clubs ,'c')
    ( 4, 4,Five of clubs ,'c')
    ( 5, 5,Six of clubs ,'c')
  • Charlton Wilbur

    #2
    Re: selecting and working with appropriate data type

    >>>>"LS" == lane straatman <grumpy196884@n etzero.netwrite s:

    LSI'm trying to figure out what data type is appropriate to
    LSrepresent a card in a game. The idea that I thought was going
    LSto work was a struct, foo, with two integer fields and two
    LSfields of char arrays:

    Why use a struct when an integer will suffice?

    card_no / 13 will give you the suit, 0-3.

    card_no % 13 will give you the number, 0-12.

    Everything else in your data structure is redundant information.

    Charlton


    --
    Charlton Wilbur
    cwilbur@chromat ico.net

    Comment

    • mark_bluemel@pobox.com

      #3
      Re: selecting and working with appropriate data type


      lane straatman wrote:
      I'm trying to figure out what data type is appropriate to represent a
      card in a game. The idea that I thought was going to work was a
      struct, foo, with two integer fields and two fields of char arrays:
      index cardno description suit
      ( 1, 1,Two of clubs ,'c')
      ( 2, 2,Three of clubs ,'c')
      ( 3, 3,Four of clubs ,'c')
      ( 4, 4,Five of clubs ,'c')
      ( 5, 5,Six of clubs ,'c')
      .
      . [cardno = index % 13]
      .
      ( 48, 9,Ten of spades ,'s')
      ( 49, 10,Jack of spades ,'s')
      ( 50, 11,Queen of spades ,'s')
      ( 51, 12,King of spades ,'s')
      ( 52, 13,Ace of spades ,'s')
      Let's say a person is dealt card 5 and 48. This means foo.index = 5 &&
      foo.index = 48 . How does a person test to see whether he has a pair?
      I can't get my head around it and suspect that my datatype as it is
      isn't as useful as I thought it was going to be. Any hints
      appreciated. LS
      Isn't this classically an application of enumerations - one for suit
      and one for value?

      Comment

      • David T. Ashley

        #4
        Re: selecting and working with appropriate data type

        "Charlton Wilbur" <cwilbur@chroma tico.netwrote in message
        news:874prrzvc8 .fsf@mithril.ch romatico.net...
        >>>>>"LS" == lane straatman <grumpy196884@n etzero.netwrite s:
        >
        LSI'm trying to figure out what data type is appropriate to
        LSrepresent a card in a game. The idea that I thought was going
        LSto work was a struct, foo, with two integer fields and two
        LSfields of char arrays:
        >
        Why use a struct when an integer will suffice?
        >
        card_no / 13 will give you the suit, 0-3.
        >
        card_no % 13 will give you the number, 0-12.
        >
        Everything else in your data structure is redundant information.
        With regard to the OP's question ...

        There are several measures of the "goodness" of a representation:

        a)Whether you can store and extract the information you commonly need
        efficiently. (i / 13 and i %13 are VERY efficient.)

        b)Whether the representation is human-interpretable (to interpret memory
        dumps, debugging info, etc.).

        c)Whether all of the bit patterns that may occur are valid (if not, it tends
        to lead to logical errors). (Generally, the best case is a set of
        enumerations where the actual space is the cartesian product of each
        individual space).



        (and what luck, the URL above gives a playing card example).

        Mr. Wilbur's suggestion is probably the best one possible.

        A perhaps equal fallback would be (number) x (suit). However, it is my
        understanding that jokers have no suit, so this means the cartesian product
        is larger than the actual space -- bad.

        An even less desirable representation would be (number) x (suit) x
        (is_a_face_card ) x (is_a_joker). The problem with that representation is
        that the actual space is smaller than the cartesian product of each
        individual space. In other words, (number = 9) && (is_a_face_card == T) is
        a contradiction (for example).

        It is unavoidable to violate (c) for a variety of reasons. However, for
        this problem, an integer in the range of 0..51 (or slightly larger to handle
        jokers) is probably the best, especially given the speed with which most
        processors will do an integer division these days.



        Comment

        • Chris Dollin

          #5
          Re: selecting and working with appropriate data type

          lane straatman wrote:
          I'm trying to figure out what data type is appropriate to represent a
          card in a game. The idea that I thought was going to work was a
          struct, foo, with two integer fields and two fields of char arrays:
          index cardno description suit
          ( 1, 1,Two of clubs ,'c')
          ( 2, 2,Three of clubs ,'c')
          ( 3, 3,Four of clubs ,'c')
          ( 4, 4,Five of clubs ,'c')
          ( 5, 5,Six of clubs ,'c')
          .
          . [cardno = index % 13]
          .
          ( 48, 9,Ten of spades ,'s')
          ( 49, 10,Jack of spades ,'s')
          ( 50, 11,Queen of spades ,'s')
          ( 51, 12,King of spades ,'s')
          ( 52, 13,Ace of spades ,'s')
          Let's say a person is dealt card 5 and 48. This means foo.index = 5 &&
          foo.index = 48 . How does a person test to see whether he has a pair?
          I can't get my head around it and suspect that my datatype as it is
          isn't as useful as I thought it was going to be. Any hints
          appreciated. LS
          As well as the advice you've also been given, you might usefully
          look at /how you're going to use/ your data-type and have that
          guide you towards your representation.

          You may find that the ID for the card isn't a significant problem
          and its choice is made easier by seeing what you want to do. For
          example, it seems likely that you want to print a card out, read
          a card in, shuffle a packful of cards, sort cards by suit or by
          rank or by honour count ...

          So consider taking an abstract type approach. You can, after all,
          change how you represent a card later on.

          (Especially if you have tests in place to help you avoid errors.)

          --
          Chris "HO. HO. HO." Dollin
          Scoring, bah. If I want scoring I'll go play /Age of Steam/.

          Comment

          • pete

            #6
            Re: selecting and working with appropriate data type

            lane straatman wrote:
            >
            I'm trying to figure out what data type is appropriate to represent a
            card in a game. The idea that I thought was going to work was a
            struct, foo, with two integer fields and two fields of char arrays:
            index cardno description suit
            ( 1, 1,Two of clubs ,'c')
            ( 2, 2,Three of clubs ,'c')
            ( 3, 3,Four of clubs ,'c')
            ( 4, 4,Five of clubs ,'c')
            ( 5, 5,Six of clubs ,'c')
            .
            . [cardno = index % 13]
            .
            ( 48, 9,Ten of spades ,'s')
            ( 49, 10,Jack of spades ,'s')
            ( 50, 11,Queen of spades ,'s')
            ( 51, 12,King of spades ,'s')
            ( 52, 13,Ace of spades ,'s')
            Let's say a person is dealt card 5 and 48. This means foo.index = 5 &&
            foo.index = 48 . How does a person test to see whether he has a pair?
            Consider the hand as an array.
            Sort the array, and check for equality in consecutive elements.
            Paul Hsieh wrote a program that I like,
            which fully evaluates poker hands and scores them.

            This is one that I wrote:

            /* BEGIN shuffle.c */

            #include <stdio.h>
            #include <time.h>
            /*
            ** #define HANDS 1
            ** #define DEALS 5
            ** #define LU_RAND_SEED 1124021992
            ** 1124021815
            ** 1141904096
            ** 1141906091
            ** 1143411367
            ** 123456789LU
            */
            #define LU_RAND_SEED time(NULL) /* time(NULL), 1141904096 */
            #define DEALS 5
            #define HAND 5
            #define CARDS (SUITS * RANKS)
            #define SUITS (sizeof suit / sizeof *suit)
            #define RANKS (sizeof rank / sizeof *rank)
            #define LU_RAND(S) ((S) * 69069 + 362437 & 0xffffffffLU)

            struct poker {
            int suit;
            int rank;
            };

            int pair(struct poker *hand);
            int three(struct poker *hand);
            int four(struct poker *hand);
            int full(struct poker *hand);
            int two_pair(struct poker *hand);
            int straight(struct poker *hand);
            int flush(struct poker *hand);
            int compar_rank(voi d const *first, void const *second);
            int compar_suit(voi d const *first, void const *second);
            long unsigned shuffle(int *array, int n, long unsigned seed);
            void s_sort(void *base, size_t nmemb, size_t size,
            int (*compar)(const void *, const void *));

            int main(void)
            {
            size_t card;
            struct poker hand[HAND];
            long unsigned deal;
            long unsigned seed;
            char *suit[] = {"Hearts","Diam onds","Clubs"," Spades"};
            char *rank[] = {"Deuce","Three ","Four","Five" ,"Six",
            "Seven","Eight" ,"Nine","Ten"," Jack","Queen"," King","Ace"
            };
            int deck[CARDS];

            seed = (long unsigned)LU_RAN D_SEED;
            printf("\nseed = %lu\n\n", seed);
            deal = DEALS;
            while (deal-- != 0) {
            seed = shuffle(deck, CARDS, seed);
            for (card = 0; card != HAND; ++card) {
            hand[card].suit = deck[card] % SUITS;
            hand[card].rank = deck[card] % RANKS;
            }
            if (pair(hand)) {
            if (three(hand)) {
            if (four(hand)) {
            puts("Four of a Kind:");
            } else {
            if (full(hand)) {
            puts("Full House:");
            } else {
            puts("Three of a Kind:");
            }
            }
            } else {
            if (two_pair(hand) ) {
            puts("Two Pair:");
            } else {
            puts("Pair:");
            }
            }
            } else {
            switch (2 * flush(hand) + straight(hand)) {
            case 0:
            s_sort(hand, HAND, sizeof *hand, compar_rank);
            printf("%s High:\n", rank[hand[4].rank]);
            break;
            case 1:
            puts("Straight: ");
            break;
            case 2:
            puts("Flush:");
            break;
            default:
            puts("Straight Flush:");
            break;
            }
            }
            putchar('\n');
            for (card = 0; card != HAND; ++card) {
            printf("%s of %s\n",
            rank[deck[card] % RANKS],
            suit[deck[card] % SUITS]);
            }
            putchar('\n');
            }
            return 0;
            }

            int pair(struct poker *hand)
            {
            s_sort(hand, HAND, sizeof *hand, compar_rank);
            return hand[1].rank == hand[0].rank
            || hand[2].rank == hand[1].rank
            || hand[3].rank == hand[2].rank
            || hand[4].rank == hand[3].rank;
            }

            int three(struct poker *hand)
            {
            s_sort(hand, HAND, sizeof *hand, compar_rank);
            return hand[0].rank == hand[2].rank
            || hand[1].rank == hand[3].rank
            || hand[2].rank == hand[4].rank;
            }

            int four(struct poker *hand)
            {
            s_sort(hand, HAND, sizeof *hand, compar_rank);
            return hand[0].rank == hand[3].rank
            || hand[1].rank == hand[4].rank;
            }

            int full(struct poker *hand)
            {
            s_sort(hand, HAND, sizeof *hand, compar_rank);
            return hand[0].rank == hand[1].rank
            && hand[2].rank == hand[4].rank
            || hand[0].rank == hand[2].rank
            && hand[3].rank == hand[4].rank;
            }

            int two_pair(struct poker *hand)
            {
            s_sort(hand, HAND, sizeof *hand, compar_rank);
            return hand[0].rank == hand[1].rank
            && hand[3].rank == hand[2].rank
            || hand[0].rank == hand[1].rank
            && hand[3].rank == hand[4].rank
            || hand[1].rank == hand[2].rank
            && hand[3].rank == hand[4].rank;
            }

            int straight(struct poker *hand)
            {
            s_sort(hand, HAND, sizeof *hand, compar_rank);
            return (hand[0].rank == 12 && hand[1].rank == 0
            || hand[0].rank + 1 == hand[1].rank)
            && hand[1].rank + 1 == hand[2].rank
            && hand[2].rank + 1 == hand[3].rank
            && hand[3].rank + 1 == hand[4].rank;
            }

            int flush(struct poker *hand)
            {
            s_sort(hand, HAND, sizeof *hand, compar_suit);
            return hand[0].suit == hand[4].suit;
            }

            int compar_rank(voi d const *first, void const *second)
            {
            int int_1 = (*(struct poker*)first).r ank;
            int int_2 = (*(struct poker*)second). rank;

            return int_2 int_1 ? -1 : int_2 != int_1;
            }

            int compar_suit(voi d const *first, void const *second)
            {
            int int_1 = (*(struct poker*)first).s uit;
            int int_2 = (*(struct poker*)second). suit;

            return int_2 int_1 ? -1 : int_2 != int_1;
            }

            long unsigned shuffle(int *array, int n, long unsigned seed)
            {
            int i, r;

            array[0] = 0;
            for (i = 1; n i; ++i) {
            seed = LU_RAND(seed);
            r = seed % (i + 1);
            array[i] = 0;
            array[i] = array[r];
            array[r] = i;
            }
            return seed;
            }

            void s_sort(void *base, size_t nmemb, size_t size,
            int (*compar)(const void *, const void *))
            {
            size_t bytes;
            unsigned char *array, *after, *i, *j, *k, *p1, *p2, *end, swap;

            array = base;
            after = nmemb * size + array;
            if (nmemb (size_t)-1 / 4) {
            nmemb /= 4;
            } else {
            nmemb = (nmemb * 3 + 1) / 7;
            }
            while (nmemb != 0) {
            bytes = nmemb * size;
            i = bytes + array;
            do {
            j = i - bytes;
            if (compar(j, i) 0) {
            k = i;
            do {
            p1 = j;
            p2 = k;
            end = p2 + size;
            do {
            swap = *p1;
            *p1++ = *p2;
            *p2++ = swap;
            } while (p2 != end);
            if (bytes + array j) {
            break;
            }
            k = j;
            j -= bytes;
            } while (compar(j, k) 0);
            }
            i += size;
            } while (i != after);
            nmemb = (nmemb * 3 + 1) / 7;
            }
            }

            /* END shuffle.c */


            --
            pete

            Comment

            • lane straatman

              #7
              Re: selecting and working with appropriate data type


              pete wrote:
              LS: fishing for hints on representing a poker game
              Consider the hand as an array.
              Sort the array, and check for equality in consecutive elements.
              Paul Hsieh wrote a program that I like,
              which fully evaluates poker hands and scores them.
              >
              This is one that I wrote:
              >
              /* BEGIN shuffle.c */
              >
              #include <stdio.h>
              #include <time.h>
              /*
              ** #define HANDS 1
              ** #define DEALS 5
              ** #define LU_RAND_SEED 1124021992
              ** 1124021815
              ** 1141904096
              ** 1141906091
              ** 1143411367
              ** 123456789LU
              */
              #define LU_RAND_SEED time(NULL) /* time(NULL), 1141904096 */
              #define DEALS 5
              #define HAND 5
              #define CARDS (SUITS * RANKS)
              #define SUITS (sizeof suit / sizeof *suit)
              #define RANKS (sizeof rank / sizeof *rank)
              #define LU_RAND(S) ((S) * 69069 + 362437 & 0xffffffffLU)
              >
              struct poker {
              int suit;
              int rank;
              };
              >
              int pair(struct poker *hand);
              int three(struct poker *hand);
              int four(struct poker *hand);
              int full(struct poker *hand);
              int two_pair(struct poker *hand);
              int straight(struct poker *hand);
              int flush(struct poker *hand);
              int compar_rank(voi d const *first, void const *second);
              int compar_suit(voi d const *first, void const *second);
              long unsigned shuffle(int *array, int n, long unsigned seed);
              void s_sort(void *base, size_t nmemb, size_t size,
              int (*compar)(const void *, const void *));
              [main and beyond snipped for brevity]
              Thanks all for replies and in particular pete for his generous post.
              I'm a mile away from a compiler now, so I can't step through it, but it
              looks as clean as a whistle.

              One thing I want to do is to be able to calculate is how much of a
              difference it makes in the odds when a card gets flipped up, which
              happens fairly frequently in real life, and on which I have no numeric
              handle. A card flipped up during the deal--in Western
              Michigan--becomes the burn card. I'm unaware of how universal this
              practice is. An upturned burn card would differ from the usual, I
              should think.

              Does Paul's version come up with a number for a hand that would inform
              a decision? LS

              Comment

              • Bill Reid

                #8
                Re: selecting and working with appropriate data type


                lane straatman <grumpy196884@n etzero.netwrote in message
                news:1166573511 .710885.166410@ 79g2000cws.goog legroups.com...
                pete wrote:
                LS: fishing for hints on representing a poker game
                >
                As is usually the case, it turns out he was looking to solve
                Fermat's Last Theorum and asked how to add 2+2...
                Consider the hand as an array.
                Sort the array, and check for equality in consecutive elements.
                Paul Hsieh wrote a program that I like,
                which fully evaluates poker hands and scores them.

                This is one that I wrote:

                /* BEGIN shuffle.c */

                #include <stdio.h>
                [main and beyond snipped for brevity]
                Thanks all for replies and in particular pete for his generous post.
                I'm a mile away from a compiler now, so I can't step through it, but it
                looks as clean as a whistle.
                >
                Well, as one of my "mentors" on one of my first jobs said, "if it
                looks good, it must be good"...

                I really do prefer my object-oriented C++ card-playing classes
                myself...
                One thing I want to do is to be able to calculate is how much of a
                difference it makes in the odds when a card gets flipped up, which
                happens fairly frequently in real life, and on which I have no numeric
                handle. A card flipped up during the deal--in Western
                Michigan--becomes the burn card. I'm unaware of how universal this
                practice is. An upturned burn card would differ from the usual, I
                should think.
                >
                It's just a card that can never be drawn to the community cards or
                to a player's hand, so you remove it from the deck remainder that
                you evaluate using combinatorial analysis...oh wait, are you writing
                a combinatorial analyzer, or a "Monte Carlo" simulator, or
                perhaps a simulator that can call in a combinatorial analysis
                at any time, or what?

                For my purposes (which include all of the above), I use three
                arrays for cards ("deck", "discards/burns", and "table", with
                hands being composed of pointers to "groups" of cards
                on the "table"). A "card" will always be in one of the three
                arrays...
                Does Paul's version come up with a number for a hand that would inform
                a decision? LS
                >
                Almost definitely not...but a poker "odds" analyzer is simpler
                and more straightforward to write than for some other games
                I can think of...

                ---
                William Ernest Reid



                Comment

                • lane straatman

                  #9
                  Re: selecting and working with appropriate data type


                  Bill Reid wrote:
                  lane straatman <grumpy196884@n etzero.netwrote in message
                  news:1166573511 .710885.166410@ 79g2000cws.goog legroups.com...
                  pete wrote:
                  >
                  LS: fishing for hints on representing a poker game
                  As is usually the case, it turns out he was looking to solve
                  Fermat's Last Theorum and asked how to add 2+2...
                  It was only a century back that logicians proclaimed that "arithmetic
                  teeters."
                  Consider the hand as an array.
                  Sort the array, and check for equality in consecutive elements.
                  Paul Hsieh wrote a program that I like,
                  which fully evaluates poker hands and scores them.
                  >
                  This is one that I wrote:
                  >
                  /* BEGIN shuffle.c */
                  >
                  #include <stdio.h>
                  >
                  [main and beyond snipped for brevity]
                  Thanks all for replies and in particular pete for his generous post.
                  I'm a mile away from a compiler now, so I can't step through it, but it
                  looks as clean as a whistle.
                  Well, as one of my "mentors" on one of my first jobs said, "if it
                  looks good, it must be good"...
                  >
                  I really do prefer my object-oriented C++ card-playing classes
                  myself...
                  What is it that you gain from OO?
                  One thing I want to do is to be able to calculate is how much of a
                  difference it makes in the odds when a card gets flipped up, which
                  happens fairly frequently in real life, and on which I have no numeric
                  handle. A card flipped up during the deal--in Western
                  Michigan--becomes the burn card. I'm unaware of how universal this
                  practice is. An upturned burn card would differ from the usual, I
                  should think.
                  It's just a card that can never be drawn to the community cards or
                  to a player's hand, so you remove it from the deck remainder that
                  you evaluate using combinatorial analysis...oh wait, are you writing
                  a combinatorial analyzer, or a "Monte Carlo" simulator, or
                  perhaps a simulator that can call in a combinatorial analysis
                  at any time, or what?
                  Monte Carlo is the short answer. I'm only able to do combo with pen
                  and paper. It's nice to have a computer tell you that you've got the
                  correct answer. More than anything though, I like to see a scenario,
                  say, that you're dealt a pocket pair and see how the bidding might go
                  given tight/loose players, short/tall stacks and position. Right now,
                  I array the cards and "players" on my desk and try to do the odds
                  analysis. In real life, I'm having trouble playing with loose players
                  on tall stacks in cash games. The burning question there is usually
                  just when to push all in.
                  For my purposes (which include all of the above), I use three
                  arrays for cards ("deck", "discards/burns", and "table", with
                  hands being composed of pointers to "groups" of cards
                  on the "table"). A "card" will always be in one of the three
                  arrays...
                  >
                  Does Paul's version come up with a number for a hand that would inform
                  a decision? LS
                  Almost definitely not...but a poker "odds" analyzer is simpler
                  and more straightforward to write than for some other games
                  I can think of...
                  True. LS

                  Comment

                  • pete

                    #10
                    Re: selecting and working with appropriate data type

                    lane straatman wrote:
                    >
                    pete wrote:
                    LS: fishing for hints on representing a poker game
                    >
                    Consider the hand as an array.
                    Sort the array, and check for equality in consecutive elements.
                    Paul Hsieh wrote a program that I like,
                    which fully evaluates poker hands and scores them.
                    Does Paul's version come up with a number for a hand that would inform
                    a decision? LS
                    Yes.

                    I deleted some unused variables and did very little reformatting.
                    This is pretty close to what he posted:

                    /* BEGIN pokeref.h */

                    #ifndef H_POKEREF_H
                    #define H_POKEREF_H

                    #define CLUB_SUIT (1)
                    #define DIAMOND_SUIT (2)
                    #define HEART_SUIT (4)
                    #define SPADE_SUIT (8)

                    #define RANK_SHL (27)
                    #define SUBR_SHL (13)

                    #define STRAIGHT_FLUSH_ SCORE (8 << RANK_SHL)
                    #define FOUR_KIND_SCORE (7 << RANK_SHL)
                    #define FULL_HOUSE_SCOR E (6 << RANK_SHL)
                    #define FLUSH_SCORE (5 << RANK_SHL)
                    #define STRAIGHT_SCORE (4 << RANK_SHL)
                    #define THREE_KIND_SCOR E (3 << RANK_SHL)
                    #define TWO_PAIR_SCORE (2 << RANK_SHL)
                    #define TWO_KIND_SCORE (1 << RANK_SHL)

                    #define ONE_PAIR_SCORE (TWO_KIND_SCORE )

                    #ifndef DWORD
                    typedef unsigned long DWORD;
                    #endif

                    #ifndef BYTE
                    typedef unsigned long BYTE;
                    #endif

                    #ifndef WORD
                    typedef unsigned long WORD;
                    #endif

                    typedef struct {
                    int len;
                    BYTE entry[52];
                    } CardPileType;

                    #endif

                    /* END pokeref.h */

                    /* BEGIN pokeref.c */

                    #include <stdio.h>
                    #include <stdlib.h>
                    #include <time.h>

                    #include "pokeref.h"

                    DWORD CardValue[52] = {
                    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
                    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
                    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
                    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
                    };

                    DWORD CardMask[52] = {
                    1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800,
                    0x1000,
                    1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800,
                    0x1000,
                    1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800,
                    0x1000,
                    1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800,
                    0x1000
                    };

                    DWORD CardSuit[52] = {
                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
                    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
                    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
                    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8
                    };

                    DWORD PokerScore( BYTE * h )
                    {
                    DWORD u,y,z;
                    DWORD c0,c1,c2,c3,c4;
                    DWORD m1,m2,m3,m4;
                    /*
                    // Make suits powers of two.
                    */
                    u = CardSuit[h[0]];
                    u |= CardSuit[h[1]];
                    u |= CardSuit[h[2]];
                    u |= CardSuit[h[3]];
                    u |= CardSuit[h[4]];
                    /*
                    // Test for single suitedness
                    */
                    u = u&(u-1);
                    /*
                    // Make cards powers of two.
                    */
                    c0 = CardMask[h[0]];
                    c1 = CardMask[h[1]];
                    c2 = CardMask[h[2]];
                    c3 = CardMask[h[3]];
                    c4 = CardMask[h[4]];
                    /*
                    // Build masks of 1, 2, 3, and 4 of a kind.
                    */
                    m1 = c0 | c1;
                    m2 = c1 & c0;
                    m2 |= c2 & m1;
                    m1 |= c2;
                    m2 |= c3 & m1;
                    m1 |= c3;
                    m2 |= c4 & m1;
                    m1 |= c4;

                    if( m2==0 ) { /*// No pairs?*/
                    /*
                    // Is the mask a sequence of 1 bits?
                    */
                    z = m1&(m1-1);
                    z ^= m1;
                    y = (z<<5) - z;
                    /*
                    // Deal with the bicycle/wheel 5,4,3,2,Ace straight
                    */
                    if ( m1 == 0x100F ) {
                    if( u!=0 ) return STRAIGHT_SCORE + 0xF;

                    return STRAIGHT_FLUSH_ SCORE + 0xF;
                    }

                    if( y==m1 ) {
                    if( u!=0 ) return STRAIGHT_SCORE + m1;

                    return STRAIGHT_FLUSH_ SCORE + m1;
                    }

                    if( u!=0 ) return m1; // Nothing

                    return FLUSH_SCORE + m1;
                    }
                    /*
                    // m1 = c0 | ... | c4
                    // m2 = (c0 & c1) | ((c0|c1) & c2)
                    | ((c0|c1|c2) & c3) | ((c0|c1|c2|c3) & c4)
                    // m3 = mask of 3 of a kind.
                    // m4 = mask of 4 of a kind.
                    */
                    m1 = c0 | c1;
                    m2 = c1 & c0;
                    m3 = c2 & m2;
                    m2 |= c2 & m1;
                    m1 |= c2;
                    m4 = c3 & m3;
                    m3 |= c3 & m2;
                    m2 |= c3 & m1;
                    m1 |= c3;
                    m4 |= c4 & m3;
                    m3 |= c4 & m2;
                    m2 |= c4 & m1;
                    m1 |= c4;

                    m1 &= ~m2;

                    if(m3 == 0) {
                    if( (m2&(m2 - 1))==0 )
                    return TWO_KIND_SCORE + (m2 << SUBR_SHL) + m1;

                    return TWO_PAIR_SCORE + (m2 << SUBR_SHL) + m1;
                    }

                    m2 &= ~m3;

                    if( m4==0 ) {
                    if( m2==0 )
                    return THREE_KIND_SCOR E + (m3 << SUBR_SHL) + m1;

                    return FULL_HOUSE_SCOR E + (m3 << SUBR_SHL) + m2;
                    }

                    return FOUR_KIND_SCORE + (m4 << SUBR_SHL) + m1;
                    }

                    //char suitdisp[9] = { 0, 5, 4, 0, 3, 0, 0, 0, 6 };

                    char suitdisp[9] = { 0, 'c', 'd', 0, 'h', 0, 0, 0, 's' };

                    void DisplayCard( BYTE c ) {
                    char s[4];

                    s[0] = " 1 "[CardValue[c]];
                    s[1] = "234567890J QKA"[CardValue[c]];
                    s[2] = suitdisp[CardSuit[c]];
                    s[3] = '\0';

                    printf(" %s ",s);

                    }

                    void DisplayHand( CardPileType * h ) {
                    int v=0;
                    int i;

                    for(i=0;i<5;i++ ) DisplayCard( h->entry[i] );

                    printf(" =%08X\n",PokerS core(&h->entry[0]));
                    }

                    CardPileType Deck, Hand;

                    void Shuffle( CardPileType * c ) {
                    int i = c->len,j;

                    for(;i>1;) {
                    BYTE t;
                    j = rand() % i;
                    i--;
                    t = c->entry[i];
                    c->entry[i] = c->entry[j];
                    c->entry[j] = t;
                    }
                    }

                    int Deal( CardPileType * h, CardPileType * d, int n )
                    {
                    int i;
                    for( i=0; i<n && d->len>0; i++ ) {
                    d->len--;
                    h->entry[ h->len ] = d->entry[ d->len ];
                    h->len++;
                    }
                    return i;
                    }

                    void InitCards()
                    {
                    int i;

                    Deck.len = 52;
                    for(i=0;i<52;i+ +)
                    Deck.entry[i] = i;
                    Shuffle(&Deck);
                    Hand.len = 0;
                    }

                    #define ARCHIVE_SHL 6
                    #define ARCHIVE_NUM (1<<(ARCHIVE_SH L))

                    CardPileType HandArchive[ARCHIVE_NUM];

                    int main(void)
                    {
                    int i,j;
                    int c;

                    srand( (unsigned int)time((void *)0) );
                    InitCards();
                    printf("STRAIGH T_FLUSH_SCORE %08x\n",STRAIGH T_FLUSH_SCORE );
                    printf("FOUR_KI ND_SCORE %08x\n",FOUR_KI ND_SCORE );
                    printf("FULL_HO USE_SCORE %08x\n",FULL_HO USE_SCORE );
                    printf("FLUSH_S CORE %08x\n",FLUSH_S CORE );
                    printf("STRAIGH T_SCORE %08x\n",STRAIGH T_SCORE );
                    printf("THREE_K IND_SCORE %08x\n",THREE_K IND_SCORE );
                    printf("TWO_PAI R_SCORE %08x\n",TWO_PAI R_SCORE );
                    printf("TWO_KIN D_SCORE %08x\n",TWO_KIN D_SCORE );

                    for(i=0;i<ARCHI VE_NUM;i++) {
                    Deal(&Hand,&Dec k,5);
                    if( i<32 ) DisplayHand(&Ha nd);
                    HandArchive[i] = Hand;
                    Deal(&Deck,&Han d,5); // Add hand back into Deck.
                    Shuffle(&Deck); // Reshuffle Deck.
                    }

                    for(c=0;c<1024; c++) {
                    for(j=0,i=0;i<A RCHIVE_NUM;i++) {
                    j += PokerScore(&Han dArchive[i].entry[0]);
                    }
                    }

                    printf("\nRigge d hands\n\n");
                    Hand.len = 5;
                    Hand.entry[0] = 12;
                    Hand.entry[1] = 12+13;
                    Hand.entry[2] = 12+26;
                    Hand.entry[3] = 12+39;
                    Hand.entry[4] = 11;
                    DisplayHand(&Ha nd);

                    Hand.entry[0] = 12;
                    Hand.entry[1] = 12+13;
                    Hand.entry[2] = 12+26;
                    Hand.entry[3] = 11+39;
                    Hand.entry[4] = 11;
                    DisplayHand(&Ha nd);

                    Hand.entry[0] = 12;
                    Hand.entry[1] = 11+13;
                    Hand.entry[2] = 10+26;
                    Hand.entry[3] = 9+39;
                    Hand.entry[4] = 8;
                    DisplayHand(&Ha nd);

                    Hand.entry[0] = 12;
                    Hand.entry[1] = 12+13;
                    Hand.entry[2] = 2+26;
                    Hand.entry[3] = 3+39;
                    Hand.entry[4] = 4;
                    DisplayHand(&Ha nd);

                    Hand.entry[0] = 2;
                    Hand.entry[1] = 2+13;
                    Hand.entry[2] = 3+26;
                    Hand.entry[3] = 3+39;
                    Hand.entry[4] = 4;
                    DisplayHand(&Ha nd);

                    Hand.entry[0] = 0;
                    Hand.entry[1] = 0+13;
                    Hand.entry[2] = 1+26;
                    Hand.entry[3] = 2+39;
                    Hand.entry[4] = 3;
                    DisplayHand(&Ha nd);

                    Hand.entry[0] = 0;
                    Hand.entry[1] = 0+13;
                    Hand.entry[2] = 1+26;
                    Hand.entry[3] = 1+39;
                    Hand.entry[4] = 2;
                    DisplayHand(&Ha nd);

                    Hand.entry[0] = 3;
                    Hand.entry[1] = 2+13;
                    Hand.entry[2] = 1+26;
                    Hand.entry[3] = 0+39;
                    Hand.entry[4] = 12;
                    DisplayHand(&Ha nd);

                    Hand.entry[0] = 4;
                    Hand.entry[1] = 3+13;
                    Hand.entry[2] = 2+26;
                    Hand.entry[3] = 1+39;
                    Hand.entry[4] = 0;
                    DisplayHand(&Ha nd);

                    Hand.entry[0] = 12;
                    Hand.entry[1] = 12+13;
                    Hand.entry[2] = 11+26;
                    Hand.entry[3] = 11+39;
                    Hand.entry[4] = 10;
                    DisplayHand(&Ha nd);

                    Hand.entry[0] = 12+ 26;
                    Hand.entry[1] = 12+13;
                    Hand.entry[2] = 11+26;
                    Hand.entry[3] = 11;
                    Hand.entry[4] = 10+39;
                    DisplayHand(&Ha nd);

                    Hand.entry[0] = 12;
                    Hand.entry[1] = 0;
                    Hand.entry[2] = 1;
                    Hand.entry[3] = 2;
                    Hand.entry[4] = 3;
                    DisplayHand(&Ha nd);

                    Hand.entry[0] = 11 + 26;
                    Hand.entry[1] = 0;
                    Hand.entry[2] = 1;
                    Hand.entry[3] = 2;
                    Hand.entry[4] = 3;
                    DisplayHand(&Ha nd);

                    Hand.entry[0] = 11 + 26;
                    Hand.entry[1] = 4;
                    Hand.entry[2] = 1;
                    Hand.entry[3] = 2;
                    Hand.entry[4] = 3;
                    DisplayHand(&Ha nd);

                    return 0;
                    }

                    /* END pokeref.c */


                    --
                    pete

                    Comment

                    • lane straatman

                      #11
                      Re: selecting and working with appropriate data type


                      pete wrote:
                      lane straatman wrote:

                      pete wrote:
                      LS: fishing for hints on representing a poker game
                      Consider the hand as an array.
                      Sort the array, and check for equality in consecutive elements.
                      Paul Hsieh wrote a program that I like,
                      which fully evaluates poker hands and scores them.
                      >
                      Does Paul's version come up with a number for a hand that would inform
                      a decision? LS
                      >
                      Yes.
                      >
                      I deleted some unused variables and did very little reformatting.
                      This is pretty close to what he posted:
                      [post downloaded but snipped for brevity]
                      pete
                      #include <stdio.h>
                      #define LU_RAND(S) ((S) * 69069 + 362437 & 0xffffffffLU)
                      int main(void)
                      {
                      /** #define LU_RAND_SEED 1124021992
                      ** 1124021815
                      ** 1141904096
                      ** 1141906091
                      ** 1143411367
                      ** 123456789LU */
                      unsigned long seed;
                      int i;
                      seed = 1124021992;
                      printf("%lu\n", seed);
                      for (i = 1; i < 1000; ++ i)
                      {
                      seed = LU_RAND(seed);
                      printf("%lu\n", seed);

                      }
                      return 0;
                      }
                      end source
                      This prog is heavily snipped from pete's upthread post. He circumvents
                      a rand() call with the macro, and I've been trying to find cracks in
                      it, but have only succeeded in finding cracks in my own knowledge of
                      C. With his choice of 69069, 362437 and mask, he never busts his data
                      type. Nor can I find a non-randomness mod some smallish number.

                      I don't understand the mask. If I remove f's, I lose 2 digits on the
                      number, yet there seems to be an extra f to my thinking. If I add an
                      f, I get the following warning that doesn't turn out to be true:
                      warning C4244: '=' : conversion from 'unsigned __int64 ' to 'unsigned
                      long '. What give's?

                      I was "certain" that the results for 5 card stud was **way** heavy on
                      pairs and trips until I took out a deck of cards and got empirical.
                      For Hold 'Em enthusiasts, you can look at it as the community cards.
                      You'll be less inclined to pull the trigger with a pocket pair.

                      Poker is a great way to sharpen up one's syntax. Familiar and hands
                      on. I've been down the hall at comp.lang.fortr an, using Metcalf, Reid
                      & Cohen. I've yet to assail interoperabilit y with C, and one reason
                      for that is that I don't see types I recognize. Are the following
                      kosher types: int_least32_t , int_fast64_t , long double _Complex ,
                      _Bool ? LS

                      Comment

                      • Bill Reid

                        #12
                        Re: selecting and working with appropriate data type


                        lane straatman <grumpy196884@n etzero.netwrote in message
                        news:1166642273 .103026.126780@ n67g2000cwd.goo glegroups.com.. .
                        Bill Reid wrote:
                        lane straatman <grumpy196884@n etzero.netwrote in message
                        news:1166573511 .710885.166410@ 79g2000cws.goog legroups.com...
                        pete wrote:
                        LS: fishing for hints on representing a poker game
                        >
                        As is usually the case, it turns out he was looking to solve
                        Fermat's Last Theorum and asked how to add 2+2...
                        It was only a century back that logicians proclaimed that "arithmetic
                        teeters."
                        >
                        Math can be pretty wacky...read the history of "probabilit y theory"
                        and compare it to what we know now for some good laughs, and those
                        comedians are/were the renowned mathematicians of their day...
                        Consider the hand as an array.
                        Sort the array, and check for equality in consecutive elements.
                        Paul Hsieh wrote a program that I like,
                        which fully evaluates poker hands and scores them.

                        This is one that I wrote:

                        /* BEGIN shuffle.c */

                        #include <stdio.h>
                        [main and beyond snipped for brevity]
                        Thanks all for replies and in particular pete for his generous post.
                        I'm a mile away from a compiler now, so I can't step through it, but
                        it
                        looks as clean as a whistle.
                        >
                        Well, as one of my "mentors" on one of my first jobs said, "if it
                        looks good, it must be good"...

                        I really do prefer my object-oriented C++ card-playing classes
                        myself...
                        What is it that you gain from OO?
                        >
                        The ability to write simulators for new games without re-creating all
                        the code for "cards", "deck of cards", "card table", "dealer", "players",
                        etc. Basically, I can just write a new "game" class with some new
                        "strategy" tables and I'm done...
                        One thing I want to do is to be able to calculate is how much of a
                        difference it makes in the odds when a card gets flipped up, which
                        happens fairly frequently in real life, and on which I have no numeric
                        handle. A card flipped up during the deal--in Western
                        Michigan--becomes the burn card. I'm unaware of how universal this
                        practice is. An upturned burn card would differ from the usual, I
                        should think.
                        >
                        It's just a card that can never be drawn to the community cards or
                        to a player's hand, so you remove it from the deck remainder that
                        you evaluate using combinatorial analysis...oh wait, are you writing
                        a combinatorial analyzer, or a "Monte Carlo" simulator, or
                        perhaps a simulator that can call in a combinatorial analysis
                        at any time, or what?
                        Monte Carlo is the short answer. I'm only able to do combo with pen
                        and paper. It's nice to have a computer tell you that you've got the
                        correct answer.
                        Ah, yes, once again, check the history of "probabilit y theory" and
                        note it only really "gelled" as the result of empirical studies, which is
                        greatly aided these days by high-speed computer simulations. Las
                        Vegas exists because of the laws of probability but the casino owners
                        didn't (and still largely don't!) know the laws, they only kind of know
                        "what works" (note that even after Dr. Thorp calculated the "odds"
                        of a hand of blackjack, they STILL didn't really understand the
                        game they were offering)...

                        Of course, if you able to do the calculation with "pen and paper",
                        you can do it with a computer, but you admit you don't really trust
                        your math skills. So you want to simulate the game and compile
                        the statistics to see what really happens. So what you really want
                        is not a full poker simulator, but a more limited simulator that just
                        checks the hand completion results after a particular card is "seen".
                        Be aware that you'll have to run many billions of trials for each
                        of the possible combinations of your dealt cards and the "seen"
                        card in order for the varying results to resolve to a statistically-valid
                        "expectatio n" number.
                        More than anything though, I like to see a scenario,
                        say, that you're dealt a pocket pair and see how the bidding might go
                        given tight/loose players, short/tall stacks and position.
                        OK, that's a full simulator. You're dealing with a lot more variables
                        there, and getting into some of the more "intangible/chaotic" aspects of
                        poker, given that in real life, "tightness" and "looseness" can and do
                        vary themselves as player "psychology " changes. The "bidding"
                        itself is dependant on YOUR "tightness" or "looseness" in many
                        situations.

                        In addition to biting off more than you can chew coding- and
                        game theory-wise, you may be asking a question that already
                        has a better strategic answer, if your goal is just to learn how
                        to win at poker...
                        Right now,
                        I array the cards and "players" on my desk and try to do the odds
                        analysis.
                        Of course, you can "see" the other player's cards, which is a tremendous
                        advantage you only sometimes get in a real game!
                        In real life, I'm having trouble playing with loose players
                        on tall stacks in cash games. The burning question there is usually
                        just when to push all in.
                        >
                        Yeah, those pesky "real-life" players will do it to you every time!
                        Here's a well-known clue: NOBODY can win in a truly "loose"
                        game. Here's the (duh!) strategy: DON'T PLAY IN THOSE
                        GAMES. Problem solved!

                        Of course, it is also impossible to win in a truly "tight" game
                        either. The general strategy for winning consistently at poker
                        thus reduces down to choosing your opponents (ideally,
                        "loose/scared"), not trying to figure out how to win in games
                        where nobody has a chance of winning.

                        ---
                        William Ernest Reid



                        Comment

                        • pete

                          #13
                          Re: selecting and working with appropriate data type

                          lane straatman wrote:
                          >
                          pete wrote:
                          lane straatman wrote:
                          >
                          pete wrote:
                          LS: fishing for hints on representing a poker game
                          >
                          Consider the hand as an array.
                          Sort the array, and check for equality in consecutive elements.
                          Paul Hsieh wrote a program that I like,
                          which fully evaluates poker hands and scores them.
                          Does Paul's version come up with
                          a number for a hand that would inform
                          a decision? LS
                          Yes.

                          I deleted some unused variables and did very little reformatting.
                          This is pretty close to what he posted:
                          [post downloaded but snipped for brevity]
                          pete
                          >
                          #include <stdio.h>
                          #define LU_RAND(S) ((S) * 69069 + 362437 & 0xffffffffLU)
                          int main(void)
                          {
                          /** #define LU_RAND_SEED 1124021992
                          ** 1124021815
                          ** 1141904096
                          ** 1141906091
                          ** 1143411367
                          ** 123456789LU */
                          unsigned long seed;
                          int i;
                          seed = 1124021992;
                          printf("%lu\n", seed);
                          for (i = 1; i < 1000; ++ i)
                          {
                          seed = LU_RAND(seed);
                          printf("%lu\n", seed);
                          >
                          }
                          return 0;
                          }
                          end source
                          This prog is heavily snipped from pete's upthread post.
                          He circumvents
                          a rand() call with the macro, and I've been trying to find cracks in
                          it, but have only succeeded in finding cracks in my own knowledge of
                          C. With his choice of 69069, 362437 and mask, he never busts his data
                          type. Nor can I find a non-randomness mod some smallish number.
                          There are three prng's that I use,
                          which I call "the fast one", "the good one" and "the standard one"
                          LU_RAND(S) yields alternating odd and even values,
                          which is why it's not "the good one".

                          The stamdard one is in the standard.
                          The good one is RAND_32LU(S), located here:


                          The algorithms are not original ones of mine.
                          What I've gleaned over the years of reading this newgroup
                          and comp.programmin g, is that until you become expert in prng's,
                          it's best to leave the prng algorithms to the experts.
                          "The good one" is adapted from something posted by
                          George Marsaglia who I believe is an expert on the topic.

                          The purpose of the mask, is to keep the results
                          portable in case of long having more than 32 bits.

                          Purpose of using the prng's instead of rand(),
                          is to make the results duplicatable across different C paltforms.

                          --
                          pete

                          Comment

                          • Lane Straatman

                            #14
                            Re: selecting and working with appropriate data type


                            "pete" <pfiland@mindsp ring.comwrote in message
                            news:459A98A2.F FA@mindspring.c om...
                            There are three prng's that I use,
                            which I call "the fast one", "the good one" and "the standard one"
                            LU_RAND(S) yields alternating odd and even values,
                            which is why it's not "the good one".
                            >
                            The stamdard one is in the standard.
                            The good one is RAND_32LU(S), located here:

                            >
                            The algorithms are not original ones of mine.
                            What I've gleaned over the years of reading this newgroup
                            and comp.programmin g, is that until you become expert in prng's,
                            it's best to leave the prng algorithms to the experts.
                            "The good one" is adapted from something posted by
                            George Marsaglia who I believe is an expert on the topic.
                            >
                            The purpose of the mask, is to keep the results
                            portable in case of long having more than 32 bits.
                            >
                            Purpose of using the prng's instead of rand(),
                            is to make the results duplicatable across different C paltforms.
                            It takes me a bit to play with these, but that will be easier now that I'm
                            hooked up to the net again.
                            http://www.mindspring.com/~pfilandr/...istributions.h has
                            prototypes. LS


                            Comment

                            Working...