Newer
Older
"""Implement Agents and Environments (Chapters 1-2).
The class hierarchies are as follows:
Thing ## A physical object that can exist in an environment
Agent
Wumpus
Dirt
Wall
...
Environment ## An environment holds objects, runs simulations
XYEnvironment
VacuumEnvironment
WumpusEnvironment
An agent program is a callable instance, taking percepts and choosing actions
SimpleReflexAgentProgram
...
EnvGUI ## A window with a graphical representation of the Environment
EnvToolbar ## contains buttons for controlling EnvGUI
EnvCanvas ## Canvas to display the environment of an EnvGUI
"""
# TO DO:
# Implement grabbing correctly.
# When an object is grabbed, does it still have a location?
# What if it is released?
# What if the grabbed or the grabber is deleted?
# What if the grabber moves?
#
# Speed control in GUI does not have any effect -- fix it.
from utils import distance_squared, turn_heading
from statistics import mean
# ______________________________________________________________________________
"""This represents any physical object that can appear in an Environment.
You subclass Thing to get the things you want. Each thing can have a
.__name__ slot (used for output only)."""
def __repr__(self):
return '<{}>'.format(getattr(self, '__name__', self.__class__.__name__))
def is_alive(self):
"""Things that are 'alive' should return true."""
return hasattr(self, 'alive') and self.alive
"""Display the agent's internal state. Subclasses should override."""
print("I don't know how to show_state.")
def display(self, canvas, x, y, width, height):
"""Display an image of this Thing on the canvas."""
# Do we need this?
class Agent(Thing):
"""An Agent is a subclass of Thing with one required slot,
.program, which should hold a function that takes one argument, the
percept, and returns an action. (What counts as a percept or action
will depend on the specific environment in which the agent exists.)
Note that 'program' is a slot, not a method. If it were a method,
then the program could 'cheat' and look at aspects of the agent.
It's not supposed to do that: the program can only look at the
percepts. An agent program that needs a model of the world (and of
the agent itself) will have to build and maintain its own model.
There is an optional slot, .performance, which is a number giving
the performance measure of the agent in its environment."""
def __init__(self, program=None):
self.alive = True
tolusalako
a validé
self.holding = []
self.performance = 0
if program is None or not isinstance(program, collections.Callable):
print("Can't find a valid program for {}, falling back to default.".format(
self.__class__.__name__))
def program(percept):
return eval(input('Percept={}; action? '.format(percept)))
self.program = program
def can_grab(self, thing):
"""Returns True if this agent can grab this thing.
Override for appropriate subclasses of Agent and Thing."""
return False
def TraceAgent(agent):
"""Wrap the agent's program to print its input and output. This will let
you see what the agent is doing in the environment."""
old_program = agent.program
def new_program(percept):
action = old_program(percept)
print('{} perceives {} and does {}'.format(agent, percept, action))
return action
agent.program = new_program
return agent
# ______________________________________________________________________________
def TableDrivenAgentProgram(table):
"""This agent selects an action based on the percept sequence.
It is practical only for tiny domains.
To customize it, provide as table a dictionary of all
{percept_sequence:action} pairs. [Figure 2.7]"""
percepts = []
def program(percept):
percepts.append(percept)
action = table.get(tuple(percepts))
return action
return program
def RandomAgentProgram(actions):
"""An agent that chooses an action at random, ignoring all percepts."""
return lambda percept: random.choice(actions)
# ______________________________________________________________________________
def SimpleReflexAgentProgram(rules, interpret_input):
"""This agent takes action based solely on the percept. [Figure 2.10]"""
def program(percept):
state = interpret_input(percept)
rule = rule_match(state, rules)
action = rule.action
return action
return program
def ModelBasedReflexAgentProgram(rules, update_state, model):
"""This agent takes action based on the percept and state. [Figure 2.12]"""
def program(percept):
program.state = update_state(program.state, program.action, percept, model)
rule = rule_match(program.state, rules)
action = rule.action
return action
program.state = program.action = None
return program
def rule_match(state, rules):
"""Find the first rule that matches state."""
for rule in rules:
if rule.matches(state):
return rule
# ______________________________________________________________________________
loc_A, loc_B = (0, 0), (1, 0) # The two locations for the Vacuum world
def RandomVacuumAgent():
"""Randomly choose one of the actions from the vacuum environment."""
return Agent(RandomAgentProgram(['Right', 'Left', 'Suck', 'NoOp']))
def TableDrivenVacuumAgent():
table = {((loc_A, 'Clean'),): 'Right',
((loc_A, 'Dirty'),): 'Suck',
((loc_B, 'Clean'),): 'Left',
((loc_B, 'Dirty'),): 'Suck',
((loc_A, 'Dirty'), (loc_A, 'Clean')): 'Right',
((loc_A, 'Clean'), (loc_B, 'Dirty')): 'Suck',
((loc_B, 'Clean'), (loc_A, 'Dirty')): 'Suck',
((loc_B, 'Dirty'), (loc_B, 'Clean')): 'Left',
((loc_A, 'Dirty'), (loc_A, 'Clean'), (loc_B, 'Dirty')): 'Suck',
((loc_B, 'Dirty'), (loc_B, 'Clean'), (loc_A, 'Dirty')): 'Suck'
return Agent(TableDrivenAgentProgram(table))
def ReflexVacuumAgent():
"""A reflex agent for the two-state vacuum environment. [Figure 2.8]"""
if status == 'Dirty':
return 'Suck'
elif location == loc_A:
return 'Right'
elif location == loc_B:
return 'Left'
return Agent(program)
def ModelBasedVacuumAgent():
"""An agent that keeps track of what locations are clean or dirty."""
model = {loc_A: None, loc_B: None}
"""Same as ReflexVacuumAgent, except if everything is clean, do NoOp."""
model[location] = status # Update the model here
if model[loc_A] == model[loc_B] == 'Clean':
return 'NoOp'
elif status == 'Dirty':
return 'Suck'
elif location == loc_A:
return 'Right'
elif location == loc_B:
return 'Left'
return Agent(program)
# ______________________________________________________________________________
"""Abstract class representing an Environment. 'Real' Environment classes
inherit from this. Your Environment will typically need to implement:
percept: Define the percept that an agent sees.
execute_action: Define the effects of executing an action.
Also update the agent.performance slot.
The environment keeps a list of .things and .agents (which is a subset
of .things). Each agent has a .performance slot, initialized to 0.
Each thing has a .location slot, even though some environments may not
need this."""
self.things = []
def thing_classes(self):
return [] # List of classes that can go into environment
def percept(self, agent):
"""Return the percept that the agent sees at this point. (Implement this.)"""
def execute_action(self, agent, action):
"""Change the world to reflect this action. (Implement this.)"""
def default_location(self, thing):
"""Default location to place a new thing with unspecified location."""
return None
def exogenous_change(self):
"""If there is spontaneous change in the world, override this."""
def is_done(self):
"""By default, we're done when we can't find a live agent."""
withal
a validé
return not any(agent.is_alive() for agent in self.agents)
def step(self):
"""Run the environment for one time step. If the
actions and exogenous changes are independent, this method will
do. If there are interactions between them, you'll need to
tolusalako
a validé
actions = []
for agent in self.agents:
if agent.alive:
actions.append(agent.program(self.percept(agent)))
else:
actions.append("")
for (agent, action) in zip(self.agents, actions):
self.exogenous_change()
def run(self, steps=1000):
"""Run the Environment for given number of time steps."""
self.step()
def list_things_at(self, location, tclass=Thing):
"""Return all things exactly at a given location."""
return [thing for thing in self.things
if thing.location == location and isinstance(thing, tclass)]
def some_things_at(self, location, tclass=Thing):
"""Return true if at least one of the things at location
is an instance of class tclass (or a subclass)."""
return self.list_things_at(location, tclass) != []
def add_thing(self, thing, location=None):
"""Add a thing to the environment, setting its location. For
convenience, if thing is an agent program we make a new agent
for it. (Shouldn't need to override this.)"""
if not isinstance(thing, Thing):
thing = Agent(thing)
if thing in self.things:
print("Can't add the same thing twice")
else:
thing.location = location if location is not None else self.default_location(thing)
self.things.append(thing)
if isinstance(thing, Agent):
thing.performance = 0
self.agents.append(thing)
def delete_thing(self, thing):
"""Remove a thing from the environment."""
self.things.remove(thing)
print(e)
print(" in Environment delete_thing")
print(" Thing to be removed: {} at {}".format(thing, thing.location))
print(" from list: {}".format([(thing, thing.location) for thing in self.things]))
if thing in self.agents:
self.agents.remove(thing)
"""A direction class for agents that want to move in a 2D plane
Usage:
To change directions:
d = d + "right" or d = d + Direction.R #Both do the same thing
Note that the argument to __add__ must be a string and not a Direction object.
Also, it (the argument) can only be right or left."""
R = "right"
L = "left"
U = "up"
D = "down"
def __init__(self, direction):
self.direction = direction
def __add__(self, heading):
if self.direction == self.R:
return{
self.R: Direction(self.D),
self.L: Direction(self.U),
}.get(heading, None)
elif self.direction == self.L:
return{
tolusalako
a validé
self.R: Direction(self.U),
self.L: Direction(self.D),
}.get(heading, None)
elif self.direction == self.U:
return{
tolusalako
a validé
self.R: Direction(self.R),
self.L: Direction(self.L),
}.get(heading, None)
elif self.direction == self.D:
return{
self.R: Direction(self.L),
self.L: Direction(self.R),
}.get(heading, None)
tolusalako
a validé
def move_forward(self, from_location):
tolusalako
a validé
if self.direction == self.R:
tolusalako
a validé
elif self.direction == self.L:
tolusalako
a validé
elif self.direction == self.U:
tolusalako
a validé
elif self.direction == self.D:
"""This class is for environments on a 2D plane, with locations
labelled by (x, y) points, either discrete or continuous.
Agents perceive things within a radius. Each agent in the
environment has a .location slot which should be a location such
as (0, 1), and a .holding slot, which should be a list of things
that are held."""
def __init__(self, width=10, height=10):
self.width = width
self.height = height
self.observers = []
# Sets iteration start and end (no walls).
self.x_start, self.y_start = (0, 0)
self.x_end, self.y_end = (self.width, self.height)
perceptible_distance = 1
def things_near(self, location, radius=None):
"""Return all things within radius of location."""
if radius is None:
radius = self.perceptible_distance
radius2 = radius * radius
return [(thing, radius2 - distance_squared(location, thing.location))
for thing in self.things if distance_squared(
location, thing.location) <= radius2]
def percept(self, agent):
"""By default, agent perceives things within a default radius."""
tolusalako
a validé
return self.things_near(agent.location)
def execute_action(self, agent, action):
agent.bump = False
if action == 'TurnRight':
elif action == 'TurnLeft':
elif action == 'Forward':
tolusalako
a validé
agent.bump = self.move_to(agent, agent.direction.move_forward(agent.location))
# elif action == 'Grab':
# things = [thing for thing in self.list_things_at(agent.location)
# if agent.can_grab(thing)]
# if things:
# agent.holding.append(things[0])
elif action == 'Release':
if agent.holding:
agent.holding.pop()
def default_location(self, thing):
return (random.choice(self.width), random.choice(self.height))
def move_to(self, thing, destination):
"""Move a thing to a new location. Returns True on success or False if there is an Obstacle.
If thing is holding anything, they move with him."""
thing.bump = self.some_things_at(destination, Obstacle)
if not thing.bump:
thing.location = destination
for o in self.observers:
o.thing_moved(thing)
tolusalako
a validé
for t in thing.holding:
self.delete_thing(t)
self.add_thing(t, destination)
t.location = destination
return thing.bump
def add_thing(self, thing, location=(1, 1), exclude_duplicate_class_items=False):
"""Adds things to the world. If (exclude_duplicate_class_items) then the item won't be
added if the location has at least one item of the same class."""
tolusalako
a validé
if (self.is_inbounds(location)):
if (exclude_duplicate_class_items and
any(isinstance(t, thing.__class__) for t in self.list_things_at(location))):
return
tolusalako
a validé
def is_inbounds(self, location):
"""Checks to make sure that the location is inbounds (within walls if we have walls)"""
tolusalako
a validé
return not (x < self.x_start or x >= self.x_end or y < self.y_start or y >= self.y_end)
def random_location_inbounds(self, exclude=None):
"""Returns a random location that is inbounds (within walls if we have walls)"""
location = (random.randint(self.x_start, self.x_end),
random.randint(self.y_start, self.y_end))
tolusalako
a validé
if exclude is not None:
while(location == exclude):
location = (random.randint(self.x_start, self.x_end),
random.randint(self.y_start, self.y_end))
tolusalako
a validé
return location
def delete_thing(self, thing):
"""Deletes thing, and everything it is holding (if thing is an agent)"""
tolusalako
a validé
if isinstance(thing, Agent):
for obj in thing.holding:
tolusalako
a validé
for obs in self.observers:
obs.thing_deleted(obj)
for obs in self.observers:
obs.thing_deleted(thing)
def add_walls(self):
"""Put walls around the entire perimeter of the grid."""
for x in range(self.width):
self.add_thing(Wall(), (x, 0))
self.add_thing(Wall(), (x, self.height - 1))
for y in range(self.height):
self.add_thing(Wall(), (0, y))
self.add_thing(Wall(), (self.width - 1, y))
# Updates iteration start and end (with walls).
self.x_start, self.y_start = (1, 1)
self.x_end, self.y_end = (self.width - 1, self.height - 1)
An observer is typically an EnvGUI.
Each observer is notified of changes in move_to and add_thing,
by calling the observer's methods thing_moved(thing)
and thing_added(thing, loc)."""
self.observers.append(observer)
def turn_heading(self, heading, inc):
"""Return the heading to the left (inc=+1) or right (inc=-1) of heading."""
return turn_heading(heading, inc)
class Obstacle(Thing):
"""Something that can cause a bump, preventing an agent from
moving into the same square it's in."""
pass
# ______________________________________________________________________________
try:
from ipythonblocks import BlockGrid
from IPython.display import HTML, display
from time import sleep
except:
pass
class GraphicEnvironment(XYEnvironment):
def __init__(self, width=10, height=10, boundary=True, color={}, display=False):
"""Define all the usual XYEnvironment characteristics,
but initialise a BlockGrid for GUI too."""
super().__init__(width, height)
self.grid = BlockGrid(width, height, fill=(200, 200, 200))
if display:
self.grid.show()
self.visible = True
else:
self.visible = False
self.bounded = boundary
self.colors = color
"""Returns all the items in the world in a format
understandable by the ipythonblocks BlockGrid."""
result = []
x_start, y_start = (0, 0)
x_end, y_end = self.width, self.height
for x in range(x_start, x_end):
row = []
for y in range(y_start, y_end):
row.append(self.list_things_at([x, y]))
result.append(row)
return result
"""
def run(self, steps=1000, delay=1):
"" "Run the Environment for given number of time steps,
but update the GUI too." ""
for step in range(steps):
sleep(delay)
if self.visible:
self.reveal()
if self.is_done():
if self.visible:
self.reveal()
return
self.step()
if self.visible:
self.reveal()
"""
def run(self, steps=1000, delay=1):
"""Run the Environment for given number of time steps,
but update the GUI too."""
for step in range(steps):
self.update(delay)
if self.is_done():
break
self.step()
self.update(delay)
def update(self, delay=1):
sleep(delay)
if self.visible:
self.conceal()
self.reveal()
else:
self.reveal()
"""Display the BlockGrid for this world - the last thing to be added
at a location defines the location color."""
self.draw_world()
self.grid.show()
def draw_world(self):
self.grid[:] = (200, 200, 200)
world = self.get_world()
for x in range(0, len(world)):
for y in range(0, len(world[x])):
if len(world[x][y]):
self.grid[y, x] = self.colors[world[x][y][-1].__class__.__name__]
"""Hide the BlockGrid for this world"""
self.visible = False
display(HTML(''))
# ______________________________________________________________________________
# Continuous environment
class ContinuousWorld(Environment):
"""Model for Continuous World"""
def __init__(self, width=10, height=10):
self.width = width
self.height = height
def add_obstacle(self, coordinates):
self.things.append(PolygonObstacle(coordinates))
class PolygonObstacle(Obstacle):
def __init__(self, coordinates):
"""Coordinates is a list of tuples."""
self.coordinates = coordinates
# ______________________________________________________________________________
class Dirt(Thing):
"""The environment of [Ex. 2.12]. Agent perceives dirty or clean,
and bump (into obstacle) or not; 2D discrete world of unknown size;
performance measure is 100 for each dirt cleaned, and -1 for
each turn taken."""
def __init__(self, width=10, height=10):
def thing_classes(self):
return [Wall, Dirt, ReflexVacuumAgent, RandomVacuumAgent,
TableDrivenVacuumAgent, ModelBasedVacuumAgent]
def percept(self, agent):
"""The percept is a tuple of ('Dirty' or 'Clean', 'Bump' or 'None').
Unlike the TrivialVacuumEnvironment, location is NOT perceived."""
status = ('Dirty' if self.some_things_at(
agent.location, Dirt) else 'Clean')
bump = ('Bump' if agent.bump else'None')
return (status, bump)
def execute_action(self, agent, action):
if action == 'Suck':
dirt_list = self.list_things_at(agent.location, Dirt)
if dirt_list != []:
dirt = dirt_list[0]
self.delete_thing(dirt)
agent.performance -= 1
"""This environment has two locations, A and B. Each can be Dirty
or Clean. The agent perceives its location and the location's
status. This serves as an example of how to implement a simple
Environment."""
def __init__(self):
self.status = {loc_A: random.choice(['Clean', 'Dirty']),
loc_B: random.choice(['Clean', 'Dirty'])}
def thing_classes(self):
return [Wall, Dirt, ReflexVacuumAgent, RandomVacuumAgent,
TableDrivenVacuumAgent, ModelBasedVacuumAgent]
def percept(self, agent):
"""Returns the agent's location, and the location status (Dirty/Clean)."""
return (agent.location, self.status[agent.location])
def execute_action(self, agent, action):
"""Change agent's location and/or location's status; track performance.
Score 10 for each dirt cleaned; -1 for each move."""
if action == 'Right':
agent.location = loc_B
agent.performance -= 1
elif action == 'Left':
agent.location = loc_A
agent.performance -= 1
elif action == 'Suck':
if self.status[agent.location] == 'Dirty':
agent.performance += 10
self.status[agent.location] = 'Clean'
def default_location(self, thing):
"""Agents start in either location at random."""
return random.choice([loc_A, loc_B])
# ______________________________________________________________________________
tolusalako
a validé
def __eq__(self, rhs):
tolusalako
a validé
return rhs.__class__ == Gold
tolusalako
a validé
class Bump(Thing):
pass
tolusalako
a validé
class Glitter(Thing):
pass
class Breeze(Thing):
pass
tolusalako
a validé
class Scream(Thing):
pass
tolusalako
a validé
class Wumpus(Agent):
screamed = False
class Stench(Thing):
pass
tolusalako
a validé
holding = []
tolusalako
a validé
has_arrow = True
tolusalako
a validé
killed_by = ""
direction = Direction("right")
tolusalako
a validé
def can_grab(self, thing):
tolusalako
a validé
return thing.__class__ == Gold
class WumpusEnvironment(XYEnvironment):
pit_probability = 0.2 # Probability to spawn a pit in a location. (From Chapter 7.2)
# Room should be 4x4 grid of rooms. The extra 2 for walls
tolusalako
a validé
def __init__(self, agent_program, width=6, height=6):
tolusalako
a validé
self.init_world(agent_program)
tolusalako
a validé
def init_world(self, program):
"""Spawn items in the world based on probabilities from the book"""
"WALLS"
tolusalako
a validé
self.add_walls()
"PITS"
tolusalako
a validé
for x in range(self.x_start, self.x_end):
for y in range(self.y_start, self.y_end):
if random.random() < self.pit_probability:
self.add_thing(Pit(), (x, y), True)
self.add_thing(Breeze(), (x - 1, y), True)
self.add_thing(Breeze(), (x, y - 1), True)
self.add_thing(Breeze(), (x + 1, y), True)
self.add_thing(Breeze(), (x, y + 1), True)
"WUMPUS"
w_x, w_y = self.random_location_inbounds(exclude=(1, 1))
tolusalako
a validé
self.add_thing(Wumpus(lambda x: ""), (w_x, w_y), True)
tolusalako
a validé
self.add_thing(Stench(), (w_x - 1, w_y), True)
self.add_thing(Stench(), (w_x + 1, w_y), True)
self.add_thing(Stench(), (w_x, w_y - 1), True)
self.add_thing(Stench(), (w_x, w_y + 1), True)
"GOLD"
self.add_thing(Gold(), self.random_location_inbounds(exclude=(1, 1)), True)
"AGENT"
self.add_thing(Explorer(program), (1, 1), True)
def get_world(self, show_walls=True):
tolusalako
a validé
result = []
x_start, y_start = (0, 0) if show_walls else (1, 1)
if show_walls:
x_end, y_end = self.width, self.height
else:
x_end, y_end = self.width - 1, self.height - 1
for x in range(x_start, x_end):
tolusalako
a validé
row = []
for y in range(y_start, y_end):
row.append(self.list_things_at((x, y)))
result.append(row)
tolusalako
a validé
return result
def percepts_from(self, agent, location, tclass=Thing):
"""Returns percepts from a given location,
and replaces some items with percepts from chapter 7."""
tolusalako
a validé
thing_percepts = {
Gold: Glitter(),
Wall: Bump(),
Wumpus: Stench(),
"""Agents don't need to get their percepts"""
tolusalako
a validé
thing_percepts[agent.__class__] = None
tolusalako
a validé
if location != agent.location:
thing_percepts[Gold] = None
tolusalako
a validé
result = [thing_percepts.get(thing.__class__, thing) for thing in self.things
if thing.location == location and isinstance(thing, tclass)]
tolusalako
a validé
return result if len(result) else [None]
tolusalako
a validé
def percept(self, agent):
"""Returns things in adjacent (not diagonal) cells of the agent.
Result format: [Left, Right, Up, Down, Center / Current location]"""
tolusalako
a validé
result = []
result.append(self.percepts_from(agent, (x - 1, y)))
result.append(self.percepts_from(agent, (x + 1, y)))
result.append(self.percepts_from(agent, (x, y - 1)))
result.append(self.percepts_from(agent, (x, y + 1)))
result.append(self.percepts_from(agent, (x, y)))
"""The wumpus gives out a loud scream once it's killed."""
tolusalako
a validé
wumpus = [thing for thing in self.things if isinstance(thing, Wumpus)]
if len(wumpus) and not wumpus[0].alive and not wumpus[0].screamed:
result[-1].append(Scream())
wumpus[0].screamed = True
tolusalako
a validé
return result
tolusalako
a validé
def execute_action(self, agent, action):
"""Modify the state of the environment based on the agent's actions.
Performance score taken directly out of the book."""
tolusalako
a validé
if isinstance(agent, Explorer) and self.in_danger(agent):
return
tolusalako
a validé
agent.bump = False
if action == 'TurnRight':
tolusalako
a validé
agent.performance -= 1
elif action == 'TurnLeft':
tolusalako
a validé
agent.performance -= 1
elif action == 'Forward':
agent.bump = self.move_to(agent, agent.direction.move_forward(agent.location))
agent.performance -= 1
elif action == 'Grab':
things = [thing for thing in self.list_things_at(agent.location)
if agent.can_grab(thing)]
tolusalako
a validé
if len(things):
tolusalako
a validé
print("Grabbing", things[0].__class__.__name__)
if len(things):
agent.holding.append(things[0])
tolusalako
a validé
agent.performance -= 1
elif action == 'Climb':
if agent.location == (1, 1): # Agent can only climb out of (1,1)
tolusalako
a validé
agent.performance += 1000 if Gold() in agent.holding else 0
self.delete_thing(agent)
tolusalako
a validé
elif action == 'Shoot':
"""The arrow travels straight down the path the agent is facing"""
tolusalako
a validé
if agent.has_arrow:
arrow_travel = agent.direction.move_forward(agent.location)
while(self.is_inbounds(arrow_travel)):
wumpus = [thing for thing in self.list_things_at(arrow_travel)
if isinstance(thing, Wumpus)]
if len(wumpus):
wumpus[0].alive = False
break
arrow_travel = agent.direction.move_forward(agent.location)
agent.has_arrow = False
tolusalako
a validé
def in_danger(self, agent):
"""Checks if Explorer is in danger (Pit or Wumpus), if he is, kill him"""
tolusalako
a validé
for thing in self.list_things_at(agent.location):
tolusalako
a validé
if isinstance(thing, Pit) or (isinstance(thing, Wumpus) and thing.alive):
tolusalako
a validé
agent.alive = False
agent.performance -= 1000
agent.killed_by = thing.__class__.__name__
tolusalako
a validé
return True
return False
tolusalako
a validé
def is_done(self):
"""The game is over when the Explorer is killed
or if he climbs out of the cave only at (1,1)."""
explorer = [agent for agent in self.agents if isinstance(agent, Explorer)]
tolusalako
a validé
if len(explorer):
if explorer[0].alive:
return False
else:
print("Death by {} [-1000].".format(explorer[0].killed_by))
tolusalako
a validé
else:
print("Explorer climbed out {}."
.format(
"with Gold [+1000]!" if Gold() not in self.things else "without Gold [+0]"))
tolusalako
a validé
return True
# TODO: Arrow needs to be implemented
# ______________________________________________________________________________
def compare_agents(EnvFactory, AgentFactories, n=10, steps=1000):
"""See how well each of several agents do in n instances of an environment.
Pass in a factory (constructor) for environments, and several for agents.
Create n instances of the environment, and run each agent in copies of
each one for steps. Return a list of (agent, average-score) tuples."""
envs = [EnvFactory() for i in range(n)]
return [(A, test_agent(A, steps, copy.deepcopy(envs)))
for A in AgentFactories]
def test_agent(AgentFactory, steps, envs):
"""Return the mean score of running an agent in each of the envs, for steps"""
agent = AgentFactory()
env.add_thing(agent)
env.run(steps)
return mean(map(score, envs))
# _________________________________________________________________________
__doc__ += """
>>> a = ReflexVacuumAgent()
>>> a.program((loc_A, 'Clean'))
'Right'
>>> a.program((loc_B, 'Clean'))
'Left'
>>> a.program((loc_A, 'Dirty'))
'Suck'
>>> a.program((loc_A, 'Dirty'))
'Suck'
>>> e = TrivialVacuumEnvironment()
>>> e.add_thing(ModelBasedVacuumAgent())
>>> e.run(5)