Problem 8 (250pts): Bodyguard Ant

Right now, our ants are quite frail. We'd like to provide a way to help them last longer against the onslaught of the bees. Enter the BodyguardAnt.

ClassFood CostHealth
BodyguardAnt42

A BodyguardAnt differs from a normal ant because it is a ContainerAnt; it can contain another ant and protect it, all in one Place. When a Bee stings the ant in a Place where one ant contains another, only the container is damaged. The ant inside the container can still perform its original action. If the container perishes, the contained ant still remains in the place (and can then be damaged).

Each ContainerAnt has an instance attribute ant_contained that stores the ant it contains. It initially starts off as None, to indicate that no ant is being protected. Implement the store_ant method so that it sets the bodyguard's ant_contained instance attribute to the passed in ant argument. Also implement the ContainerAnt's action method to perform its ant_contained's action if it is currently containing an ant.

In addition, you will need to make the following modifications throughout your program so that a container and its contained ant can both occupy a place at the same time (a maximum of two ants per place), but only if exactly one is a container:

  1. There is an Ant.can_contain method, but it always returns False. Override the method ContainerAnt.can_contain so that it takes an ant other as an argument and returns True if:
    • This ContainerAnt does not already contain another ant.
    • The other ant is not a container.
  2. Modify Ant.add_to to allow a container and a non-container ant to occupy the same place according to the following rules:
    • If the ant originally occupying a place can contain the ant being added, then both ants occupy the place and original ant contains the ant being added.
    • If the ant being added can contain the ant originally in the space, then both ants occupy the place and the (container) ant being added contains the original ant.
    • If neither Ant can contain the other, raise the same AssertionError as before (the one already present in the starter code).
    • Important: If there are two ants in a specific Place, the ant attribute of the Place instance should refer to the container ant, and the container ant should contain the non-container ant.
  3. Add a BodyguardAnt.__init__ that sets the initial amount of health for the ant.

Hint: You may find the is_container attribute that each Ant has useful for checking if a specific Ant is a container. You should also take advantage of the can_contain method you wrote and avoid repeating code.

Note: the constructor of ContainerAnt.__init__ is implemented as such

def __init__(self, *args, **kwargs):
   Ant.__init__(self, *args, **kwargs)
   self.contained_ant = None

As we saw in Hog, we have that args is bound to all positional arguments (that is all arguments not passed not with keywords, and kwargs is bound to all the keyword arguments. This ensures that both sets of arguments are passed to the Ant constructor).

Effectively, this means the constructor is exactly the same as Ant.__init__ but sets self.ant_contained = None

Before

Before writing any code, read the instructions and test your understanding of the problem:

python ok -q 08 -u

After

After writing code, test your implementation:

python ok -q 08