(defconstant *rounds* '(3 4 5 6 7 8 9 10 11 12 13)) (defconstant *wild-cards* '(3 4 5 6 7 8 9 10 J Q K)) (defconstant *picture-card-values* '((J 11) (Q 12) (K 13) (JOKER 50))) (defvar *players*) (defvar *scores*) (defvar *round-counter*) (defun reset-game () (format t "Please enter list of player names: ") (let ((player-names (read))) (setf *players* player-names)) (let ((zero-score (make-list (length *players*) :initial-element 0))) (setf *scores* (make-list (length *rounds*) :initial-element zero-score))) (setf *round-counter* 0)) (defun current-score (player-name) (let ((playerno (position player-name *players*))) (reduce #'+ (mapcar #'(lambda (score-rec) (elt score-rec playerno)) *scores*)))) (defun current-wild-card () (elt *wild-cards* *round-counter*)) (defun card-value (card) (if (equalp card (current-wild-card)) 20 (if (not (numberp card)) (cadr (assoc card *picture-card-values*)) card))) (defun outcome->score (outcome) (if (listp outcome) (reduce #'+ (mapcar #'card-value outcome)) outcome)) (defun score-this-round (outcome-list) (let ((score-list (mapcar #'outcome->score outcome-list))) (setf (elt *scores* *round-counter*) score-list))) (defun print-current-score-for-player (player-name) (format t "The current score for ~A is ~A~%" player-name (current-score player-name))) (defun print-current-scores () (mapcar #'print-current-score-for-player *players*)) (defun round-descriptor (round-num) (let ((num-cards (elt *rounds* round-num)) (wild-card (elt *wild-cards* round-num))) (if (not (eql num-cards wild-card)) (format nil "~A (~A)" num-cards wild-card) (format nil "~A" num-cards)))) (defun tally-final-scores () ; to-do nil) (defun do-one-round () (if (game-is-over) (error "The game is already over")) (format t "The current round is round ~A~%" (round-descriptor *round-counter*)) (format t "Enter outcomes for this round in order ~A: " *players*) (let ((this-round-outcomes (read))) (score-this-round this-round-outcomes) (print-current-scores) (if (game-is-over) (tally-final-scores)))) (defun winning-player-name () (let ((ranked-players *players*)) (sort ranked-players #'(lambda (p1 p2) (< (current-score p1) (current-score p2)))) (first ranked-players))) (defun game-is-over () (>= *round-counter* (length *rounds*))) (defun run-game () (reset-game) (do ((*round-counter* 0 (1+ *round-counter*))) ((game-is-over)) (do-one-round)) (format t "Game over.~%"))