;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Spider state evaluation ;;; Evaluation function features (defun spider-hidden-cards (state &aux (count 0)) (map nil #'(lambda (stack) (incf count (count-if #'card-hidden? stack))) (spider-state-stacks state)) count) (defun spider-open-spaces (state &aux (count 0)) (map nil #'(lambda (stack) (when (null stack) (incf count))) (spider-state-stacks state)) count) (defun spider-suit-changes (state &aux (count 0)) (map nil #'(lambda (stack) (incf count (stack-suit-changes stack 0))) (spider-state-stacks state)) count) (defun stack-suit-changes (cards n &optional (previous-suit nil) (previous-number nil)) "Return the number of within-sequence suit changes in cards." (cond ((or (null cards) (card-hidden? (first cards))) n) ((or (not (eql (1- (card-number (first cards))) previous-number)) (eql (card-suit (first cards)) previous-suit)) (stack-suit-changes (rest cards) n (card-suit (first cards)) (card-number (first cards)))) (t (stack-suit-changes (rest cards) (1+ n) (card-suit (first cards)) (card-number (first cards)))))) (defun spider-sequence-changes (state &aux (count 0)) (map nil #'(lambda (stack) (incf count (stack-sequence-changes stack 0))) (spider-state-stacks state)) count) (defun stack-sequence-changes (cards n &optional (previous-number nil)) "Return the number of sequence changes in cards." (cond ((or (null cards) (card-hidden? (first cards))) n) ((or (null previous-number) (eql (1- (card-number (first cards))) previous-number)) (stack-sequence-changes (rest cards) n (card-number (first cards)))) (t (stack-sequence-changes (rest cards) (1+ n) (card-number (first cards)))))) (defun spider-pure-stacks (state &aux (count 0)) (map nil #'(lambda (stack) (when (pure-stack? stack) (incf count))) (spider-state-stacks state)) count) (defun pure-stack? (cards &optional (previous-suit nil) (previous-number nil)) "Return t iff stack is a single same-suit sequence (plus hidden cards)." (cond ((or (null cards) (card-hidden? (first cards))) t) ((or (null previous-number) (and (eql (1- (card-number (first cards))) previous-number) (eql (card-suit (first cards)) previous-suit))) (pure-stack? (rest cards) (card-suit (first cards)) (card-number (first cards)))) (t nil))) (defun spider-suits-completed (state) (length (spider-state-completed state))) (defun spider-top-diversity (state &aux (numbers nil)) (map nil #'(lambda (stack) (when (and stack (not (card-hidden? (first stack)))) (pushnew (card-number (first stack)) numbers))) (spider-state-stacks state)) (length numbers)) ;;; Linear evaluation function (defvar *spider-features*) (setq *spider-features* (list #'spider-hidden-cards #'spider-open-spaces #'spider-suit-changes #'spider-sequence-changes #'spider-pure-stacks #'spider-suits-completed #'spider-top-diversity )) (defvar *spider-weights*) (setq *spider-weights* '(-0.5 ; spider-hidden-cards +10.0 ; spider-open-spaces -1.0 ; spider-suit-changes -3.0 ; spider-sequence-changes +2.0 ; spider-pure-stacks +30.0 ; spider-suits-completed +0.5 ; spider-top-diversity )) (defun spider-eval (state) "Return a value for state using a linear combination of features." (linear-eval state *spider-features* *spider-weights*))