@@ -60,7 +60,7 @@ def display(self, canvas, x, y, width, height):
60
60
"""Display an image of this Object on the canvas."""
61
61
pass
62
62
63
- class Agent (object ):
63
+ class Agent (Object ):
64
64
"""An Agent is a subclass of Object with one required slot,
65
65
.program, which should hold a function that takes one argument, the
66
66
percept, and returns an action. (What counts as a percept or action
@@ -214,11 +214,11 @@ def object_classes(self):
214
214
return [] ## List of classes that can go into environment
215
215
216
216
def percept (self , agent ):
217
- "Return the percept that the agent sees at this point. Override this."
217
+ "Return the percept that the agent sees at this point. (Implement this.) "
218
218
abstract
219
219
220
220
def execute_action (self , agent , action ):
221
- "Change the world to reflect this action. Override this."
221
+ "Change the world to reflect this action. (Implement this.) "
222
222
abstract
223
223
224
224
def default_location (self , object ):
@@ -260,23 +260,17 @@ def list_objects_at(self, location, oclass=Object):
260
260
261
261
def some_objects_at (self , location , oclass = Object ):
262
262
"""Return true if at least one of the objects at location
263
- is an instance of class oclass.
264
-
265
- 'Is an instance' in the sense of 'isinstance',
266
- which is true if the object is an instance of a subclass of oclass."""
267
-
263
+ is an instance of class oclass (or a subclass)."""
268
264
return self .list_objects_at (location , oclass ) != []
269
265
270
266
def add_object (self , obj , location = None ):
271
267
"""Add an object to the environment, setting its location. Also keep
272
268
track of objects that are agents. Shouldn't need to override this."""
273
-
274
269
obj .location = location or self .default_location (obj )
275
270
self .objects .append (obj )
276
271
if isinstance (obj , Agent ):
277
272
obj .performance = 0
278
273
self .agents .append (obj )
279
- return self
280
274
281
275
def delete_object (self , obj ):
282
276
"""Remove an object from the environment."""
@@ -286,15 +280,11 @@ def delete_object(self, obj):
286
280
print e
287
281
print " in Environment delete_object"
288
282
print " Object to be removed: %s at %s" % (obj , obj .location )
289
- trace_list (" from list" , self .objects )
283
+ print " from list: %s" % [(obj , obj .location )
284
+ for obj in self .objects ]
290
285
if obj in self .agents :
291
286
self .agents .remove (obj )
292
287
293
-
294
- def trace_list (name , objlist ):
295
- ol_list = [(obj , obj .location ) for obj in objlist ]
296
- print "%s: %s" % (name , ol_list )
297
-
298
288
class XYEnvironment (Environment ):
299
289
"""This class is for environments on a 2D plane, with locations
300
290
labelled by (x, y) points, either discrete or continuous.
@@ -306,22 +296,21 @@ class XYEnvironment(Environment):
306
296
307
297
def __init__ (self , width = 10 , height = 10 ):
308
298
super (XYEnvironment , self ).__init__ ()
309
- self .width = width
310
- self .height = height
311
- #update(self, objects=[], agents=[], width=width, height=height)
312
- self .observers = []
299
+ update (self , width = width , height = height , observers = [])
313
300
314
- def objects_near (self , location , radius ):
301
+ def objects_near (self , location , radius = None ):
315
302
"Return all objects within radius of location."
303
+ if radius is None : radius = self .perceptible_distance
316
304
radius2 = radius * radius
317
305
return [obj for obj in self .objects
318
306
if distance2 (location , obj .location ) <= radius2 ]
319
307
308
+ perceptible_distance = 1
309
+
320
310
def percept (self , agent ):
321
- "By default, agent perceives objects within radius r."
322
- ### Error below: objects_near requires also a radius argument
311
+ "By default, agent perceives objects within a default radius."
323
312
return [self .object_percept (obj , agent )
324
- for obj in self .objects_near (agent )] ### <- error
313
+ for obj in self .objects_near (agent . location )]
325
314
326
315
def execute_action (self , agent , action ):
327
316
agent .bump = False
@@ -349,12 +338,8 @@ def default_location(self, object):
349
338
350
339
def move_to (self , obj , destination ):
351
340
"Move an object to a new location."
352
-
353
- # Bumped?
354
341
obj .bump = self .some_objects_at (destination , Obstacle )
355
-
356
342
if not obj .bump :
357
- # Move object and report to observers
358
343
obj .location = destination
359
344
for o in self .observers :
360
345
o .object_moved (obj )
@@ -363,8 +348,6 @@ def add_object(self, obj, location=(1, 1)):
363
348
super (XYEnvironment , self ).add_object (obj , location )
364
349
obj .holding = []
365
350
obj .held = None
366
- # self.objects.append(obj) # done in Environment!
367
- # Report to observers
368
351
for obs in self .observers :
369
352
obs .object_added (obj )
370
353
@@ -392,11 +375,11 @@ def add_observer(self, observer):
392
375
and object_added(obj, loc)."""
393
376
self .observers .append (observer )
394
377
395
- def turn_heading (self , heading , inc , headings = orientations ):
396
- "Return the heading to the left (inc=+1) or right (inc=-1) in headings ."
397
- return headings [( headings . index ( heading ) + inc ) % len ( headings )]
378
+ def turn_heading (self , heading , inc ):
379
+ "Return the heading to the left (inc=+1) or right (inc=-1) of heading ."
380
+ return turn_heading ( heading , inc )
398
381
399
- class Obstacle (object ):
382
+ class Obstacle (Object ):
400
383
"""Something that can cause a bump, preventing an agent from
401
384
moving into the same square it's in."""
402
385
pass
@@ -407,7 +390,7 @@ class Wall(Obstacle):
407
390
#______________________________________________________________________________
408
391
## Vacuum environment
409
392
410
- class Dirt (object ):
393
+ class Dirt (Object ):
411
394
pass
412
395
413
396
class VacuumEnvironment (XYEnvironment ):
@@ -446,16 +429,15 @@ def execute_action(self, agent, action):
446
429
agent .performance -= 1
447
430
448
431
class TrivialVacuumEnvironment (Environment ):
449
-
450
432
"""This environment has two locations, A and B. Each can be Dirty
451
433
or Clean. The agent perceives its location and the location's
452
434
status. This serves as an example of how to implement a simple
453
435
Environment."""
454
436
455
437
def __init__ (self ):
456
438
super (TrivialVacuumEnvironment , self ).__init__ ()
457
- self .status = {loc_A :random .choice (['Clean' , 'Dirty' ]),
458
- loc_B :random .choice (['Clean' , 'Dirty' ])}
439
+ self .status = {loc_A : random .choice (['Clean' , 'Dirty' ]),
440
+ loc_B : random .choice (['Clean' , 'Dirty' ])}
459
441
460
442
def object_classes (self ):
461
443
return [Wall , Dirt , ReflexVacuumAgent , RandomVacuumAgent ,
@@ -532,9 +514,9 @@ def rule_match(state, rules):
532
514
#______________________________________________________________________________
533
515
## The Wumpus World
534
516
535
- class Gold (object ): pass
536
- class Pit (object ): pass
537
- class Arrow (object ): pass
517
+ class Gold (Object ): pass
518
+ class Pit (Object ): pass
519
+ class Arrow (Object ): pass
538
520
class Wumpus (Agent ): pass
539
521
class Explorer (Agent ): pass
540
522
@@ -573,31 +555,34 @@ def test_agent(AgentFactory, steps, envs):
573
555
574
556
#_________________________________________________________________________
575
557
576
- _docex = """
577
- a = ReflexVacuumAgent()
578
- a.program
579
- a.program((loc_A, 'Clean')) ==> 'Right'
580
- a.program((loc_B, 'Clean')) ==> 'Left'
581
- a.program((loc_A, 'Dirty')) ==> 'Suck'
582
- a.program((loc_A, 'Dirty')) ==> 'Suck'
583
-
584
- e = TrivialVacuumEnvironment()
585
- e.add_object(TraceAgent(ModelBasedVacuumAgent()))
586
- e.run(5)
558
+ __doc__ += """
559
+ >>> a = ReflexVacuumAgent()
560
+ >>> a.program((loc_A, 'Clean'))
561
+ 'Right'
562
+ >>> a.program((loc_B, 'Clean'))
563
+ 'Left'
564
+ >>> a.program((loc_A, 'Dirty'))
565
+ 'Suck'
566
+ >>> a.program((loc_A, 'Dirty'))
567
+ 'Suck'
568
+
569
+ >>> e = TrivialVacuumEnvironment()
570
+ >>> e.add_object(ModelBasedVacuumAgent()); None
571
+ >>> e.run(5)
587
572
588
573
## Environments, and some agents, are randomized, so the best we can
589
574
## give is a range of expected scores. If this test fails, it does
590
575
## not necessarily mean something is wrong.
591
- envs = [TrivialVacuumEnvironment() for i in range(100)]
592
- def testv(A): return test_agent(A, 4, copy.deepcopy(envs))
593
- testv(ModelBasedVacuumAgent)
594
- (7 < _ < 11) ==> True
595
- testv(ReflexVacuumAgent)
596
- (5 < _ < 9) ==> True
597
- testv(TableDrivenVacuumAgent)
598
- (2 < _ < 6) ==> True
599
- testv(RandomVacuumAgent)
600
- (0.5 < _ < 3) ==> True
576
+ >>> envs = [TrivialVacuumEnvironment() for i in range(100)]
577
+ >>> def testv(A): return test_agent(A, 4, copy.deepcopy(envs))
578
+ >>> 7 < testv(ModelBasedVacuumAgent) < 11
579
+ True
580
+ >>> 5 < testv(ReflexVacuumAgent) < 9
581
+ True
582
+ >>> 2 < testv(TableDrivenVacuumAgent) < 6
583
+ True
584
+ >>> 0.5 < testv(RandomVacuumAgent) < 3
585
+ True
601
586
"""
602
587
603
588
#______________________________________________________________________________
0 commit comments