Due: Oct 10, 2012 CS 580 Fall 2012 Dr. Duric Homework #2 (45p) In your second homework you will start writing a program for playing a popular card game called 'Texas Hold'em Poker'. If you are not familiar with the game full rules can be found here: http://boardgames.about.com/cs/poker/a/texas_rules.htm In the first part of your assignment you will learn the rules of the game. You do not need to play it, but it might help you if you do. We do not recommend that you spend the time playing the game to become really good, only to learn the rules. As you can see in a game each player has two face-down cards ('hole cards') and can also make use of the three 'communal' cards which are available to all players. Each player can combine their own cards and the communal cards to make a hand. Hand strengths can be seen here: http://boardgames.about.com/cs/poker/a/poker_hands.htm Note that if two players have equivalent hands they are compared by the relative strengths of the cards in those hands. For example, a pair of Queens is stronger than a pair of 8s. After you have learned the rules of the game you will start implementing a program for playing the game. You will implement the following functions first: 1. (15p) You will first write a RandomShuffle function that will take a deck of cards in the format ((Card1 Suit1) (Card2 Suit1) ... (Card1 Suit2) ... (Card1 Suit3) ... (Card14 Suit4)) where Card1-Card13 is the sequence (A 2 3 4 5 6 7 8 9 10 J Q K) and Suit1-Suit4 is the sequence (Spades Diamonds Hearts Clubs) [See for example http://en.wikipedia.org/wiki/Suit_(cards)] The function will return a random sequence of 52 card pairs. The easiest way to implement the function is to choose an index into the deck sequence at random and move that card (pair) from the deck into the new 'shuffled' deck, and then repeat. You should create a deck separately and pass it as an argument to your function. That will simplify your work later. In addition, use the length of the sequence to be shuffled as a local variable. 2. (30p) You will write functions to evaluate poker hands. You will write a function CompareHands which will take two poker hands of five cards each and determine which hand is better. The function should return 1 if the first hand is better, 0 if the hands are equal, and -1 if the second hand is better. Each hand is given as a list of five pairs (card suit), for example: (setf hand1 '((2 C) (8 C) (J C) (5 C) (K C))) (setf hand2 '((8 S) (7 S) (2 S) (J S) (K S))) (CompareHands hand1 hand2) should return -1. The rules that determine strengths of the hands are given at: http://boardgames.about.com/cs/poker/a/poker_hands.htm Notice that in case of ties you need to apply tie-breaking rules: http://www.pokerhands.com/poker_hand_tie_rules.html You can write as many help functions as you want to work with your CompareHands function. These are the prototype functions in a possible implementation: ------------------------ ;; NumericalHand ;; replace A by 1, J by 11, Q by 12, K by 13 (defun NumericalHand (hand) (let ((new-hand nil) (cardvals nil) (straight nil)) (setf new-hand (mapcar #'(lambda (x) (cond ((eq (first x) 'A) (list 1 (second x))) ((eq (first x) 'J) (list 11 (second x))) ((eq (first x) 'Q) (list 12 (second x))) ((eq (first x) 'K) (list 13 (second x))) (t x))) hand)) (setf cardvals (sort (mapcar #'(lambda (x) (first x)) new-hand) #'<)) (setf straight (and (eq (first cardvals) 1) (eq (second cardvals) 2) (eq (third cardvals) 3) (eq (fourth cardvals) 4) (eq (fifth cardvals) 5))) (if straight (SortHand new-hand) ;; keep A's as 1's - have straight (SortHand (mapcar #'(lambda (x) (if (eq (first x) 1) (list 14 (second x)) x)) new-hand))))) Examples: (NumericalHand '((2 C) (8 C) (J C) (5 C) (K C))) ((2 C) (5 C) (8 C) (11 C) (13 C)) (NumericalHand '((2 C) (A C) (3 H) (4 C) (5 D))) ((1 C) (2 C) (3 H) (4 C) (5 D)) ------------------------- ;; Sort hand by card value (defun SortHand (hand) (sort hand #'(lambda (x y) (< (first x) (first y))))) ------------------------- ;; EvaluateHand ;; Evaluate hand from strongest to weakest ;; Input: 5 card hand ;; Return value: ;; ((RoyalFlush Suit) ;; have royal flush give suit, otherwise nil ;; (StraightFlush HighCard Suit) ;; high card value & suit, otherwise nil ;; (FourOfAKind CardVal) ;; (FullHouse HighCardVal LowCardVal) ;; HighCardVal - three of a kind value, LowCard - pair value ;; (Flush HighCard Suit) ;; (Straight HighCard) ;; (ThreeOfAKind CardVal) ;; (TwoPair HighCardVal LowCardVal) ;; (Pair CardVal) ;; HighCardVal) (defun EvaluateHand (hand) () Examples: 260]> (EvaluateHand (NumericalHand '((2 C) (A C) (3 H) (4 C) (5 D)))) (NIL NIL NIL NIL NIL (STRAIGHT 5) NIL NIL NIL 14) [261]> (EvaluateHand (NumericalHand '((2 C) (10 C) (J C) (Q C) (K C)))) (NIL NIL NIL NIL (FLUSH 13 C) NIL NIL NIL NIL 13) [262]> (EvaluateHand (NumericalHand '((8 S) (10 S) (10 D) (10 H) (10 C)))) (NIL NIL (FOUROFAKIND 10) NIL NIL NIL NIL NIL NIL 10) [263]> (EvaluateHand (NumericalHand '((8 S) (10 S) (A D) (10 H) (10 C)))) (NIL NIL NIL NIL NIL NIL (THREEOFAKIND 10) NIL NIL 14) [264]> (EvaluateHand (NumericalHand '((8 S) (10 S) (A D) (6 H) (10 C)))) (NIL NIL NIL NIL NIL NIL NIL NIL (PAIR 10) 14) ----------------------- ;; function to break ties; compare two hands until one card is higher or done ;; return 1 if hand1 is better, -1 if hand2 is better and 0 otherwise ;; only card values are given in reverse order (from highest to lowest) (defun BreakTies (cvals1 cvals2) ;; (format t "~% cvals1 = ~A cvals2 = ~A ~%" cvals1 cvals2) (cond ((or (null cvals1) (null cvals2)) 0) ((> (first cvals1) (first cvals2)) 1) ((< (first cvals1) (first cvals2)) -1) (t (BreakTies (rest cvals1) (rest cvals2)))) ) ;; check if all cards are different (defun All-Diff (cardvals) (and (< (first cardvals) (second cardvals)) (< (second cardvals) (third cardvals)) (< (third cardvals) (fourth cardvals)) (< (fourth cardvals) (fifth cardvals)))) ----------------------- ;; COMPAREHANDS ;; given two hands of five cards each determine if hand1 is stronger than hand2 ;; there are three possible return values ;; 1: hand1 is better ;; -1: hand2 is better ;; 0: hands are equal (defun CompareHands (hand1 hand2) () Examples: [265]> (setf hand1 '((2 C) (8 C) (J C) (5 C) (K C))) ((2 C) (8 C) (J C) (5 C) (K C)) [266]> (setf hand2 '((8 S) (7 S) (2 S) (J S) (K S))) ((8 S) (7 S) (2 S) (J S) (K S)) [267]> (CompareHands hand1 hand2) -1 Instructions for submission: ---------------------------- (1) Using script or dribble, you are to capture the output of a Lisp session in which you successfully load and execute your code, showing sufficient testing of your function(s). (2) Send a SINGLE email to formatted in the following way: - the subject field of the email should read: CS580 HW#2 Duric - the content of the email should be : (a) a cover sheet containing: Your name CS580 Fall 2012 Dr. Duric Homework #2 (A short summary stating whether you were successful, describing any problems, etc.) (b) a commented version of the Lisp code for HW2. Comments at the top should include: Your name CS580 Fall 2012 Dr. Duric Homework #2 (c) a printout of a captured Lisp session involving the execution of the HW2 Lisp code As a safety precaution, always CC yourself when you submit homework this way and keep it around until it has been graded and returned.