Skip to content
This repository has been archived by the owner on Oct 19, 2021. It is now read-only.

Commit

Permalink
Merge remote-tracking branch 'origin/main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
Myonmu committed Sep 24, 2021
2 parents 0e8c70c + ed39db2 commit 0d9aa5f
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 34 deletions.
3 changes: 3 additions & 0 deletions .idea/agent-aspirateur.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions .idea/other.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

115 changes: 82 additions & 33 deletions hoover-agent/environment.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
from numpy import sqrt, power
import random


class Thing:
"""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
Expand All @@ -6,10 +10,6 @@ class Thing:
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

def show_state(self):
"""Display the agent's internal state. Subclasses should override."""
print("I don't know how to show_state.")
Expand All @@ -20,10 +20,46 @@ def display(self, canvas, x, y, width, height):
pass


class Agent(Thing):
class Dirt(Thing):
pass


class Jewel(Thing):
pass


class Agent(Thing):
"""An Agent is a subclass of Thing with one required instance attribute
(aka 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
self.bump = False
self.holding = []
self.performance = 0
if program is None:
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):
"""Return True if this agent can grab this thing.
Override for appropriate subclasses of Agent and Thing."""
return False


class Environment:
"""Abstract class representing an Environment. 'Real' Environment classes
inherit from this. Your Environment will typically need to implement:
Expand All @@ -35,54 +71,74 @@ class Environment:
Each thing has a .location slot, even though some environments may not
need this."""

def __init__(self):
def __init__(self, width=25, height=25):
self.things = []
self.agents = []
self.width = width
self.height = height

perceptible_distance = 1

def things_near(self, location, radius=None):
radius = self.perceptible_distance if radius is None else self.perceptible_distance
return [thing for thing in self.things
if sqrt(power(location[0]-thing.location[0], 2) + power(location[1]-thing.location[1], 2)) <= radius]

def thing_classes(self):
return [] # List of classes that can go into environment
return [Dirt, Jewel, Agent] # List of classes that can go into environment

def percept(self, agent):
"""Return the percept that the agent sees at this point. (Implement this.)"""
raise NotImplementedError
"""Return the percept that the agent sees at this point."""
return 'Dirty' if self.some_things_at(agent.location, Dirt) else 'Clean'

def execute_action(self, agent, action):
"""Change the world to reflect this action. (Implement this.)"""
raise NotImplementedError

def default_location(self, thing):
"""Default location to place a new thing with unspecified location."""
return None
location = self.random_location_inbounds()
while self.some_things_at(location, Thing):
location = self.random_location_inbounds()
return location

def is_inbounds(self, location):
"""Checks to make sure that the location is inbounds (within walls if we have walls)"""
x, y = location
return not (x < 0 or x > self.width or y < 0 or y > self.height)

def random_location_inbounds(self, exclude=None):
"""Returns a random location that is inbounds."""
location = (random.randint(0, self.width),
random.randint(0, self.height))
if exclude is not None:
while location == exclude:
location = (random.randint(0, self.width),
random.randint(0, self.height))
return location

def exogenous_change(self):
"""If there is spontaneous change in the world, override this."""
pass

def is_done(self):
"""By default, we're done when we can't find a live agent."""
return NotImplementedError

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
override this method."""
if not self.is_done():
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.execute_action(agent, action)
self.exogenous_change()
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.execute_action(agent, action)
self.exogenous_change()

def run(self, steps=1000):
"""Run the Environment for given number of time steps."""
for step in range(steps):
if self.is_done():
return
self.step()

def list_things_at(self, location, tclass=Thing):
Expand Down Expand Up @@ -112,12 +168,5 @@ def add_thing(self, thing, location=None):

def delete_thing(self, thing):
"""Remove a thing from the environment."""
try:
self.things.remove(thing)
except ValueError as e:
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)
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
numpy~=1.21.2
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
author_email='[email protected]',
packages=[
'pretty-tables',
'colorama'
'colorama',
'numpy',
]
)

0 comments on commit 0d9aa5f

Please sign in to comment.