;;; ;;; A Reasoning Wumpus Agent Using SNePS ;;; Stuart C. Shapiro ;;; April 4, 1996 ;;; Modified March 19, 1998 to use the SNePS Tell-Ask Interface ;;; Last modified March 30, 1998 ;;; ;;; (load "/projects/snwiz/bin/sneps") (in-package "COMMON-LISP-USER") (load "/projects/shapiro/Sneps/tellask") (import '(snepsul:Tell snepsul:Ask snepsul:Askifnot snepsul:Askwh snepsul:Askwhnot)) (load "/projects/shapiro/AIclass/Aimacode/aima.lisp") (aima-load 'agents) (defun run-my-wumpus (&key (agents (list (SNePS-wumpus-agent 'S))) (max-steps 5) (display t) (env (make-wumpus-world :agents agents))) "Run a Wumpus world until the game is over." (print-environment-map env) (run-eval-environment env :max-steps max-steps :display display)) (defun SNePS-wumpus-agent (name) ;; a modification of the Aima stupid-wumpus-agent ;; by Stuart C. Shapiro (wumpus-agent name (let ((plan nil) ; Use for a plan of moves (wumpus-alive? t) ; T if the wumpus is alive (got-gold? nil) ; T if the agent has the gold (have-arrow? t) ; T if the agent has an arrow (x 1) (y 1) ; The current location of the agent (dx 1) (dy 0) ; Codes the direction the agent is looking ) (setf snip:*infertrace* nil) ; Turn off SNePS inference tracing ;; start with an empty SNePS network (tell "clearkb") ;; A location is safe iff there's no wumpus there and no pit there. (tell "all(x) (Safe(x) <=> (~At(Wumpus, x) and ~At(Pit, x)))") ;; If the Wumpus is dead, it isn't at any location. (tell "Dead(Wumpus) => all(x)(Location(x) => ~At(Wumpus, x))") #'(lambda (percept) (labels ((move (movement) ;; Adjusts x and y for the movement (cond ((eql movement 'forward) (incf x dx) (incf y dy)) ((equal movement '(turn right)) (psetf dx (if (zerop dx) dy 0) dy (if (zerop dy) (- dx) 0))) ((equal movement '(turn left)) (psetf dx (if (zerop dx) (- dy) 0) dy (if (zerop dy) dx 0)))) movement)) (block SNePS-AGENT ;; If bump, back up (when (wumpus-percept-bump percept) (decf x dx) (decf y dy)) ;; If the agent has the gold and is at the cave entrance, climb. (when (and got-gold? (= x y 1)) (return-from SNePS-AGENT 'climb)) ;; The nearby locations are locations. (tell (format nil "Location(position(~a, ~a))!" x y)) (tell (format nil "Location(position(~a, ~a))!" x (1+ y))) (tell (format nil "Location(position(~a, ~a))!" (1+ x) y)) (tell (format nil "Location(position(~a, ~a))!" x (1- y))) (tell (format nil "Location(position(~a, ~a))!" (1- x) y)) ;; The current location is safe (tell (format nil "Safe(position(~a, ~a))!" x y)) ;; If the wumpus screams, it's dead. (when (wumpus-percept-sound percept) (setf wumpus-alive? nil) (format t "~%I killed the wumpus!~%") #!((remove-from-context (findassert min 1 max 1 arg (find a1 wumpus)))) (sneps:clear-infer) (tell "Dead(Wumpus)!")) (when wumpus-alive? ;; If a stench, the wumpus is nearby, ;; but if not, it isn't. (let ((n 0)) (when (wumpus-percept-stench percept) (setf n 1) (format t "~%I smell the wumpus!~%")) (tell (format nil "andor(~a,~a){At(Wumpus,position(~a,~a)),~ At(Wumpus,position(~a,~a)),~ At(Wumpus,position(~a,~a)),~ At(Wumpus,position(~a,~a))}!" n n x (1+ y) (1+ x) y x (1- y) (1- x) y)))) (let ((i 0) (j 0)) ;; If a breeze, one or more pits are nearby, ;; but if not, there aren't (when (wumpus-percept-breeze percept) (setf i 1 j 4) (format t "~%I detect a pit.~%")) (tell (format nil "andor(~a,~a){At(Pit,position(~a,~a)),~ At(Pit,position(~a,~a)),~ At(Pit,position(~a,~a)),~ At(Pit,position(~a,~a))}!" i j x (1+ y) (1+ x) y x (1- y) (1- x) y))) (sneps:clear-infer) ;; Now decide what to do (cond ((wumpus-percept-glitter percept) ;; go for the gold (setf got-gold? t) (format t "~&I've got the gold!") 'grab) ((wumpus-percept-bump percept) ;; left over from stupid-wumpus-agent (setf plan '((turn right) (turn right) forward)) (format t "~&I bumped, so I've got a plan.") (move (pop plan))) (plan ;; left over from stupid-wumpus-agent (format t "~&I'm using my plan.") (move (pop plan))) ((ask (format nil "Safe(position(~a, ~a))" (+ x dx) (+ y dy))) (format t "~&It's safe to go forward.~%") (move 'forward)) ((and wumpus-alive? have-arrow?) ;; Shoot away, just in case. ;; This decision could be improved. (setf have-arrow? nil) 'shoot) (t ;; left over from stupid-wumpus-agent (move (random-element '(forward forward (turn right) (turn left))))) )))))))