;;;; PRELIMINARY -- ian oct.19 (fri) ;; A rank is a number in [MIN-RANK,MAX-RANK+1). (define MIN-RANK 2) (define MAX-RANK 14) ; 11 = jack; ... 13=king, 14=ace. ;; nums-upthrough: int int --> list-of-num ;; Return a list of integers [start,stop] ;; (Note that "stop" *is* in the returned list.) ;; (define (nums-upthrough start stop) (cond [(> start stop) empty] [else (cons start (nums-upthrough (add1 start) stop))])) (define suitranks (nums-upthrough MIN-RANK MAX-RANK)) (define deck (append suitranks suitranks suitranks suitranks)) ;; shuffle: list-of-ANY --> list-of-ANY ;; Return a list with the original's contents, but ;; in a scrambled order. ;; (define (shuffle stuff) (cond [(empty? stuff) empty] [(cons? stuff) (insert-at (first stuff) (random (length stuff)) (shuffle (rest stuff))) ;; insert-at: alpha, int, list-of-alpha --> list-of-alpha ;; Add newguy after n other elements of stuff. ;; Yields an error, if (> n (length stuff)). ;; (define (insert-at newguy n stuff) (cond [(zero? n) (cons newguy stuff)] [(positive? n) (cons (first stuff) (insert-at newguy (sub1 n) (rest stuff)))])) (insert-at 0 'hello empty) = '(hello) (insert-at 0 'hello '(aloha tag ciao)) = '(hello aloha tag ciao) (insert-at 2 'hello '(aloha tag ciao)) = '(aloha tag hello ciao) (shuffle empty) (shuffle (list 'a 'b 'c)) (shuffle (list 'a 'b 'c)) ;; unzip: list-of-alpha --> (list list-of-alpha list-of-alpha) ;; Return two lists, each with alternating items from "stuff". ;; (define (unzip stuff) (local [(define (unzip-help remaining bin-a bin-b) (cond [(empty? remaining) (list bin-a bin-b)] [(cons? remaining) (unzip-help (rest remaining) bin-b (cons (first remaining) bin-a))]))] (unzip-help stuff empty empty))) ;; beats?: rank, rank --> boolean ;; (define (beats? rank-a rank-b) (cond [(and (= rank-a MIN-RANK) (= rank-b MAX-RANK)) true] [(and (= rank-a MAX-RANK) (= rank-b MIN-RANK)) false] [(= rank-a rank-b) (zero? (random 2))] [else (> rank-a rank-b)])) ;; battle: list-of-two-hands --> list-of-two-hands ;; Flip top card of each hand, ;; and put them on top of the winner's deck. ;; (define (battle players) (local [(define a (first players)) (define b (second players)) (define a-card (first a)) (define b-card (first b)) (define stake (list a-card b-card))] (if (beats? a-card b-card) (list (append (rest a) stake) (rest b)) (list (rest a) (append (rest b) stake))))) (define TIMEOUT (* 100 (length deck))) ;; war: list-of-two-hands n --> {'a, 'b, 'draw} ;; Battle until somebody loses, ;; Return 'a if first player wins, or 'b if second player wins. ;; or 'draw if TIMEOUT games played. ;; ;; NOTE: May not terminate??? ;; A student pointed out: ;; (war '((2 10) (10 2))) = (war '((10) (2 10 2))) = (war '((2 10) (10 2))) ;; (This presumes than when capturing, a player always ;; puts player b's card above player a's, regardless of ;; who the winner is.) ;; (define (war players n) (local [(define a (first players)) (define b (second players))] (cond [(empty? a) 'b] [(empty? b) 'a] [(> n TIMEOUT) 'draw] [else (war (battle (list a b)) (add1 n))]))) (battle (unzip (shuffle deck))) (battle (battle (battle (battle (unzip (shuffle deck)))))) ;; go: --> {'a, 'b, 'draw} ;; PLay one game. ;; (define (go) (war (unzip (shuffle deck)) 0)) ;; tally: num --> num ;; Return the number of draws in n games. ;; (define NUMTESTS 10) (define (tally n) (cond [(zero? n) 0] [(positive? n) (+ (if (symbol=? 'draw (go)) 1 0) (tally (sub1 n)))])) ;; measure: --> num in [0,1]. ;; Return the percentage of draws in NUMTESTS games. ;; (define (measure) (/ (tally NUMTESTS) NUMTESTS)) (measure)