Skip to content

Commit 669743f

Browse files
committed
Moving project to github
1 parent 7e14166 commit 669743f

File tree

114 files changed

+17053
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

114 files changed

+17053
-0
lines changed

agents/README.html

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<HTML>
2+
<HEAD>
3+
<TITLE>Agents (Subsystem of AIMA Code)</TITLE>
4+
<!-- Changed by: Peter Norvig, 30-Oct-1996 -->
5+
</HEAD>
6+
<BODY bgcolor="#ffffff">
7+
8+
<H1>Agents (Subsystem of AIMA Code)</H1>
9+
10+
The <b>agents</b> subsystem covers the code in Part I of the book: the
11+
basic environment simulator <tt>run-environment</tt>; simulations for
12+
the vacuum and wumpus worlds, and some simple agents for those worlds.
13+
It also includes the abstract class <tt>grid-environment</tt>, which
14+
is an environment that supports physical objects located in a
15+
two-dimensional rectangular grid of spaces. It serves as the basis
16+
for the vacuum and wumpus worlds, as well as for more complex
17+
environments like the shopping world of Chapter 8.
18+
19+
<LISP>
20+
21+
</BODY>
22+
</HTML>

agents/agents/agent.lisp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
;;; -*- Mode: Lisp; Syntax: Common-Lisp; -*- Author: Peter Norvig
2+
3+
;;;; Definition of basic AGENT functions
4+
5+
(defstructure (ask-user-agent (:include agent (program 'ask-user)))
6+
"An agent that asks the user to type in an action.")
7+
8+
(defun ask-user (percept)
9+
"Ask the user what action to take."
10+
(format t "~&Percept is ~A; action? " percept)
11+
(read))
12+
13+
(defmethod print-structure ((agent agent) stream)
14+
"Agents are printed by showing their name (or body) and score."
15+
(format stream "[~A = ~D]" (or (agent-name agent) (agent-body agent))
16+
(agent-score agent)))
17+
18+
(defun initialize-agent-names (env)
19+
"Name the agents 1, 2, ... if they don't yet have a name."
20+
(for each agent in (environment-agents env) do
21+
(when (null (agent-name agent))
22+
(let ((i (+ 1 (position agent (environment-agents env))))
23+
(body (agent-body agent)))
24+
(setf (agent-name agent) i)
25+
(when (and body (null (object-name body)))
26+
(setf (object-name body) i))))))
27+
28+
;; Design Decision Notes
29+
30+
;; We have decided that the agent and its body are two separate objects.
31+
;; We could have combined the agent and its body into one object. But then
32+
;; each new type of agent would need to inherit from both AGENT and some
33+
;; body type, such as OBJECT. This would require multiple inheritance,
34+
;; which is part of CLOS, but is not in our simple implementation for those
35+
;; who don't have CLOS. In any case, it would get messy. We think that
36+
;; separating agents from agent-bodies is a good thing for this
37+
;; implementation. (Just don't take it too far and assume that this says
38+
;; anything about the mind-body problem.)
39+
;;
40+
;; We could have defined the agent program as a generic function on the
41+
;; agent. But that would mean that everytime you want to try out a
42+
;; slightly different agent program, you would need to define a new type. You
43+
;; would also need to hold state information in slots rather than in local
44+
;; variables, and we would need to have some kind of discipline to ensure
45+
;; that the slots representing intermediate state could be accessed and
46+
;; modified by the agent program, while the slot representing, say, the score
47+
;; could not. All in all, a closure (a different one for every agent) is
48+
;; exactly what we want in an agent program: a closure encapsulates local
49+
;; state and behavior, and can access only its arguments and closed-over
50+
;; variables.
51+

agents/agents/vacuum.lisp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
;;; -*- Mode: Lisp; Syntax: Common-Lisp; -*- Author: Peter Norvig
2+
3+
;;;; Some simple agents for the vacuum world
4+
5+
(defstructure (random-vacuum-agent
6+
(:include agent
7+
(program
8+
#'(lambda (percept)
9+
(declare (ignore percept))
10+
(random-element
11+
'(suck forward (turn right) (turn left) shut-off))))))
12+
"A very stupid agent: ignore percept and choose a random action.")
13+
14+
(defstructure (reactive-vacuum-agent
15+
(:include agent
16+
(program
17+
#'(lambda (percept)
18+
(destructuring-bind (bump dirt home) percept
19+
(cond (dirt 'suck)
20+
(home (random-element '(shut-off forward (turn right))))
21+
(bump (random-element '((turn right) (turn left))))
22+
(t (random-element '(forward forward forward
23+
(turn right) (turn left))))))))))
24+
"When you bump, turn randomly; otherwise mostly go forward, but
25+
occasionally turn. Always suck when there is dirt.")
26+
27+

agents/agents/wumpus.lisp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
;;; -*- Mode: Lisp; Syntax: Common-Lisp; -*- Author: Peter Norvig
2+
3+
;;;; Agents for the wumpus world
4+
5+
(defstructure (wumpus-agent (:include agent (body (make-wumpus-agent-body))))
6+
"The default wumpus agent gets an arrow.")
7+
8+
(defstructure (random-wumpus-agent
9+
(:include wumpus-agent
10+
(program
11+
#'(lambda (percept)
12+
(declare (ignore percept))
13+
(random-element '(forward (turn right) (turn left) shoot grab
14+
release climb)))))))
15+
16+
(defstruct (aimless-wumpus-agent
17+
(:include wumpus-agent
18+
(program
19+
(let ((plan nil)
20+
(wumpus-alive? t))
21+
#'(lambda (percept)
22+
(destructuring-bind (stench breeze glitter bump sound) percept
23+
(when sound
24+
(setf wumpus-alive? nil))
25+
(cond (glitter 'grab)
26+
(bump (setf plan '((turn right) (turn right) forward))
27+
(pop plan))
28+
(plan (pop plan))
29+
((or breeze (and wumpus-alive? stench))
30+
(setf plan (list (random-element '((turn left) (turn right)))
31+
'forward))
32+
(pop plan))
33+
(t (random-element '(forward forward (turn right)
34+
(turn left)))))))))))
35+
"This agent does the obvious reactive things: grab when there's a glitter,
36+
and turn and move when there's a bump. If the wumpus is alive and
37+
there's a stench, it turns and moves. Otherwise it wanders aimlessly.")

agents/algorithms/grid.lisp

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
;;; -*- Mode: Lisp; Syntax: Common-Lisp; -*- Author: Peter Norvig
2+
3+
;;;; Algorithms for manipulating objects in a grid
4+
5+
(defun grid-contents (env loc)
6+
"Return a list of objects in this location, optionally including
7+
objects that are contained within containers here."
8+
(aref (grid-environment-grid env) (xy-x loc) (xy-y loc)))
9+
10+
(defsetf grid-contents (env loc) (val)
11+
`(setf (aref (grid-environment-grid ,env) (xy-x ,loc) (xy-y ,loc))
12+
,val))
13+
14+
(defun move-object-to (object loc env)
15+
"Move an object to an absolute location and return that location. However,
16+
attempting to move into a location with an obstacle fails (returns nil)
17+
and the object receives a bump."
18+
(cond ((find-object-if #'obstacle-p loc env)
19+
(setf (object-bump object) 'bump)
20+
nil)
21+
(t (remove-object object env)
22+
(place-object object loc env)
23+
loc)))
24+
25+
(defun place-object (object loc env &optional (initial? t))
26+
"Put the object in its initial position or a new position in environment."
27+
;; Coerce agents into agent-bodies
28+
(when (agent-p object)
29+
(pushnew object (environment-agents env))
30+
(setf object (agent-body object)))
31+
;; Place the object
32+
(setf (object-loc object) loc)
33+
(pushnew object (grid-contents env loc))
34+
(when initial?
35+
(push object (grid-environment-objects env)))
36+
object)
37+
38+
(defun place-in-container (object container env)
39+
"Put the object inside the container, if there is room."
40+
;; First, check to see if there is space
41+
(when (< (+ (object-size object)
42+
(sum (object-contents container) #'object-size))
43+
(object-max-contents object))
44+
;; If there is, remove it from where it was.
45+
(remove-object object env)
46+
;; Now place it in its new container
47+
(setf (object-container object) container)
48+
(setf (object-loc object) (object-loc container))
49+
(pushnew object (object-contents container))
50+
object))
51+
52+
(defun remove-object (object env)
53+
"Remove the object from its current location."
54+
(let ((loc (object-loc object))
55+
(old-container (object-container object)))
56+
(deletef object (grid-contents env loc))
57+
(when old-container
58+
(deletef object (object-contents old-container))
59+
(setf (object-container object) nil))))
60+
61+
(defun find-object-if (predicate loc env)
62+
"Return an object in this location that satisfies this predicate."
63+
(find-if predicate (grid-contents env loc)))
64+
65+
(defun find-neighbor-if (predicate loc env)
66+
"Return an object in a neighboring square that satisfies the predicate."
67+
(let ((x (xy-x loc))
68+
(y (xy-y loc)))
69+
;; Look in the four neighboring squares
70+
(or (find-object-if predicate (@ x (+ y 1)) env)
71+
(find-object-if predicate (@ x (- y 1)) env)
72+
(find-object-if predicate (@ (+ x 1) y) env)
73+
(find-object-if predicate (@ (- x 1) y) env))))
74+
75+
(defun find-object-or-neighbor-if (predicate loc env)
76+
"Return an object either in loc or a neighboring square that satisfies
77+
the predicate."
78+
(or (find-object-if predicate loc env)
79+
(find-neighbor-if predicate loc env)))
80+
81+
(defun near? (loc1 loc2 &optional (tolerance 1))
82+
"Are the two locations nearby each other?"
83+
(and (<= (abs (- (xy-x loc1) (xy-x loc2))) tolerance)
84+
(<= (abs (- (xy-y loc1) (xy-y loc2))) tolerance)))
85+
86+
;;;; Maintaining and manipulating orientation
87+
88+
(defun add-locs (&rest locations)
89+
"Coordinate-wise addition of locations: (add-locs '(1 2) '(10 20)) = (11 22)"
90+
(apply #'mapcar #'+ locations))
91+
92+
(defun subtract-locs (&rest locations)
93+
"Coordinate-wise subtraction of locations."
94+
(apply #'mapcar #'- locations))
95+
96+
(defun heading->string (heading)
97+
"Convert a heading like (0 1) to a depictive string like ^."
98+
(cond ((equal heading '(1 0)) ">")
99+
((equal heading '(0 1)) "^")
100+
((equal heading '(-1 0)) "<")
101+
((equal heading '(0 -1)) "V")
102+
(t "?")))
103+
104+
(defun absolute-loc (agent-body offset)
105+
"Return an absolute location given an offset from an agent, taking the
106+
agent's orientation into account. An offset of (1 2) means 1 square to
107+
the right and two ahead of the agent, given its present orientation."
108+
(let ((x (xy-x offset))
109+
(y (xy-y offset))
110+
(heading (agent-body-heading agent-body)))
111+
(add-locs (object-loc agent-body)
112+
(cond ((equal heading '(1 0)) (@ y (- x)))
113+
((equal heading '(0 1)) offset)
114+
((equal heading '(-1 0)) (@ (- y) x))
115+
((equal heading '(0 -1)) (@ (- x) (- y)))
116+
(t "?")))))
117+
118+
(defun offset-loc (agent-body loc)
119+
"Return an offset from an agent that corresponds to the absolute loc."
120+
(let ((x (- (xy-x loc) (xy-x (object-loc agent-body))))
121+
(y (- (xy-y loc) (xy-y (object-loc agent-body))))
122+
(heading (agent-body-heading agent-body)))
123+
(cond ((equal heading '(1 0)) (@ (- y) (+ x)))
124+
((equal heading '(0 1)) (@ x y))
125+
((equal heading '(-1 0)) (@ (+ y) (- x)))
126+
((equal heading '(0 -1)) (@ (- x) (- y)))
127+
(t "?"))))

0 commit comments

Comments
 (0)