; ranks are 2-14 with 2 being two, 13 being king, and 14 being ace ; suits are 1-4 with no particular labelling ; takes a list of five cards (rank . suit) and returns the value of the best poker ; hand which can be made with them ; Hands are represented: ; straight flush (5 high_card) ; 4 of a kind (4 1 quad_rank kicker) ; full house (3 2 set_rank pair_rank) ; flush (3 1 3 high_card first_kicker second_kicker third_kicker fourth_kicker) ; straight (3 1 2 high_card) ; set (3 1 1 set_rank first_kicker second_kicker) ; two pair (2 2 1 high_pair_rank low_pair_rank kicker) ; pair (2 1 1 1 pair_rank first_kicker second_kicker third_kicker) ; high card (1 1 1 1 1 high_card first_kicker second_kicker third_kicker fourth_kicker) ( (defun hand_compare (a b) (if (= (f a) (f b)) (if (r a) (hand_compare (r a) (r b)) 0 ) (- (* 2 (> (f a) (f b))) 1) ) ) (defun hand< (a b) (= (hand_compare a b) -1) ) (defun merge (a b) (if (not a) b (if (not b) a (if (> (f a) (f b)) (c (f a) (merge (r a) b)) (c (f b) (merge a (r b))) ) ) ) ) ; Sorts atoms into descending order ; This is optimized for sorting short lists ; A more general function would return a list of lists of ascending sizes ; to be merged (defun atomsort ((@ firstpos (first @ secondpos (second @ thirdpos (third . remaining))))) (if firstpos (if secondpos (if thirdpos (assign-lambda mylist (if (> first second) (if (> second third) (list first second third) (if (> first third) (list first third second) (list third first second) ) ) (if (> first third) (list second first third) (if (> second third) (list second third first) (list third second first) ) ) ) (merge mylist (atomsort remaining)) ) (if (> first second) firstpos (list second first) ) ) firstpos ) 0 ) ) (defun check_flush (@ cards ((rank1 . suit1) (rank2 . suit2) (rank3 . suit3) (rank4 . suit4) (rank5 . suit5))) (logand (= suit1 suit2) (= suit1 suit3) (= suit1 suit4) (= suit1 suit5)) ) ; returns the high card of a straight or 0 if there isn't any (defun straight_high (@ all-args (count1 count2 count3 count4 count5 rank1 rank2 rank3 rank4 rank5)) (if (not (= count1 1)) 0 (= rank5 (- rank1 4)) rank1 (= rank1 14) (* (= rank2 5) 5) 0 ) ) (defun flatten_card ((rank . suit)) (logior (lsh rank 4) suit) ) (defun unflatten_card (my_card) (c (lsh my_card -4) (logand my_card 15)) ) (defun group_by_count_inner (items last count) (if (not items) (list (flatten_card (c count last))) (if (= (f items) last) (group_by_count_inner (r items) last (+ count 1)) (c (flatten_card (c count last)) (group_by_count_inner (r items) (f items) 1)) ) ) ) (defun group_by_count (items) (group_by_count_inner items (f items) 0) ) (defun ranks_of_hand (count1 count2 count3 count4 count5 . ranks) ranks ) (defun onehandcalc ((@ cards ((card1rank . card1suit) (card2rank . card2suit) (card3rank . card3suit) (card4rank . card4suit) (card5rank . card5suit)))) (assign-lambda ranks (atomsort (list card1rank card2rank card3rank card4rank card5rank)) raw_groups (atomsort (group_by_count ranks)) hand (map (lambda (x) (lsh x -4)) raw_groups (map (lambda (x) (logand x 15)) raw_groups)) shigh (straight_high &rest hand) (if shigh (if (check_flush &rest cards) (list 5 shigh) (if (logior (= (f hand) 4) (logand (= (f hand) 3) (= (f (r hand)) 2))) hand (list 3 1 2 shigh) ) ) (if (logand (check_flush &rest cards) (logior (< (f hand) 3) (logand (= (f hand) 3) (< (f (r hand)) 2)))) (list 3 1 3 (ranks_of_hand &rest hand)) hand ) ) ) ) )