;;; A percept is the sum total of all the agent knows ;;; about the world at a point in time. This can be ;;; task specific---it depends on the sensors, and also ;;; on what the agent needs to do. ;;; ;;; For our purposes we will take a percept to be a list ;;; of all the objects at the truck's current location, ;;; and a list of objects in the truck's cargo bays. ;;; Each field in the data structure will contain one ;;; sense report. (defstruct percept location-contents bay-1-contents bay-2-contents fuel-level) ;;; One of the main things we do with percepts is to ;;; find objects of a particular kind (e.g. GARBAGE, ;;; TRASHCAN) at a location. This function takes a location ;;; as input, which is one of :OUTSIDE, :BAY-1, :BAY-2, and ;;; returns the positions of all objects of that kind at ;;; that location. ;;; Just call the main function and take the first element ;;; returned. KINDS is a list of symbols indicating which ;;; kinds of object to look for. (defun find-object (percept kinds location) (car (find-objects percept kinds location))) (defun find-objects (percept kinds location) (cond ((symbolp kinds) (really-find-objects percept (list kinds) location)) (T (really-find-objects percept kinds location)))) (defun really-find-objects (percept kinds location) (case location ((:OUTSIDE) (find-objects-at kinds (percept-location-contents percept))) ((:BAY-1) (find-objects-at kinds (percept-bay-1-contents percept))) ((:BAY-2) (find-objects-at kinds (percept-bay-2-contents percept))) (OTHERWISE (error "Don't understand location ~a" location)))) ;;; Find all the objects of this kind in this location's percept list (defun find-objects-at (kinds percept-list) (mapcar 'object-position (remove-if-not #'(lambda (object) (member (object-kind object) kinds)) percept-list))) ;;;********************************************************** ;;; Here are some functions that operate on "objects", where ;;; an object is really a list of attribute/value pairs, for ;;; example ;;; ((KIND ROADSIGN) (POSITION 3) (DIRECTION E)) ;;; (defun object-kind (object) (object-feature object 'kind)) (defun object-position (object) (object-feature object 'position)) (defun object-feature (object feature) (second (assoc feature object))) ;;;*************************************************************** ;;; This code finds an empty position at a location. It has to ;;; know the last valid position at that location. Then it searches ;;; through the integers from 1 to last, looking for an object at ;;; that position. It returns the first index without an object, ;;; or NIL if every position is filled. ;;; The last valid position in each location (defvar *positions*) (setf *positions* '((:OUTSIDE 11) (:BAY-1 1) (:BAY-2 1))) (defun pr-max-positions (location) (let ((mm (assoc location *positions*))) (cond ((null mm) (error "Don't know how to find max positions for ~a" location)) (T (second mm))))) (defun find-empty-position (percept location) (case location ((:OUTSIDE) (find-empty-position-at (mapcar #'object-position (percept-location-contents percept)) 0 (pr-max-positions :OUTSIDE))) ((:BAY-1) (find-empty-position-at (mapcar #'object-position (percept-bay-1-contents percept)) 0 (pr-max-positions :BAY-1))) ((:BAY-2) (find-empty-position-at (mapcar #'object-position (percept-bay-2-contents percept)) 0 (pr-max-positions :BAY-2))) (OTHERWISE (error "Cannot find empty position at ~a" location)))) (defun find-empty-position-at (position-list current max) (cond ((> current max) NIL) ((not (member current position-list :test #'=)) current) (T (find-empty-position-at position-list (+ current 1) max)))) (defun find-objects-with-attributes (percept location attribute-list) (let ((object-list (case location ((:OUTSIDE) (percept-location-contents percept)) ((:BAY-1) (percept-bay-1-contents percept)) ((:BAY-2) (percept-bay-2-contents percept)) (OTHERWISE (error "Don't know how to retrieve at location ~a" location))))) (find-objects-with-attributes-in object-list attribute-list))) (defun find-objects-with-attributes-in (object-list attribute-list) (mapcar 'object-position (remove-if-not #'(lambda (obj) (every #'(lambda (att-value-pair) (eql (object-feature obj (first att-value-pair)) (second att-value-pair))) attribute-list)) object-list))) (defun find-object-with-attributes (percept location attribute-list) (first (find-objects-with-attributes percept location attribute-list)))