Skip to content

Commit 81c0c27

Browse files
committed
Add docstrings to undocumented public API (agents, search, csp, games) (#666)
Document previously-undocumented module-level functions, classes and public methods in agents.py, agents4e.py, search.py, csp.py, games.py and games4e.py (132 docstrings). Descriptions are derived from the code; AIMA figure references are added only where confident. No code or behaviour changed; docs still build with 0 warnings.
1 parent 21b9dcd commit 81c0c27

6 files changed

Lines changed: 201 additions & 0 deletions

File tree

‎agents.py‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@ def __init__(self):
301301
self.agents = []
302302

303303
def thing_classes(self):
304+
"""Return the list of Thing subclasses that may appear in this environment."""
304305
return [] # List of classes that can go into environment
305306

306307
def percept(self, agent):
@@ -504,6 +505,10 @@ def percept(self, agent):
504505
return self.things_near(agent.location)
505506

506507
def execute_action(self, agent, action):
508+
"""Apply a motion or manipulation action for the agent. Supports turning
509+
('TurnRight'/'TurnLeft'), moving one step ('Forward', setting agent.bump on
510+
a collision), grabbing a grabbable thing at the agent's location ('Grab'),
511+
and dropping the last held thing ('Release')."""
507512
agent.bump = False
508513
if action == 'TurnRight':
509514
agent.direction += Direction.R
@@ -524,6 +529,7 @@ def execute_action(self, agent, action):
524529
self.add_thing(dropped, location=agent.location)
525530

526531
def default_location(self, thing):
532+
"""Return a random inbounds location that contains no Obstacle."""
527533
location = self.random_location_inbounds()
528534
while self.some_things_at(location, Obstacle):
529535
# we will find a random location with no obstacles
@@ -613,13 +619,18 @@ class Obstacle(Thing):
613619

614620

615621
class Wall(Obstacle):
622+
"""An impassable Obstacle forming the boundary or interior walls of a grid."""
616623
pass
617624

618625

619626
# ______________________________________________________________________________
620627

621628

622629
class GraphicEnvironment(XYEnvironment):
630+
"""An XYEnvironment that visualises itself in a Jupyter notebook using an
631+
ipythonblocks BlockGrid, colouring each cell according to the class of the
632+
last thing placed there."""
633+
623634
def __init__(self, width=10, height=10, boundary=True, color={}, display=False):
624635
"""Define all the usual XYEnvironment characteristics,
625636
but initialise a BlockGrid for GUI too."""
@@ -674,6 +685,7 @@ def run(self, steps=1000, delay=1):
674685
self.update(delay)
675686

676687
def update(self, delay=1):
688+
"""Pause for delay seconds, then redraw the world in the GUI."""
677689
sleep(delay)
678690
self.reveal()
679691

@@ -689,6 +701,8 @@ def reveal(self):
689701
self.visible = True
690702

691703
def draw_world(self):
704+
"""Repaint the BlockGrid, colouring each occupied cell by the class of the
705+
last thing at that location using the configured color mapping."""
692706
self.grid[:] = (200, 200, 200)
693707
world = self.get_world()
694708
for x in range(0, len(world)):
@@ -714,10 +728,13 @@ def __init__(self, width=10, height=10):
714728
self.height = height
715729

716730
def add_obstacle(self, coordinates):
731+
"""Add a PolygonObstacle defined by the given list of vertex coordinates."""
717732
self.things.append(PolygonObstacle(coordinates))
718733

719734

720735
class PolygonObstacle(Obstacle):
736+
"""An Obstacle in a ContinuousWorld whose shape is a polygon described by a
737+
list of vertex coordinates."""
721738

722739
def __init__(self, coordinates):
723740
"""Coordinates is a list of tuples."""
@@ -730,6 +747,7 @@ def __init__(self, coordinates):
730747

731748

732749
class Dirt(Thing):
750+
"""A piece of dirt that a vacuum agent can clean up."""
733751
pass
734752

735753

@@ -744,6 +762,7 @@ def __init__(self, width=10, height=10):
744762
self.add_walls()
745763

746764
def thing_classes(self):
765+
"""Return the Thing/Agent classes that may populate the vacuum world."""
747766
return [Wall, Dirt, ReflexVacuumAgent, RandomVacuumAgent,
748767
TableDrivenVacuumAgent, ModelBasedVacuumAgent]
749768

@@ -756,6 +775,9 @@ def percept(self, agent):
756775
return status, bump
757776

758777
def execute_action(self, agent, action):
778+
"""Carry out the agent's action. 'Suck' removes dirt at the agent's location
779+
and adds 100 to its performance; movement actions are delegated to the
780+
XYEnvironment, and every action other than 'NoOp' costs 1 performance point."""
759781
agent.bump = False
760782
if action == 'Suck':
761783
dirt_list = self.list_things_at(agent.location, Dirt)
@@ -782,6 +804,7 @@ def __init__(self):
782804
loc_B: random.choice(['Clean', 'Dirty'])}
783805

