]> gitweb.factorcode.org Git - factor.git/blob - extra/poker/poker.factor
Merge branch 'master' of git://projects.elasticdog.com/git/factor
[factor.git] / extra / poker / poker.factor
1 ! Copyright (c) 2009 Aaron Schaefer.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors ascii binary-search combinators kernel locals math
4     math.bitwise math.order poker.arrays sequences splitting ;
5 IN: poker
6
7 ! The algorithm used is based on Cactus Kev's Poker Hand Evaluator:
8 !     http://www.suffecool.net/poker/evaluator.html
9
10 <PRIVATE
11
12 ! Bitfield Format for Card Values:
13
14 !     +-------------------------------------+
15 !     | xxxbbbbb bbbbbbbb ssssrrrr xxpppppp |
16 !     +-------------------------------------+
17 !       xxxAKQJT 98765432 CDHSrrrr xxpppppp
18 !     +-------------------------------------+
19 !     | 00001000 00000000 01001011 00100101 |  King of Diamonds
20 !     | 00000000 00001000 00010011 00000111 |  Five of Spades
21 !     | 00000010 00000000 10001001 00011101 |  Jack of Clubs
22
23 ! p = prime number value of rank (deuce = 2, trey = 3, four = 5, ..., ace = 41)
24 ! r = rank of card (deuce = 0, trey = 1, four = 2, ..., ace = 12)
25 ! s = bit turned on depending on suit of card
26 ! b = bit turned on depending on rank of card
27 ! x = bit turned off, not used
28
29 CONSTANT: CLUB     8
30 CONSTANT: DIAMOND  4
31 CONSTANT: HEART    2
32 CONSTANT: SPADE    1
33
34 CONSTANT: DEUCE  0
35 CONSTANT: TREY   1
36 CONSTANT: FOUR   2
37 CONSTANT: FIVE   3
38 CONSTANT: SIX    4
39 CONSTANT: SEVEN  5
40 CONSTANT: EIGHT  6
41 CONSTANT: NINE   7
42 CONSTANT: TEN    8
43 CONSTANT: JACK   9
44 CONSTANT: QUEEN  10
45 CONSTANT: KING   11
46 CONSTANT: ACE    12
47
48 CONSTANT: STRAIGHT_FLUSH   1
49 CONSTANT: FOUR_OF_A_KIND   2
50 CONSTANT: FULL_HOUSE       3
51 CONSTANT: FLUSH            4
52 CONSTANT: STRAIGHT         5
53 CONSTANT: THREE_OF_A_KIND  6
54 CONSTANT: TWO_PAIR         7
55 CONSTANT: ONE_PAIR         8
56 CONSTANT: HIGH_CARD        9
57
58 CONSTANT: RANK_STR { "2" "3" "4" "5" "6" "7" "8" "9" "T" "J" "Q" "K" "A" }
59
60 CONSTANT: VALUE_STR { "" "Straight Flush" "Four of a Kind" "Full House" "Flush"
61     "Straight" "Three of a Kind" "Two Pair" "One Pair" "High Card" }
62
63 : card-rank-prime ( rank -- n )
64     RANK_STR index { 2 3 5 7 11 13 17 19 23 29 31 37 41 } nth ;
65
66 : card-rank ( rank -- n )
67     {
68         { "2" [ DEUCE ] }
69         { "3" [ TREY  ] }
70         { "4" [ FOUR  ] }
71         { "5" [ FIVE  ] }
72         { "6" [ SIX   ] }
73         { "7" [ SEVEN ] }
74         { "8" [ EIGHT ] }
75         { "9" [ NINE  ] }
76         { "T" [ TEN   ] }
77         { "J" [ JACK  ] }
78         { "Q" [ QUEEN ] }
79         { "K" [ KING  ] }
80         { "A" [ ACE   ] }
81     } case ;
82
83 : card-suit ( suit -- n )
84     {
85         { "C" [ CLUB    ] }
86         { "D" [ DIAMOND ] }
87         { "H" [ HEART   ] }
88         { "S" [ SPADE   ] }
89     } case ;
90
91 : card-rank-bit ( rank -- n )
92     RANK_STR index 1 swap shift ;
93
94 : card-bitfield ( rank rank suit rank -- n )
95     {
96         { card-rank-bit 16 }
97         { card-suit 12 }
98         { card-rank 8 }
99         { card-rank-prime 0 }
100     } bitfield ;
101
102 :: (>ckf) ( rank suit -- n )
103     rank rank suit rank card-bitfield ;
104
105 : >ckf ( str -- n )
106     #! Cactus Kev Format
107     >upper 1 cut (>ckf) ;
108
109 : flush? ( cards -- ? )
110     HEX: F000 [ bitand ] reduce 0 = not ;
111
112 : rank-bits ( cards -- q )
113     0 [ bitor ] reduce -16 shift ;
114
115 : lookup ( cards table -- value )
116     [ rank-bits ] dip nth ;
117
118 : unique5? ( cards -- ? )
119     unique5-table lookup 0 > ;
120
121 : map-product ( seq quot -- n )
122     [ 1 ] 2dip [ dip * ] curry [ swap ] prepose each ; inline
123
124 : prime-bits ( cards -- q )
125     [ HEX: FF bitand ] map-product ;
126
127 : hand-value ( cards -- value )
128     {
129         { [ dup flush?   ] [ flushes-table lookup ] }
130         { [ dup unique5? ] [ unique5-table lookup ] }
131         [
132             prime-bits products-table sorted-index
133             values-table nth
134         ]
135     } cond ;
136
137 : >card-rank ( card -- str )
138     -8 shift HEX: F bitand RANK_STR nth ;
139
140 : >card-suit ( card -- str )
141     {
142         { [ dup 15 bit? ] [ drop "C" ] }
143         { [ dup 14 bit? ] [ drop "D" ] }
144         { [ dup 13 bit? ] [ drop "H" ] }
145         [ drop "S" ]
146     } cond ;
147
148 PRIVATE>
149
150 TUPLE: hand
151     { cards sequence }
152     { value integer } ;
153
154 M: hand <=> [ value>> ] compare ;
155 M: hand equal?
156     over hand? [ [ value>> ] bi@ = ] [ 2drop f ] if ;
157
158 : <hand> ( str -- hand )
159     " " split [ >ckf ] map
160     dup hand-value hand boa ;
161
162 : hand-rank ( hand -- rank )
163     value>> {
164         { [ dup 6185 > ] [ drop HIGH_CARD ] }        ! 1277 high card
165         { [ dup 3325 > ] [ drop ONE_PAIR ] }         ! 2860 one pair
166         { [ dup 2467 > ] [ drop TWO_PAIR ] }         !  858 two pair
167         { [ dup 1609 > ] [ drop THREE_OF_A_KIND ] }  !  858 three-kind
168         { [ dup 1599 > ] [ drop STRAIGHT ] }         !   10 straights
169         { [ dup 322 > ]  [ drop FLUSH ] }            ! 1277 flushes
170         { [ dup 166 > ]  [ drop FULL_HOUSE ] }       !  156 full house
171         { [ dup 10 > ]   [ drop FOUR_OF_A_KIND ] }   !  156 four-kind
172         [ drop STRAIGHT_FLUSH ]                      !   10 straight-flushes
173     } cond ;
174
175 : >value ( hand -- str )
176     hand-rank VALUE_STR nth ;
177
178 : >cards ( hand -- str )
179     cards>> [
180         [ >card-rank ] [ >card-suit ] bi append
181     ] map " " join ;