;;;
;;; 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)))))
)))))))