784806
def thing_classes(self):
807+
"""Return the Thing/Agent classes that may populate this vacuum world."""
785808
return [Wall, Dirt, ReflexVacuumAgent, RandomVacuumAgent, TableDrivenVacuumAgent, ModelBasedVacuumAgent]
786809

787810
def percept(self, agent):
@@ -812,6 +835,7 @@ def default_location(self, thing):
812835

813836

814837
class Gold(Thing):
838+
"""The gold the explorer is trying to grab in the Wumpus World."""
815839

816840
def __eq__(self, rhs):
817841
"""All Gold are equal"""
@@ -821,39 +845,49 @@ def __eq__(self, rhs):
821845

822846

823847
class Bump(Thing):
848+
"""Percept signalling that the explorer walked into a wall."""
824849
pass
825850

826851

827852
class Glitter(Thing):
853+
"""Percept indicating that gold is in the explorer's current room."""
828854
pass
829855

830856

831857
class Pit(Thing):
858+
"""A pit that kills the explorer if entered."""
832859
pass
833860

834861

835862
class Breeze(Thing):
863+
"""Percept felt in rooms adjacent to a Pit."""
836864
pass
837865

838866

839867
class Arrow(Thing):
868+
"""The single arrow the explorer can shoot to try to kill the wumpus."""
840869
pass
841870

842871

843872
class Scream(Thing):
873+
"""Percept heard throughout the world when the wumpus is killed."""
844874
pass
845875

846876

847877
class Wumpus(Agent):
878+
"""The wumpus: a monster that kills the explorer sharing its room."""
848879
screamed = False
849880
pass
850881

851882

852883
class Stench(Thing):
884+
"""Percept smelled in rooms adjacent to the Wumpus."""
853885
pass
854886

855887

856888
class Explorer(Agent):
889+
"""The agent that explores the Wumpus World, seeking gold while avoiding
890+
pits and the wumpus."""
857891
holding = []
858892
has_arrow = True
859893
killed_by = ""
@@ -865,6 +899,10 @@ def can_grab(self, thing):
865899

866900

867901
class WumpusEnvironment(XYEnvironment):
902+
"""A grid implementation of the Wumpus World from Chapter 7: a cave of rooms
903+
surrounded by walls, holding pits, the wumpus and gold, in which an Explorer
904+
agent perceives stench, breeze, glitter, bump and scream."""
905+
868906
pit_probability = 0.2 # Probability to spawn a pit in a location. (From Chapter 7.2)
869907

870908
# Room should be 4x4 grid of rooms. The extra 2 for walls

‎agents4e.py‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,7 @@ def __init__(self):
306306
self.agents = []
307307

308308
def thing_classes(self):
309+
"""Return the list of Thing subclasses that may appear in this environment."""
309310
return [] # List of classes that can go into environment
310311

311312
def percept(self, agent):
@@ -509,6 +510,9 @@ def percept(self, agent):
509510
return self.things_near(agent.location)
510511

511512
def execute_action(self, agent, action):
513+
"""Apply a motion action for the agent. Supports turning
514+
('TurnRight'/'TurnLeft'), moving one step ('Forward', setting agent.bump on
515+
a collision) and dropping the last held thing ('Release')."""
512516
agent.bump = False
513517
if action == 'TurnRight':
514518
agent.direction += Direction.R
@@ -521,6 +525,7 @@ def execute_action(self, agent, action):
521525
agent.holding.pop()
522526

523527
def default_location(self, thing):
528+
"""Return a random inbounds location that contains no Obstacle."""
524529
location = self.random_location_inbounds()
525530
while self.some_things_at(location, Obstacle):
526531
# we will find a random location with no obstacles
@@ -613,13 +618,18 @@ class Obstacle(Thing):
613618

614619

615620
class Wall(Obstacle):
621+
"""An impassable Obstacle forming the boundary or interior walls of a grid."""
616622
pass
617623

618624

619625
# ______________________________________________________________________________
620626

621627

622628
class GraphicEnvironment(XYEnvironment):
629+
"""An XYEnvironment that visualises itself in a Jupyter notebook using an
630+
ipythonblocks BlockGrid, colouring each cell according to the class of the
631+
last thing placed there."""
632+
623633
def __init__(self, width=10, height=10, boundary=True, color={}, display=False):
624634
"""Define all the usual XYEnvironment characteristics,
625635
but initialise a BlockGrid for GUI too."""
@@ -674,6 +684,7 @@ def run(self, steps=1000, delay=1):
674684
self.update(delay)
675685

676686
def update(self, delay=1):
687+
"""Pause for delay seconds, then redraw the world in the GUI."""
677688
sleep(delay)
678689
self.reveal()
679690

