aboutsummaryrefslogtreecommitdiff
(in-package "ACL2")

(include-book "standard-52-card-deck/top")

(defun sum (x)
  (declare (xargs :guard (nat-listp x)))
  (cond ((endp x) 0)
        (t (+ (car x) (sum (cdr x))))))

(defun rank-natp-filter (x)
  (declare (xargs :guard (true-listp x)))
  (cond ((endp x) nil)
        ((natp (car x))
         (cons (car x) (rank-natp-filter (cdr x))))
        (t (rank-natp-filter (cdr x)))))

(defun rank-facep-filter (x)
  (declare (xargs :guard (true-listp x)))
  (cond ((endp x) nil)
        ((rank-facep (car x))
         (cons (car x) (rank-facep-filter (cdr x))))
        (t (rank-facep-filter (cdr x)))))

(defmacro rank-face-list-to-score (x)
  `(* 10 (len ,x)))

(defmacro score-without-aces (x)
  `(+ (sum (rank-natp-filter ,x))
      (rank-face-list-to-score (rank-facep-filter ,x))))

(defthm natp-score-without-aces
  (let ((s (score-without-aces x)))
    (and (integerp s)
         (<= 0 s))))

(defun ace-count (x)
  (declare (xargs :guard (rank-listp x)))
  (cond ((endp x) 0)
        ((rank-acep (car x)) (+ 1 (ace-count (cdr x))))
        (t (ace-count (cdr x)))))

(defthm natp-ace-count
  (and (integerp (ace-count x))
       (<= 0 (ace-count x))))

(defmacro add-ace-scores (s ac)
  `(cond
     ((equal ,ac 0) ,s)
     ((< (+ ,s 10) 21) (+ ,s 11 (- ,ac 1)))
     (t (+ ,s 1 (- ,ac 1)))))

(defthm natp-add-ace-scores
  (implies (and (integerp x)
                (<= 0 x)
                (integerp y)
                (<= 0 y))
           (let ((s (add-ace-scores x y)))
             (and (integerp s)
                  (<= 0 s)))))

(defmacro nat-score (x)
  `(add-ace-scores (score-without-aces ,x)
                   (ace-count ,x)))

(defthm natp-nat-score
  (implies (rank-listp x)
           (and (integerp (nat-score x))
                (<= 0 (nat-score x))))
  :rule-classes (:rewrite :forward-chaining))

(defmacro score (x)
  `(cond
     ((and (< 21 (nat-score ,x))) 'BUST)
     ((and (equal (len ,x) 2) (equal (nat-score ,x) 21))
      'NATURAL-BLACKJACK)
     (t (nat-score ,x))))

(defmacro scorep (x)
  `(or (equal ,x 'bust)
       (equal ,x 'natural-blackjack)
       (if (integerp ,x)
           (if (< ,x 0)
               nil
               (< ,x 22))
           nil)))

(defthm natp-sum
  (implies (nat-listp x)
           (and (integerp (sum x))
                (<= 0 (sum x))))
  :rule-classes (:rewrite :forward-chaining))

(defthm nat-listp-rank-natp-filter
  (implies (rank-listp x)
           (rank-nat-listp (rank-natp-filter x)))
  :rule-classes (:rewrite :forward-chaining))

(defthm scorep-score
  (implies (rank-listp x)
           (scorep (score x))))

(defmacro score-judge (player dealer)
  `(cond
     ((and (equal ,player 'NATURAL-BLACKJACK)
           (equal ,dealer 'NATURAL-BLACKJACK))
      'PUSH)
     ((equal ,player 'NATURAL-BLACKJACK) 'WIN)
     ((equal ,dealer 'NATURAL-BLACKJACK) 'LOSE)
     ((equal ,player 'BUST) 'LOSE)
     ((equal ,dealer 'BUST) 'WIN)
     ((< ,player ,dealer) 'LOSE)
     ((> ,player ,dealer) 'WIN)
     (t 'PUSH)))

(defmacro judge (player dealer)
  `(score-judge (score (card-list-to-rank-list ,player))
                (score (card-list-to-rank-list ,dealer))))

(defmacro judgementp (x)
  `(or (equal ,x 'NATURAL-BLACKJACK)
       (equal ,x 'BUST)
       (equal ,x 'LOSE)
       (equal ,x 'WIN)
       (equal ,x 'PUSH)))

(defthm judgementp-score-judge
  (judgementp (score-judge p d)))

(defthm if-bust-then-lose
  (equal (score-judge 'BUST x) 'LOSE))

(defthm if-draw-a-face-card-and-have-a-ace-card-only-then-natural-blackjack
  (implies (and (rank-facep face)
                (rank-acep ace))
           (equal (score (list ace face))
                  'NATURAL-BLACKJACK)))

(defun no-rank-acep (x)
  (declare (xargs :guard (true-listp x)))
  (if (endp x)
      t
      (and (not (rank-acep (car x)))
           (no-rank-acep (cdr x)))))

(defthm if-draw-a-face-when-12-then-bust
  (implies (and (rank-listp rs)
                (no-rank-acep rs)
                (rank-facep face)
                (equal (nat-score rs) 12))
           (equal (score (cons face rs)) 'BUST)))

(defthm safe-to-hit
  (implies (and (rank-listp rs)
                (rankp new)
                (<= (nat-score rs) 11))
           (not (equal (score (cons new rs)) 'BUST))))