; Here's my proposed export format from ddp. ; This is just scribbles. Note even sure this runs. Just notation. ; Needs a notation for setting numerics via pre-defined functions. What? (defvar *goal1* '!goal) (defvar *forest1* `((!goal (ror ; do any 1 (picked at random) !happy !healthy !wise) ) (!happy solar) (!wealthy nuclear) (!wise (rand ; do all, in any order !old !at-uni) ) (=old 23 ; the reward from doing "old" $12 ; the cost of doing "old" ))) ; end ; but what does it all mean? well... (defun rand-p (x) "and, in any order" (list-p x 'rand) (defun ror-p (x) "or, in any order" (list-p x 'ror)) (defun and-p (x) "and, in any order" (list-p x 'and) (defun or-p (x) "or, in any order" (list-p x 'or)) (defun constant-p (x) "leaves of the forst: things with three items: (id reward cost)" (charp-p x #\=)) (defun global-p (x) "Memoed recursion. I.e. if we need it 10 times, it only gets called once, then we cache the result." (char-p x #\!)) (defun local-p (x) "Boring old recursion. No memoing." (char-p x #\?)) (defun char-p (x c) "helper function: different things have different first characters" (and (symbolp x) (equal (elt (symbol-name x) 0) c))) (defun list-p (x y) "helper function: different lists have different first symbols" (and (consp x) (equal (car x) y)) ;;;; ; interpreter (defun walk (&optional (forest *forest1*)) "main function start-up call to the worker" (let ((cache (make-hash-table))) (values (walk1 *goal1* forest cache) cache))) (defun jump (goal forest cache) "recursive call to the worker" (walk1 (assoc goal forst) forest cache)) (defun walk1 (goal forest cache) "the worker" (list goal (walk2 goal forest cache))) (defun walk2 (goal forest cache) "the real worker" (cond ((null goal) nil) ((rand-p goal) (random-and goal forest cache)) ((ror-o goal) (random-or goal forest cache)) ((and-p goal) (l2r-and goal forest cache)) ((or-o goal) (l2r-or goal forest cache)) ((constant-p goal) (assoc goal forest)) ((local-p goal) (jump goal forest cache)) ((global-p goal) (or (gethash goal cache) (setf (gethash goal cache) (jump goal forest cache)))) (t goal)))) (defun random-or (list forest cache) "run the list in any order. one success will do. fail if all fail" (stagger list forest cache :enough 1 :patience: (length list) :grab 'rany)) (defun random-and (list forest cache) "run the list in any order. one failure is too much, need all to succeed." (stagger list forst cache :enough (length list) :patience 0 :grab 'rany)) (defun l2r-or (list forest cache) "run the list in l2r order. one success will do. fail if all fail" (stagger list forest cache :enough 1 :patience: (length list) :grab 'l2r)) (defun l2r-and (list forest cache) "run the list in l2r order. one failure is too much, need all to succeed." (stagger list forst cache :enough (length list) :patience 0 :grab 'l2r)) (defun rany (x) "eat a list, in any order" (let ((next (nth (random (length x)) x))) (values next (delete next x))))) (defun l2r (x) "eat a list, left to right" (values (car x) (cdr x))) ; stagger is missing a combination function for ; unifying the result of staggering over things in ; a random order (defun stagger (list forest cache &keys enough patience (wins 0) (losses 0) (grab 'rany)) (if list (multiple-value-bind (one rest) (funcall grab list) (if (walk1 one forest cache) (incf wins) (incf losses)) (cond ((>= losses patience) ; probably a +1 errors here nil) ((>= wins enough) ; probably a +1 errors here t) (t (stagger rest forest cache :enough enough :patience patience :wins wins :losses losses :grab grab ))))))