NAME
    Games::Cards::Poker - Pure Perl Poker functions

VERSION
    This documentation refers to version 1.4 of Games::Cards::Poker, which
    was released on Tue Jun 6 21:04:20:08 -0500 2017.

SYNOPSIS
      use Games::Cards::Poker; # deal hands
      my $players   =  4; # number of players to get hands dealt
      my $hand_size =  5; # number of cards to deal to each player
      my @hands     = (); # player hand data as array of arrayrefs
      my @deck      = Shuffle(Deck()); # initially shuffled card deck
      while (         $players--) { # load and print cards and scores
        push(@{$hands[$players]}, pop(@deck)) for(1 .. $hand_size );
        printf("Player$players score:%4d hand:@{$hands[$players]}\n",
                                    HandScore(@{$hands[$players]})); }
      # please see ex/ directory for Hold'Em and BlackJack examples

DESCRIPTION
    Poker provides a few functions for creating decks of cards and
    manipulating them for simple Poker games or simulations.

USAGE
  Deck()
    Returns a new array of scalars with the abbreviated Poker names of cards
    (e.g., 'As' for 'Ace of Spades', 'Td' for 'Ten of Diamonds', '2c' for
    'Two of Clubs', etc.).

    Use CardName() to expand abbreviated cards into their full names.

  Shuffle(@cards)
    Shuffles the passed in @cards array in one quick pass. Shuffle() returns
    a shuffled copy of the @cards array.

    Shuffle() can also take an arrayref parameter instead of an explicit
    @cards array in which case, the passed in arrayref will be shuffled in
    place so the return value does not need to be reassigned.

  SortCards(@cards)
    Sorts the passed in @cards array. SortCards() returns a sorted copy of
    the @cards array.

    SortCards() can also take an arrayref parameter instead of an explicit
    @cards array in which case, the passed in arrayref will be sorted in
    place so the return value does not need to be reassigned.

    SortCards() works consistently on the return values of ShortHand() as
    well as abbreviated cards (e.g., 'AAA', 'AAK'..'AKQs', 'AKQ'..'222').

  ShortHand(@hand)
    Returns a scalar string containing the abbreviated Poker description of
    @hand (e.g., 'AKQJTs' for any of the four possible 'Royal Flush' hands,
    'QQ993' as a specific example of one of the many possible 'Two Pair'
    hands comprised of Queens and Nines with a Three kicker, etc.).

    ShortHand() calls SortCards() on its parameter before doing the
    abbreviation in order to make sure that the return value is consistent
    (even knowing that this is typically a redundant operation).

    ShortHand() can be called on fewer cards than a full @hand of 5 to
    obtain other useful abbreviations (e.g., ShortHand(@hole) will return
    the abbreviated form of a player's two hole [pocket] cards or
    ShortHand(@flop) will abbreviate the three community cards which flop
    onto the board in Hold'Em).

  HandScore(@hand)
    Returns an integer score (where lower is better) for the passed in Poker
    @hand. This means 0 (zero) is returned for a Royal Flush and the worst
    possible score of 7461 is awarded to 7, 5, 4, 3, 2 unsuited.

    If you want higher scores to mean higher hands, just subtract the return
    value from 7461.

    All suits are considered to have equal value in this scoring function.
    It should be easy to use HandScore() as a first pass where ties can be
    resolved by another suit-comparison function if you require such
    behavior.

    This function does the inverse of ScoreHand() by accepting an array of
    cards or a ShortHand() string and returning the proper associated Poker
    score.

  ScoreHand($score)
    This function is the opposite of HandScore(). It takes an integer $score
    parameter and returns the corresponding ShortHand() string.

    ScoreHand() uses a fully enumerated table to simply index the associated
    ShortHand() so it is quite fast. The table was generated by running
    HandScore() on every possible hand and sorting the resultant unique
    ShortHand() values by their associated scores.

ADVANCED USAGE
  BestIndices(@cards)
    BestIndices() takes 5 or more cards (normally 7) which can be split
    among separate arrays (like BestIndices(@hole, @board) for Hold'Em) and
    returns an array of the indices of the 5 cards (hand) which yield the
    best score.

  BestHand(@best, @cards)
    BestHand() takes the return value of BestIndices() as the first
    parameter (which is an array of the best indices) and then the same
    other parameters (@cards) or (@hole, @board) to give you a copy of just
    the best cards. The return value of this function can be passed to
    HandScore() to get the score of the best hand.

    BestHand() can optionally take just the @cards like BestIndices() and it
    will automagically call BestIndices() first to obtain @best. It will
    then return copies of those indexed cards from the @cards.

  HandName($score)
    HandName() takes a HandScore() parameter (e.g., 0, 2000, 7000) and
    returns the name of the corresponding hand scoring category it falls
    under (e.g., 'Royal Flush', 'Three-of-a-Kind', 'High Card').

    HandName() can optionally accept an arrayref to a hand, the @hand
    itself, or a ShortHand instead of the $score parameter.

  VerboseHandName($score)
    VerboseHandName() takes a HandScore() parameter (e.g., 0, 2000, 7000)
    and returns the name of the corresponding verbose (i.e., commonly
    spoken) description of the hand (e.g., 'Aces over Kings', 'Tens, Jack
    kicker', 'Queen high, Ten kicker'). VerboseHandName() should normally be
    used in conjunction with HandName() as a further clarification of a
    specific hand's description.

    VerboseHandName() can optionally accept an arrayref to a hand, the @hand
    itself, or a ShortHand instead of the $score parameter.

  NameCard($name)
    NameCard() does the opposite of CardName() by taking an expanded full
    $name (e.g., 'Queen of Diamonds', 'Jack of Hearts', 'Ten of Clubs') and
    returning the abbreviated card (e.g., 'Qd', 'Jh', 'Tc').

  CardName($card)
    CardName() takes an abbreviated $card (e.g., 'As', 'Kh', '2c') and
    returns the expanded full name of the card ('Ace of Spades', 'King of
    Hearts', 'Two of Clubs').

  B64Card($b64c)
    B64Card() does the opposite of CardB64() by taking a base-64 card
    ($b64c) representation (e.g., 'K', 'N', 'T') and returning the
    abbreviated card (e.g., 'Qd', 'Jh', 'Tc').

  CardB64($card)
    CardB64() takes an abbreviated $card (e.g., 'As', 'Kh', '2c') and
    returns the single character (only letters) base-64 representation of
    the card ('A', 'F', 'z');

    Please see the "NOTES" section below for the complete B64 <-> Card
    conversion table.

  B64Hand($b64h)
    B64Hand() does the opposite of HandB64() by taking a string containing
    several concatenated base-64 card abbreviations and converting it into a
    list of the cards.

  HandB64(@hand)
    HandB64() takes a list of cards which make up a @hand (or a reference to
    such an array) and returns a base-64 abbreviation string.

  DecCard($decc)
    DecCard() does the opposite of CardDec() by taking a decimal card
    ($decc) representation (e.g., '0', '3', '51') and returning the
    abbreviated card (e.g., 'As', 'Ac', '2c').

  CardDec($card)
    CardDec() takes an abbreviated $card (e.g., 'As', 'Kh', '2c') and
    returns the corresponding decimal card representation ('0', '15', '51').

  DecHand($dech)
    DecHand() does the opposite of HandDec() by taking a string containing
    several concatenated decimal card abbreviations and converting it into a
    list of the cards.

  HandDec(@hand)
    HandDec() takes a list of cards which make up a @hand (or a reference to
    such an array) and returns an array of decimal abbreviations.

  BJ(@hand)
    BJ returns the boolean value of whether the passed in @hand or ShortHand
    is a BlackJack.

  BJHandScore(@hand)
    BJHandScore returns the score of the passed in @hand or ShortHand for
    BlackJack.

  BJCmp($bj_score_0, $bj_score_1)
    BJCmp is similar to <=> between the two BlackJack scores passed as
    parameters.

  RemoveCard($card, @cards)
    Returns a copy of @cards with abbreviated $card (e.g., 'Td') removed.

    RemoveCard() can also take an arrayref parameter instead of an explicit
    @cards array in which case, the passed in arrayref will be updated in
    place so the return value does not need to be reassigned.

  WorstHand(@cards)
    Returns the ShortHand description of the worst hand possible using
    @cards. This means that if there are fewer than 5 @cards, it returns
    simply the worst hand containing all of them however if there are 5 or
    more cards, it returns the same result as the abbreviated best hand
    (i.e., ShortHand(BestHand(BestIndices(@cards), @cards)) )since that is
    also the worst hand you are guaranteed to at least have out of your
    @cards.

    WorstHand() can also accept an arrayref or ShortHand parameter in place
    of a list of cards.

    WorstHand() is useful for calculating odds when you have a chance to
    improve your hand by future cards but you want to know the minimum hand
    or score you are guaranteed of.

  CountWays($bad_score_limit [,$good_score_limit])
    CountWays() helps calculate odds by summing the ways to get a range of
    abbreviated card sets (normally just ShortHands) between the
    $bad_score_limit (which starts from 7461, the bad 'High Card' end of
    hands) to the optional $good_score_limit (which starts from 0, the good
    'Royal Flush' end of hands).

  CalcOdds($hole_index)
    CalcOdds() takes the index of a hole abbreviation (e.g., values of %zloh
    CalcOdds($zloh{'AA'})) from a Hold'Em game and returns the percent that
    will win against all possibilities.

    CalcOdds() is currently a failed experiment at approximation for heads
    up situations but it will hopefully be improved later, as more Poker
    statistics can be understood and incorporated.

  FindNuts(@board)
    Returns the B64 hole descriptions of the best of all remaining possible
    pocket pairs after @board cards are determined. Maybe instead of taking
    by default the standard cards array, it too should be just a scalar of
    Suit-Abstracted B64 Boards (@{$pd8a{'sabb'}}) as the baseline to search
    out from.

  %pd8a
    %pd8a is my global Poker Data structure which contains all of the data
    used to provide this module's functionality. It can be accessed with the
    :pd8a export tag like:

      use Games::Cards::Poker qw(:pd8a);

    which only exports %pd8a, %zdnh, %zplf, and %zloh for the main data
    sets, fast reverse handz mapping to scores, and flopz and holez mapped
    to their indices.

EXPORT TAGS
    Games::Cards::Poker normally only exports a few key Poker functions
    (Deck Shuffle SortCards ShortHand ScoreHand HandScore) into your local
    namespace when you:

      use Games::Cards::Poker;

    You can specify additional export tags such as:

      use Games::Cards::Poker qw(:all);

    for when you want to utilize more than just the above default functions.

  :all
    Exports everything!

      Shuffle Deck SortCards ShortHand HandName VerboseHandName      %pd8a
      BestIndices CardB64 B64Hand CardDec DecHand ScoreHand CardName %zdnh
      BestHand    B64Card HandB64 DecCard HandDec HandScore NameCard %zplf
      WorstHand RemoveCard CountWays CalcOdds   BJHandScore BJCmp BJ %zloh
                                     FindNuts

  :best
    This tag just exports functions for finding the best hand out of some
    list of more than 5 cards.

      BestIndices BestHand

  :name
    This tag exports functions which convert between verbose names for cards
    and hands.

      CardName NameCard HandName VerboseHandName

  :b64
    This tag exports functions which convert between base-64 representations
    of cards and hands.

      CardB64 B64Card HandB64 B64Hand

  :dec
    This tag exports functions which convert between decimal representations
    of cards and hands.

      CardDec DecCard HandDec DecHand

  :odds
    This tag exports functions which should be useful in calculating odds.

      WorstHand RemoveCard CountWays CalcOdds FindNuts

  :blak
    This tag just exports functions useful for BlackJack.

      BJ BJCmp BJHandScore

  :pd8a
    This tag exports four internal data hashes in case direct access to them
    is beneficial in local namespaces. They are %pd8a, %zdnh, %zplf, and
    %zloh.

NOTES
    Suits are: s,h,d,c (Spade,Heart,Diamond,Club) like bridge
    (anti-alphabetical). Although they are sorted and appear in this order,
    suits are ignored for scoring by default (but can be optionally
    reordered and scored later)

    B64 notes: Cards map perfectly into A..Z,a..z (indx += 10) for one
    letter rep

                                                                            Suits:
      B64 Cards: A.As E.Ks I.Qs M.Js Q.Ts U.9s Y.8s c.7s g.6s k.5s o.4s s.3s w.2s 0
                 B.Ah F.Kh J.Qh N.Jh R.Th V.9h Z.8h d.7h h.6h l.5h p.4h t.3h x.2h 1
                 C.Ad G.Kd K.Qd O.Jd S.Td W.9d a.8d e.7d i.6d m.5d q.4d u.3d y.2d 2
                 D.Ac H.Kc L.Qc P.Jc T.Tc X.9c b.8c f.7c j.6c n.5c r.4c v.3c z.2c 3
          Ranks:   0    1    2    3    4    5    6    7    8    9    A    B    C

      B64 Cards: A.As B.Ah C.Ad D.Ac Ranks: 0
                 E.Ks F.Kh G.Kd H.Kc        1
                 I.Qs J.Qh K.Qd L.Qc        2
                 M.Js N.Jh O.Jd P.Jc        3
                 Q.Ts R.Th S.Td T.Tc        4
                 U.9s V.9h W.9d X.9c        5
                 Y.8s Z.8h a.8d b.8c        6
                 c.7s d.7h e.7d f.7c        7
                 g.6s h.6h i.6d j.6c        8
                 k.5s l.5h m.5d n.5c        9
                 o.4s p.4h q.4d r.4c        A
                 s.3s t.3h u.3d v.3c        B
                 w.2s x.2h y.2d z.2c        C
                 0.Jokr                    -1
          Suits:    0    1    2    3

    Error checking is minimal.

    I hope you find Games::Cards::Poker useful. Please pardon my infrequent
    release of updates.

TODO
    - upd8 release d8, regener8 README, make dist, and upload a new release,
    then close the RT WorstHand bug
    - think about gener8ing all SuitAbstracted Flopz below Holez, then Turn
    && River for all whole Boardz or Handz for betr than orig ShrtHndz dir
    structz, but recognize that alloc8ing spade && heart 1st for Hole might
    want to SortCards with Flop added so must track where orig Hole cardz
    sort to
    - mk CalcOdds() work accurately and for more opponents and factor in
    stages beyond hole
    - at least imp fast score in C version if not also here (from Nov2005
    GameDvlMag):6 4-bit nibbles, 6-elem array, 6-char string (or b13
    int?)-1st is type, rSt R ranks in significance ordr. bNchmRk dif
    approaches. Type:0==HighCard,1==Pair,2==2Pair..9==Royal. Str8s only nEd
    2nd LMNt2trak hIghSt cRd rank

CHANGES
    Revision history for Perl extension Games::Cards::Poker:

    - 1.4 H66ML4K8 Tue Jun 6 21:04:20:08 -0500 2017
        * prepended new Pod tests and renumbered all others, added test
        names to all tests

        * started FindNuts() to hopefully compute what BenB's old
        flop-gen.pl was looking for

        * fixed WorstHand() on As 2s from returning FullHouse
        HTTPS://RT.CPAN.Org/Public/Bug/Display.html?id=100391 (Thanks Iain!)

        * removed all old PDat duplicate data structures && accessor
        functions && renamed %pdat to %pd8a with matching :pd8a export tag
        which also has holz,flpz,hndz

        * removed all %pdat ways d8a (since all should be gener8d easily) &&
        replaced lists with just qw() && fixed CountWays() && CalcOdds() to
        gener8 nstd of index

        * got rid of OrigHandScore except good category commentz

        * audited all of old MANIFEST, yanked SuitAbstraction.pm, fixed
        t/*.t, && it seems like none of following old bin files are really
        needed until maybe l8r after reviving CalcOdds (so I'm removing all
        of the old bin/ from the next release):

          bin/tstPoker.pl  - generate test runs of Texas Hold'Em poker hands and print out the results (probably just a precursor to ex/txholdem.pl ?)
          bin/runHands.pl  - create MySQL databases and tables for storing Games::Cards::Poker exhaustive odds data
          bin/findOdds.pl  - try to query odds from a pre-generated MySQL database
          bin/mkDecks.pl   - made suit-abstracted B64 hole pairs but could all be in qw()
          bin/mkTable.pl   - select odds from a MySQL server populated by runHands.pl and build HTML summary of results for all holes versus each number of opponents
          bin/mkHoleDr.pl  - make 'h' . ShortHand(@hole) directories (not suit-abstracted B64 but just joined Ranks maybe 's'uited together)
          bin/mkHoleDr.bat - a batch file generated to do the same as the above .pl file
          bin/Makefile     - make pokr.c into pokr executable binary
          bin/pokr.c       - C source file for generating *.ppx files?
          bin/mkPPX.pl     - try to compile a root h.ppx file from all subdirectories
          bin/h.ppx        - example root hole Pip's Poker Xml aggregate odds file
          bin/ckOdds.pl    - lookup odds within already explored .ppx directory structure
          bin/pokrlocl.pl  - attempt to provide a local interactive (Perl/Tk) interface to pokr odds
          bin/index.cgi    - provide a basic web-interface to picking game-state to query odds

        * replaced Hold'Em and BlackJack synopsis examples with new ex/ .pl
        scripts

        * updated license to GPLv3

        * s/Slow//g && further downplayed OrigHandScore

        * s/(Hand|Score)(Score|Hand)/$2$1/g to be consistent with others
        (e.g., CardB64 implying X-to-Y)

        * s/(for)each/$1/g

        * fixed DecCard(0) to return 'As' error reported by Dan C.

        * restored code &&'s, reverted license

    - 1.2.565CHh5 Sun Jun 5 12:17:43:05 2005
        * added VerboseHandName() from code contributed by Roy Lyons

        * fixed Shuffle() off-by-one results skewing error reported by Lee

    - 1.2.4CCJ12M Sun Dec 12 19:01:02:22 2004
        * added MySQL and XML and .c and Tk scripts to bin/

        * fixed pod typo and updated License

    - 1.2.46QD4ax Sat Jun 26 13:04:36:59 2004
        * added Dec functions

    - 1.2.4610lBw Tue Jun 1 00:47:11:58 2004
        * removed benchmrk.pl since it's not worth including in pkg

        * fixed some out-of-date POD and rearranged USAGE

    - 1.2.45UGmiC Sun May 30 16:48:44:12 2004
        * upped minor version number since CPAN doesn't recognize my PTVR

        * split test.pl into t/*.t and added those + bin/pokr to MANIFEST

        * added separate EXPORT_TAGS and added ADVANCED USAGE POD

        * added RemoveCard(), WorstHand(), CountWays(), and CalcOdds()

        * added %pdat as common structure for all my Poker Data and Counts

        * added B64Hand and HandB64 functions

        * added simple accessors to internal data

        * added possible hole and flop data

        * made CardName take either of just rank or suit

        * made new b64 card conversion functions: CardB64() and B64Card()

        * changed b64 maps to use letters

    - 1.0.44P0KER Sun Apr 25 00:20:14:27 2004
        * made CardName() to return 'Ace of Spades' or 'Two of Clubs' for
        'As'or'A' or '2c'or'z' and NameCard() to do inverse

        * made HandName() to return 'Royal Flush' or 'High Card' for
        ScoreHand() or ShortHand() or @hand or \@hand and NameHand()

        * rewrote SortCards() to accept any length ShortHand() params

        * s/valu/rank/g s/scor/score/g s/bord/board/g

    - 1.0.44LCEw8 Wed Apr 21 12:14:58:08 2004
        * s/HoldEm//g; on advice from Joe since Best*() are useful for more
        than just Hold'Em (like 7-card stud)

        * fixed minor typos in POD

    - 1.0.44KFNKP Tue Apr 20 15:23:20:25 2004
        * wrote UseSlow() so that benchmrk.pl would still work without
        Best() and in case anyone would rather have ScoreHand() call
        SlowScoreHand() every time instead.

        * since my old Best() was actually slower than BestHoldEmIndices()
        =O I removed Best().

        * since old Scor() was so much faster than old ScoreHand(), I
        renamed them to ScoreHand() and SlowScoreHand() respectively since
        computational version is unnecessary now.

        * wrote benchmrk.pl to test BestHoldEmIndices() + ScoreHand()
        against Best() + Scor(). Best()+Scor() only took 60% as long to run.

        * added SortCards() call on ShortHand() param just in case

    - 1.0.44ILBKV Sun Apr 18 21:11:20:31 2004
        * wrote Scor() with gen'd enumerated hash of ShortHand => Score

        * wrote HandScore() to just lookup index of a ShortHand from a score

        * squashed 4 scoring bugs in one pair section

        * used Algorithm::ChooseSubsets for new BestHoldEmIndices (on Jan's
        recommendation)

        * renamed enumerated BestHoldEmIndices() as Best()

        * gave ScoreHand() optional arrayref param like others

        * gave ScoreHand() optional ShortHand() string param

        * updated 2do and tidied up documentation a bit

    - 1.0.44H2DUS Sat Apr 17 02:13:30:28 2004
        * added BestHoldEmIndices() and BestHoldEmHand() for Tim and Jan

        * commented unnecessary Games::Cards inheritance since I haven't
        written any compatability / object interface yet

    - 1.0.44F2Q8F Thu Apr 15 02:26:08:15 2004
        * original version

INSTALL
    Please run:

      `perl -MCPAN -e "install Games::Cards::Poker"`

    or uncompress the package and run the standard:

      `perl Makefile.PL; make; make test; make install`

FILES
    Games::Cards::Poker requires:

    Algorithm::ChooseSubsets to allow searching for best cards

BUGS
    Please report any bugs or feature requests to bug-Games-Cards-Poker at
    RT.CPAN.Org, or through the web interface at
    <HTTPS://RT.CPAN.Org/NoAuth/ReportBug.html?Queue=Games-Cards-Poker>. I
    will be notified, and then you can be updated of progress on your bug as
    I address fixes.

SUPPORT
    You can find documentation for this module with the perldoc command.

      `perldoc Games::Cards::Poker`

    You can also look for information at:

        RT: CPAN's Request Tracker

      L<HTTPS://RT.CPAN.Org/NoAuth/Bugs.html?Dist=Games-Cards-Poker>

        AnnoCPAN: Annotated CPAN documentation

      L<HTTP://AnnoCPAN.Org/dist/Games-Cards-Poker>

        CPAN Ratings

      L<HTTPS://CPANRatings.Perl.Org/d/Games-Cards-Poker>

        Search  CPAN

      L<HTTP://Search.CPAN.Org/dist/Games-Cards-Poker>

LICENSE
    Most source code should be Free! Code I have lawful authority over is
    and shall be! Copyright: (c) 2004-2017, Pip Stuart. Copyleft : This
    software is licensed under the GNU General Public License (version 3 or
    later). Please consult <HTTPS://GNU.Org/licenses/gpl-3.0.txt> for
    important information about your freedom. This is Free Software: you are
    free to change and redistribute it. There is NO WARRANTY, to the extent
    permitted by law. See <HTTPS://FSF.Org> for further information.

AUTHOR
    Pip Stuart <Pip@CPAN.Org>