Advertisement
Guest User

Untitled

a guest
Jun 26th, 2017
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scheme 11.27 KB | None | 0 0
  1. ;;
  2. ;; Artificial Intelligence - Lab 6 - Games
  3. ;;
  4.  
  5. ; README: explicarea implementarii
  6. ; Strategia implementata functioneaza in felul urmator:
  7. ; - AI-ul tine intern o multime a tuturor cartilor din pachet,
  8. ;   pe baza a ceea ce se afla pe masa si a ce s-a impartit anterior.
  9. ; - daca mana AI-ului e mai proasta decat a adversarului, acesta
  10. ;   face hit, cu riscul de a pierde (nu tine cont de asta).
  11. ; - altfel, isi evalueaza sansele de a face bust: daca probabilitatea
  12. ;   de bust (nr carti busted/nr total de carti din pachet) e cel
  13. ;   putin 50%, atunci executa stand, altfel hit.
  14. ; - practic, se aduna mana curenta la fiecare tip de carte
  15. ;   ce poate fi impartita si se vede daca vreo posibila mana
  16. ;   viitoare poate da peste 21. Daca da, atunci se calculeaza
  17. ;   probabilitatea de a face bust.
  18.  
  19. ;
  20. ; Helper functions
  21. ;
  22.  
  23. ; Generate a full set of card numbers
  24. (define gen-cardset
  25.   (lambda ()
  26.     (let do-gen ((n 10))
  27.       (if (= n 0)
  28.           '()
  29.           (cons (cons n 4) (do-gen (- n 1)))
  30.       )
  31.     )
  32.   )
  33. )
  34.  
  35. ; Check if a given set contains a given card number
  36. (define contains-card?
  37.   (lambda (n set)
  38.     (if (null? set)
  39.         #f
  40.         (let* ((tup (car set))
  41.                (rest (cdr set))
  42.                (card (car tup))
  43.                (num (cdr tup))
  44.               )
  45.           (if (and (= n card) (not (= num 0)))
  46.               #t
  47.               (contains-card? n rest)
  48.           )
  49.         )
  50.     )
  51.   )
  52. )
  53.  
  54. ; Remove a given card from the set. Returns the
  55. ; modified set or the same set if card doesn't exist
  56. (define remove-card
  57.   (lambda (n set)
  58.     (if (null? set)
  59.         '()
  60.         (let* ((tup (car set))
  61.                (rest (cdr set))
  62.                (card (car tup))
  63.                (num (cdr tup))
  64.               )
  65.           (if (= n card)
  66.               (let ((num1 (- num 1)))
  67.                 (if (<= num1 0)
  68.                     rest
  69.                     (cons (cons card num1) rest)
  70.                 )
  71.               )
  72.               (cons tup (remove-card n rest))
  73.           )
  74.        )
  75.     )
  76.   )
  77. )
  78.  
  79. ; Gets all existent card numbers from a set
  80. (define get-cards
  81.   (lambda (set)
  82.     (map car set)
  83.   )
  84. )
  85.  
  86. (define get-numbers
  87.   (lambda (set)
  88.     (map cdr set)
  89.   )
  90. )
  91.  
  92. ; Set difference - first set *must* be in the
  93. ; dotted pair format, second set can be a '(card type)
  94. ; list.
  95. (define set-diff
  96.   (lambda (s1 s2)
  97.     (let do-diff ((s1 s1)
  98.                   (cards (get-cards s2))
  99.                  )
  100.       (if (null? cards)
  101.           s1
  102.           (do-diff (remove-card (car cards) s1)
  103.                    (cdr cards))
  104.       )
  105.     )
  106.   )
  107. )
  108.  
  109. ; Check the current state and return an action
  110. ; Game strategy goes here, basically
  111. (define check-state
  112.   (lambda (state hishand myhand)
  113.     (if (>= (sum-hand hishand) (sum-hand myhand))
  114.         'hit
  115.         (let* ((handsum (sum-hand myhand))
  116.                (addhand (lambda (tup) (cons (+ (car tup) handsum)
  117.                                             (cdr tup))))
  118.                (gt21 (lambda (tup) (cons (> (car tup) 21) (cdr tup))))
  119.                (summed (map addhand state))
  120.                (gt21-cards (map gt21 summed))
  121.                (canlose? (foldl (lambda (a b) (or a b))
  122.                                 #f (get-cards gt21-cards)))
  123.               )
  124.           (if canlose?
  125.               (let* ((num-cards (foldl + 0 (get-numbers state)))
  126.                     (busted? (lambda (tup) (car tup)))
  127.                     (num-bust (get-numbers
  128.                                (filter busted? gt21-cards)))
  129.                     (tot-bust (foldl + 0 num-bust))
  130.                    )
  131.                 (if (< (/ tot-bust num-cards) (/ 1 2))
  132.                     'hit
  133.                     'stand
  134.                 )
  135.               )
  136.               'hit
  137.           )
  138.         )
  139.     )
  140.   )
  141. )
  142.  
  143. ; strategy for the AI player
  144. ; parameters:
  145. ;   hand1 - player's hand
  146. ;   hand2 - AI's hand
  147. ;   ai-state - internal state of the player
  148. ; returns one of the following:
  149. ;   (list 'hit new-ai-state)
  150. ;   (list 'stand new-ai-state)
  151. ; where new-ai-state is the new internal state of the AI player
  152. (define do-ai-strategy
  153.   (lambda (hand1 hand2 ai-state)
  154.     (display "my hand: ") (display hand2) (newline)
  155.     (display "my sum: ") (display (sum-hand hand2)) (newline)
  156.     (display "ai-state: ") (display ai-state) (newline)
  157.     (if (null? ai-state)
  158.         (let* ((new-set (gen-cardset))
  159.                (new-state (set-diff (set-diff new-set hand1)
  160.                                     hand2))
  161.               )
  162.           (list (check-state new-state hand1 hand2) new-state)
  163.         )
  164.         (let ((new-state (set-diff (set-diff ai-state hand1)
  165.                                    hand2))
  166.              )
  167.           (list (check-state new-state hand1 hand2) new-state)
  168.         )
  169.     )
  170.   )
  171. )
  172.  
  173. ; play a game of 21
  174. ; state of the game is (pack (hand1 hand2) ai-state round)
  175. ; where:
  176. ;   pack is the pack of cards
  177. ;   hand1 is player's hand
  178. ;   hand2 is  AI's hand
  179. ;   ai-state is the internal state of the AI player
  180. ;   round is the number of the current round
  181. (define play21
  182.   (lambda ()
  183.     (let* ((pack (random-shuffle (generate-pack)))
  184.            (state (list pack '(() ()) '() 0)))
  185.       (run-game state 0)
  186.     )
  187.   )
  188. )
  189.  
  190. ; runs the game
  191. ; turn is:
  192. ;   0 for start of the game
  193. ;   1 for AI's turn
  194. ;   2 for player's turn
  195. ;   3 for end of round
  196. (define run-game
  197.   (lambda (state turn)
  198.     (let* ((winner (check-winner state (= turn 3)))
  199.            (pack (car state))
  200.            (hands (cadr state))
  201.            (ai-state (caddr state))
  202.            (round (cadddr state)))
  203.       (cond
  204.         ((= turn 0) ; start of round
  205.           (let* ((hand1 (list (caddr pack) (car pack)))
  206.                  (hand2 (list (cadddr pack) (cadr pack)))
  207.                  (pack (cddddr pack))
  208.                  (hands (list hand1 hand2))
  209.                  (round (+ round 1))
  210.                  (state (list pack hands ai-state round)))
  211.             (display "\n====================\n")
  212.             (display "Round ")
  213.             (display round)
  214.             (display "\n====================\n\n")
  215.             (run-game state 1)
  216.           )
  217.         )
  218.         (winner ; end of game?
  219.           (begin
  220.             (display "Winner: ")
  221.             (display winner)
  222.             (newline)
  223.             (display "Play again? (y/n): ")
  224.             (if (eq? (read) 'y)
  225.               (run-game state 0)
  226.             )
  227.           )
  228.         )
  229.         ((= turn 1) ; AI's turn
  230.           (move-ai state))
  231.         ((= turn 2) ; player's turn
  232.           (move-player state))
  233.       )
  234.     )
  235.   )
  236. )
  237.  
  238. ; check if any player busts, or who wins if the game is over
  239. (define check-winner
  240.   (lambda (state over)
  241.     (let* ((pack (car state))
  242.            (hands (cadr state))
  243.            (hand1 (car hands))  ; player's hand
  244.            (hand2 (cadr hands)) ; AI's hand
  245.            (sum1 (sum-hand hand1))
  246.            (sum2 (sum-hand hand2)))
  247.       (show-hands hands)
  248.       (cond
  249.         ((> sum1 21)            ; player busts, AI wins
  250.           (begin
  251.             (display "Player busts!\n")
  252.             'AI))
  253.         ((> sum2 21)            ; AI busts, player wins
  254.           (begin
  255.             (display "AI busts!\n")
  256.             'PLAYER))
  257.         ((or (null? pack) over) ; pack finished or game over
  258.           (cond
  259.             ((> sum1 sum2) 'PLAYER)
  260.             ((< sum1 sum2) 'AI)
  261.             (else 'DRAW)
  262.           )
  263.         )
  264.         (else #f)               ; game not over yet
  265.       )
  266.     )
  267.   )
  268. )
  269.  
  270. ; do a move for the AI
  271. (define move-ai
  272.   (lambda (state)
  273.     (let* ((pack (car state))
  274.            (hands (cadr state))
  275.            (hand1 (car hands))
  276.            (hand2 (cadr hands))
  277.            (ai-state (caddr state))
  278.            (round (cadddr state))
  279.            (r (do-ai-strategy hand1 hand2 ai-state))
  280.            (x (car r))
  281.            (new-ai-state (cadr r)))
  282.       (cond
  283.         ((eq? x 'hit) (display ">>> AI: Hit!\n"))
  284.         ((eq? x 'stand) (display ">>> AI: Stand!\n"))
  285.       )
  286.       (cond
  287.         ((eq? x 'hit) (run-game (list (cdr pack) (list hand1 (cons (car pack) hand2)) new-ai-state round) 1))
  288.         ((eq? x 'stand) (run-game (list pack (list hand1 hand2) new-ai-state round) 2))
  289.         (else (display "AI tries to cheat with an invalid move!\n"))
  290.       )
  291.     )
  292.   )
  293. )
  294.  
  295. ; do a move for the player
  296. (define move-player
  297.   (lambda (state)
  298.     (let* ((pack (car state))
  299.            (hands (cadr state))
  300.            (hand1 (car hands))
  301.            (hand2 (cadr hands))
  302.            (ai-state (caddr state))
  303.            (round (cadddr state))
  304.            (x (read-move)))
  305.       (cond
  306.         ((eq? x 'hit) (display ">>> Player: Hit!\n"))
  307.         ((eq? x 'stand) (display ">>> Player: Stand!\n"))
  308.       )
  309.       (cond
  310.         ((eq? x 'hit) (run-game (list (cdr pack) (list (cons (car pack) hand1) hand2) ai-state round) 2))
  311.         ((eq? x 'stand) (run-game state 3))
  312.         ((eq? x 'surrender) (display "Game over\n"))
  313.       )
  314.     )
  315.   )
  316. )
  317.  
  318. ; show hands
  319. (define show-hands
  320.   (lambda (hands)
  321.     (display "### Player's hand: ")
  322.     (show-hand (car hands))
  323.     (display "### AI's hand: ")
  324.     (show-hand (cadr hands))
  325.   )
  326. )
  327.  
  328. ; show a hand
  329. (define show-hand
  330.   (lambda (hand)
  331.     (map
  332.       (lambda (h)
  333.         (display (car h))
  334.         (display (cadr h))
  335.         (display " ")
  336.       )
  337.       hand
  338.     )
  339.     (display "=> ")
  340.     (display (sum-hand hand))
  341.     (newline)
  342.   )
  343. )
  344.  
  345. ; sum hand
  346. (define sum-hand
  347.   (lambda (hand)
  348.     (let* ((l (sort (map car hand) <))
  349.            (s (apply + l)))
  350.       (if (and (< s 13) (not (null? l)) (= (car l) 1))
  351.         (let* ((l (cdr l))
  352.                (s (+ s 9))) ; count first ace as 10 points
  353.           (if (and (< s 13) (not (null? l)) (= (car l) 1))
  354.             (+ s 9) ; count second ace as 10 points too
  355.             s ; only one ace, or more aces but treating all except the first as 1 point
  356.           )
  357.         )
  358.         s ; no ace, or ace but treating it as 1 point
  359.       )
  360.     )
  361.   )
  362. )
  363.  
  364. ; wait for a move from the player (either 'hit or 'stand)
  365. (define read-move
  366.   (lambda ()
  367.     (display "Enter player's move (hit, stand, exit): ")
  368.     (let ((x (read)))
  369.       (cond
  370.         ((or (eq? x 'hit) (eq? x 'stand)) x)
  371.         ((eq? x 'exit) 'exit)
  372.         (else (begin  (display "Invalid move!\n") (read-move)))
  373.       )
  374.     )
  375.   )
  376. )
  377.  
  378. ; generate a pack of cards for Blackjack
  379. ; suit encoding: Spades, Hearts, Diamonds, Clubs
  380. (define generate-pack
  381.   (lambda ()
  382.     (let add-cards ((n 11)
  383.                    (suits '())
  384.                    (pack '()))
  385.       (if (<= n 0)
  386.         pack
  387.         (if (null? suits)
  388.           (add-cards (- n 1) '(S H D C) pack)
  389.           (add-cards n (cdr suits) (cons (list n (car suits)) pack))
  390.         )
  391.       )
  392.     )
  393.   )
  394. )
  395.  
  396. ; do a special cut on the pack at the specified index
  397. (define cut-pack
  398.   (lambda (pack n)
  399.     (let do-cut-pack ((pack pack)
  400.                       (rest '())
  401.                       (n n))
  402.       (if (<= n 0)
  403.         (append pack rest)
  404.         (do-cut-pack (cdr pack) (cons (car pack) rest) (- n 1))
  405.       )
  406.     )
  407.   )
  408. )
  409.  
  410. ; shuffle the pack
  411. (define random-shuffle
  412.   (lambda (pack)
  413.     (let do-random-shuffle ((pack pack)
  414.                             (n 1000))
  415.       (if (<= n 0)
  416.         pack
  417.         (do-random-shuffle (cut-pack pack (random (length pack))) (- n 1))
  418.       )
  419.     )
  420.   )
  421. )
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement