Project 2

Due date: Midnight Mon Dec 7.

In this project you will use classes to implement behavior of various robots as they war with each other. The project is similar to the code from Day 26 and Day 27 (in particular Day 27), so you should start by understanding the design of the code from Day 27. The war proceeds as follows.

Implementation

For the implementation, you will be required to create four classes. The grading is such that you should first work on getting the attack robots to work and then attempt the medic robot. The code should be in two files, world.py and robots.py.

World class

You must create a class called World which stores the grid and the robots at each location. This class must be in a file called world.py. The only property should be the 20x20 grid: an array of arrays where each element in the array is either None or a robot object. It must have the following methods. You can create additional methods to help your implementation.

Robot class

You must create a generic Robot class which implements the shared actions and properties between the two types of robots. This Robot class should be in a file robots.py. The properties should be the team, current location, direction, and hit points. Your Robot class must have (at least) the following methods:

As a hint on the direction, I suggest you keep the current direction the robot is facing as a string "N", "E", "S", "W". You can then use dictionaries with keys "N", "E", "S", "W" to implement the turning and moving. (For example, left90 should use {"N":"W", "W":"S", "S":"E", "E":"N"}.)

AttackRobot

You must create a AttackRobot class which inherits from the generic Robot class. The AttackRobot class must implement a run_turn method with one parameter which is the world object. The run_turn method must implement the attack robot behavior by using the world object to check the neighboring robots and attack or move. The class must also be in robots.py. You should consider some helper methods to implement to make run_turn easier to implement, such as a function to attempt an attack or check for a turn. These are just examples, you can use whatever helper methods you like. (When coming up with a helper method, you might think about if it should appear on the Robot base class or inside AttackRobot.)

MedicRobot

You must create a MedicRobot class which inherits from the generic Robot class. The MedicRobot class must implement a run_turn method with one parameter which is the world object. The run_turn method must implement the medic robot behavior. It should also be in robots.py. The grading is such that we will test your code with no medics first, so you should not work on the medic until you have the attack robot working correctly. Each medic reads movement commands from a file and this should be done inside the __init__ method; during __init__ the entire file contents should be read in as commands into a list, so that run_turn does not have any file access. Again you should consider writing helper methods such as a method to read the commands from the file or interpret a command.

The format is as follows:

Here is an example file contents with three commands (that causes the medic to move in a box as long as it is not near a wall).

Forward
Forward
Left90

Testing

First, while you are writing each class you should write a few tests which call the various methods you are writing. None of this test code should be submitted, but it is helpful to test small pieces of code before testing if all the code works.

For testing the entire program, here is some sample test code you can stick in a file called test.py.

from world import *
from robots import *

def print_board(w):
    print("-" * 60)
    for y in range(19,-1,-1):
        line = ""
        for x in range(0,20):
            r = w.test_position(x, y)
            if r == None:
                line += ".... "
            else:
                if isinstance(r, AttackRobot):
                    rtype = "A"
                elif isinstance(r, MedicRobot):
                    rtype = "M"
                else:
                    rtype = "!"
                if r.get_team() == 1:
                    line += "%s%02i%s " % (rtype, r.get_health(), r.get_direction())
                else:
                    line += "%s%02i%s " % (rtype.lower(), r.get_health(), r.get_direction())
        print(line)
    print("-" * 60)

world = World()
# Add a few robots (try different values)
world.add_attack_robot(1, 5, 5, "N")
world.add_attack_robot(....)

print_board(world)

# Run a turn and see the result
world.run_turn()
print_board(world)

world.run_turn()
print_board(world)

And check that the board positions are correct.

Some Test Samples

this directory has some test code I have written. Each test comes with a python file which imports test.py (which I provide) and the world and robot code you have written. Some of the tests also come with an instruction file for the medics. Each test also comes with an output file which was generated by running the test code. You should be checking that your output matches the expected output.

I have run these tests on Python 3.4.0 64 bit Linux.

Grading

Our grading will work by first specifying a random seed using seed, adding robots to your world class, calling run_turn on the board several times, then calling test_position to determine if the world is correct.

See Also

This project was partly inspired by pyrobotwar.