@@ -689,6 +700,8 @@ def reveal(self):
689700
self.visible = True
690701

691702
def draw_world(self):
703+
"""Repaint the BlockGrid, colouring each occupied cell by the class of the
704+
last thing at that location using the configured color mapping."""
692705
self.grid[:] = (200, 200, 200)
693706
world = self.get_world()
694707
for x in range(0, len(world)):
@@ -714,10 +727,13 @@ def __init__(self, width=10, height=10):
714727
self.height = height
715728

716729
def add_obstacle(self, coordinates):
730+
"""Add a PolygonObstacle defined by the given list of vertex coordinates."""
717731
self.things.append(PolygonObstacle(coordinates))
718732

719733

720734
class PolygonObstacle(Obstacle):
735+
"""An Obstacle in a ContinuousWorld whose shape is a polygon described by a
736+
list of vertex coordinates."""
721737

722738
def __init__(self, coordinates):
723739
"""Coordinates is a list of tuples."""
@@ -730,6 +746,7 @@ def __init__(self, coordinates):
730746

731747

732748
class Dirt(Thing):
749+
"""A piece of dirt that a vacuum agent can clean up."""
733750
pass
734751

735752

@@ -744,6 +761,7 @@ def __init__(self, width=10, height=10):
744761
self.add_walls()
745762

746763
def thing_classes(self):
764+
"""Return the Thing/Agent classes that may populate the vacuum world."""
747765
return [Wall, Dirt, ReflexVacuumAgent, RandomVacuumAgent,
748766
TableDrivenVacuumAgent, ModelBasedVacuumAgent]
749767

@@ -756,6 +774,9 @@ def percept(self, agent):
756774
return status, bump
757775

758776
def execute_action(self, agent, action):
777+
"""Carry out the agent's action. 'Suck' removes dirt at the agent's location
778+
and adds 100 to its performance; movement actions are delegated to the
779+
XYEnvironment, and every action other than 'NoOp' costs 1 performance point."""
759780
agent.bump = False
760781
if action == 'Suck':
761782
dirt_list = self.list_things_at(agent.location, Dirt)
@@ -782,6 +803,7 @@ def __init__(self):
782803
loc_B: random.choice(['Clean', 'Dirty'])}
783804

784805
def thing_classes(self):
806+
"""Return the Thing/Agent classes that may populate this vacuum world."""
785807
return [Wall, Dirt, ReflexVacuumAgent, RandomVacuumAgent, TableDrivenVacuumAgent, ModelBasedVacuumAgent]
786808

787809
def percept(self, agent):
@@ -812,6 +834,7 @@ def default_location(self, thing):
812834

813835

814836
class Gold(Thing):
837+
"""The gold the explorer is trying to grab in the Wumpus World."""
815838

816839
def __eq__(self, rhs):
817840
"""All Gold are equal"""
@@ -821,39 +844,49 @@ def __eq__(self, rhs):
821844

822845

823846
class Bump(Thing):
847+
"""Percept signalling that the explorer walked into a wall."""
824848
pass
825849

826850

827851
class Glitter(Thing):
852+
"""Percept indicating that gold is in the explorer's current room."""
828853
pass
829854

830855

831856
class Pit(Thing):
857+
"""A pit that kills the explorer if entered."""
832858
pass
833859

834860

835861
class Breeze(Thing):
862+
"""Percept felt in rooms adjacent to a Pit."""
836863
pass
837864

838865

839866
class Arrow(Thing):
867+
"""The single arrow the explorer can shoot to try to kill the wumpus."""
840868
pass
841869

842870

843871
class Scream(Thing):
872+
"""Percept heard throughout the world when the wumpus is killed."""
844873
pass
845874

846875

847876
class Wumpus(Agent):
877+
"""The wumpus: a monster that kills the explorer sharing its room."""
848878
screamed = False
849879
pass
850880

851881

852882
class Stench(Thing):
883+
"""Percept smelled in rooms adjacent to the Wumpus."""
853884
pass
854885

855886

856887
class Explorer(Agent):
888+
"""The agent that explores the Wumpus World, seeking gold while avoiding
889+
pits and the wumpus."""
857890
holding = []
858891
has_arrow = True
859892
killed_by = ""
@@ -865,6 +898,10 @@ def can_grab(self, thing):
865898

866899

867900
class WumpusEnvironment(XYEnvironment):
901+
"""A grid implementation of the Wumpus World from Chapter 7: a cave of rooms
902+
surrounded by walls, holding pits, the wumpus and gold, in which an Explorer
903+
agent perceives stench, breeze, glitter, bump and scream."""
904+
868905
pit_probability = 0.2 # Probability to spawn a pit in a location. (From Chapter 7.2)
869906

870907
# Room should be 4x4 grid of rooms. The extra 2 for walls

0 commit comments

Comments
 (0)