I am testing my two classes with a file called test.py. I am just learning programming so this is just a practice program. There is one atlas(map) and i can put multiple ‘robots’ inside one map.
#test.py
from Atlas import Atlas
atlas = Atlas()
atlas.add_robot('rbt1')
#atlas.py
from Robot import Robot
class Atlas:
def __init__(self):
...
def add_robot(self, robot, zone = 'forrest'):
self.robot = Robot(robot)
print 'added robot %s to %s' % (robot, zone)
#robot.py
class Robot():
def __init__(self, rbt, zone = 'forrest'):
self.name = rbt
print "%s initiated" % rbt
def step(self, direction):
...
I use the code “atlas.add_robot(‘rbt1’)” to put a new robot inside the atlas.
I want to be able to control the robot with a command such as “rbt1.step(‘left’)” in test.py.
You should make your robot in test.py with
newRobot = Robot('rbt1'), then doatlas.add_robot(newRobot). To do this, we pass in a whole robot, not a robot name. Atlas should not be trying to initialize robots, because it is an Atlas. It should just worry about what Atlases do: keep track of where robots are.A good concept to learn in programming is which pieces of code are allowed to touch something. In this case, we will create the robot in test.py (so we can touch it), then pass it to an Atlas (so the Atlas can touch it). That is effectively the heart of your question. Here are some general ways to deal with this problem:
yourAtlas.robotsToZones(...)below)nonlocalkeyword in python to declare your intent to do thisTo change the control flow so you don’t have this problem: the Atlas can be made more flexible by passing in a fully-made Robot. It is an Atlas after all. Why would an Atlas be in charge of making Robots?
Alternatively you could do this:
(probably better since we probably expect robots to change zones)
(if you care about speed you could actually do both… but you usually shouldn’t care about speed, and that would require making sure both structures are in sync)
Also you should have data exist in just one spot. In your case, both the Robot and Atlas need to know which zone a robot is in. This is bad because you must make sure those two values are always equal and in sync, leading to needless headaches and complications, even maybe bugs. The solution is to ignore which zone a robot is in, in robot.py:
A Robot should never need to figure out where it is; that’s the job of the atlas. If test.py needs to know where a Robot is, it can do something like
myAtlas.whereIs(myRobot), which can justreturn self.robotsToZones[robot.name]. This is known as modularization and separation of concerns.(sidenote: The above assumes that you have some other mechanism to track which robots are in which zones, and you don’t have coordinates. If you have your
step()function deal with coordinates, you’ll have to decide whether you have global or per-zone coordinates. The latter case is probably easier since all you need to define is how the boundaries of zones stitch together; though you can do the first case if you have the Atlas define non-overlapping (ick, possible bugs) boundaries for which zone is where. You can also maybe do something like have signposts which define zone boundaries, and a Robot is in the zone of the closest signpost. Though having each zone be made of equally-sized rectangles, representable via a grid, is probably easiest.)