CS 261 Homework 2 - Zombie Infection Simulator
Due Wed Feb 13 at 9:00am
Extended to Fri Deb 15 at 9:00am
Overview
In this assignment, you will create an agent-based simulation of the zombie apocalypse and the spread of the zombie-ism. This simulation will be based on that designed by Kevin Davis http://kevan.org/proce55ing/zombies/ (Yyu can test out the demo on that site). A screenshot of an example run in our system is below: In this picture, green dots are zombies, pink dots are humans, and yellow dots are people who are panicking. The outbreak started from a single zombie.
You are welcome to work individually or in pairs on this assignment.
Objectives
- To practice with abstract classes, inheritence, and type conversion
- To practice designing and implenting complex class interactions, including data sharing
- To practice with two-dimensional arrays as a data structure
- To explore agent-based modeling as a form of program design
Necessary Files
You will want a copy of the
Hwk2.zip file
which contains the the basic code to display your simulation. (You are perfectly capable of writing this code your self and are welcome to modify--I am providing this code to get you started). This zip archive contains three files: ZISFrame.java
(the GUI frame that displays the simulated City; this also has a main method), City.java
(the beginnings of the City class that will be a part of your simulation), and the README.txt for the assignment.
Be sure to carefully look over the City class in particular. You will need to make substanial modifications and additions to this file (including filling in some of the provided methods)---it might not even compile in its current form!
Details
- Read through all of these instructions carefully before you begin!
- You will be making a simulation of the spread of a zombie infection. This system will be agent-based--that means that you will model many different "agents" (i.e., objects) that will have their own specific behaviors. The simulation is the emergent result of how these agents interact.
-
In this simulation, you have a large number of people (like 5,000) running around a "city" or "building" (the black is where they can walk, and the gray are solid walls. Note that the map is randomly generated). Agents act as follows:
Humans are pink, and move around at random. Zombies are green, and move more slowly and change direction more frequently than humans. If a zombie sees movement in front of it, it walks in that direction without turning. After a while, the zombie will lose interest and start turning randomly. If a zombie finds a human directly in front of it, it bites and infects the human, who immediately turns into a zombie. If a human sees a zombie directly in front of him, he turns around and panics. Panicked humans run even faster. But if a panicked human doesn't see a zombie for a short time, he will stop being panicked. If a human sees another person who is panicked, they too become panicked (panic spread in the zombie apocalypse). In the end, the single zombie will be able to infest the rest of the city, leaving nothing but small herds of zombies looking for food.
- Your simulation will need a number of classes: Agent, Human, PanickedHuman, Zombie, City, and the provided ZISFrame.
-
Agent
This class will act as the parent class for all the agents in your system (Humans, PanickedHumans, and Zombies are all agents). It should be abstract--you can't directly instantiate an Agent class. At the very least, all agents should keep track of their position in the city, what direction they are currently facing (i.e., north east south or west).
- Hint: The Point class is an easy way to encapsulate both position and direction!
- Agents will need different speeds (since zombies are slower than humans who are slower than panicked humans). While you could have this chance how many steps they take on each turn (similar to the Bouncing Ball class from 161), another option is to have faster agents take more turns (in which they take a single step)--zombies may only step every 5 turns, while humans step every 2 turns and panicked humans step every turns. You can approximate this using randomization--zombies may have a 20% chance of taking their turn, while humans have a 50% chance. The simulation will run fast enough that you won't be able to tell the difference.
- Remember that abstract classes may have abstract methods!
- Agents will need to have some way of "looking fowards" (so humans can see zombies and zombies can see humans). This will mean checking the locations of other agents--information that is likely associated with the city. You will need to decide if this functionality should belong to agents or to the city, and how those two data structures should interact.Agents should be able to see about 10 squares in front of them, but not through walls or other agents.
- Note that agents will want to keep track of their location, but the City ALSO will need to keep track of everyone (so that they can be drawn on the screen). Thus you will likely have some data duplication that you will need to keep synchronized.
-
Human
Humans are represented by pink dots on the map. On their turn, humans should take a step in whatever direction they are facing. However, you'll need to make sure that a human (or any agent) doesn't try to step into a space that there is a wall or another Agent! If a human can't walk forward, they should turn to face a random direction. After taking a step, if a human sees a zombie, he should turn around and turn into a PanickedHuman. If he sees a PanickedHuman, he should also become a PanickedHuman (but doesn't need to turn around).
- Despite what polymorphism might suggest, we can't just transform objects of one class into another. So you will need to create a new PanickedHuman object that can replace the Human object in your data structures. Again, since the City is keeping track of people, you'll have to also replace the Agent in the City's model of the world.
-
Zombie
Zombies are represented by green dots on the map. Like humans, on their turn, a zombie should try to take a step in whatever direction they are facing, then check to see if it see anyone in front of it. If it sees a non-Zombie, it should start "pursuing" that person--moving in that direction without turning. Zombies should keep pursing for a short time--perhaps 10 turns (note that the count can start over again if the zombie sees another person!) If the zombie is not pursing anyone, it should change directions. After they've moved, if there is a person immediately in front of them, zombies should "bite" that person and turn them into a Zombie.
- Like with changing Humans to PanickedHumans, you'll need to have a way to turn Humans into Zombies so that the City is aware of the change.
- I managed to get a nice clustering behavior by having zombies turn if they are not pursuing AND if whatever they see in front of them is not a zombie. You are welcome to experiment with other behavior algorithms to make your zombies act in interesing ways (but be sure to document what you do in your README!!)
- PanickedHuman PanickedHumans are represented by yellow dots on the map. PanickedHumans are a type of Human (that's a hint--how can we use our Human functionality without rewriting a lot of code?) Indeed, the only difference is that PanickedHumans move faster than humans. If PanickedHumans don't see a zombie for a short time (10 turns is good), then they should stop being panicked.
-
City
The City class will keep track of all your Agents and draw them on the map (that is displayed through the ZISFrame). This class will need know where agents are, even as those agents move around, so that it can help agents to see each other (and draw them on the map each cycle). The city is also responsible for telling all the agents to act on their turn.
- Since you will be tracking agents on a two-dimensional grid, a two-dimensional array is an incredibly helpful data structure to use. You can quickly look up what agent (if any) is in a particular spot. Note that this array will not be totally filled; many slots will be
null
. - The most difficult part of this class (and of the whole program) is being able to have Agents move and replace themselves, but still keep the city up to date so that the city can give accurate information about who is located where (such as for the "look forward" functionality). Remember that you can let Agents know about the city by passing it as a parameter (e.g., you can have a method in Agent that takes a City as a parameter, and then have city call that method with
methodName(this)
). - Although this class will need to share information, try to share as little as possible in order to avoid coupling problems.
- Since you will be tracking agents on a two-dimensional grid, a two-dimensional array is an incredibly helpful data structure to use. You can quickly look up what agent (if any) is in a particular spot. Note that this array will not be totally filled; many slots will be
- This program has a number of interconnected moving parts, though most of those parts are individually simple (but not necessarily simplistic). Take some time to think about HOW you are going to implement the program before you do. Try to outline methods you will use and who will call those methods (and when), then fill in the blanks. If you get stuck or need help, don't be afraid to ask!
- Once you're finished, be sure that all your code is fully documented. This means full Javadoc comments on each method you create, and lots of comments explaining your code. Remember to explain the why of the code, not the what.
- Finally, be sure to complete the README.txt that you found in the Hwk2.zip file, and upload it along with your code!
Submitting
BEFORE YOU SUBMIT: make sure your code is fully documented and functional! If your code doesn't run, I can't give you credit!
Submit your program to the Hwk2 submission folder on hedwig, following the instructions detailed in Lab A. You should upload Agent.java, Human.java, Zombie.java, PanickedHuman.java, City.java, ZISFrame.java and the README.txt.
The homework is due at the start of class on Wed Feb 13.
Plan of Attack
This is a large complex program and it's hard to know where to begin. Here is a rough plan of attack for how to start making this thing work (compiled from memory of how I implemented the program):
- Make the Human class (and the Agent class it extends) and just try to get them to show up on the screen--randomly spread them throughout the city.
- Make the agents be populated in legal areas (e.g., in roads and not in the buildings, and not in the same square. Hint: try making a list of all possible places an agent COULD be and then picking a random item from that list)
- Make the agents all move in one direction on a tick (e.g., to the left)
- Make the agents all move in a random directon on a tick
- Test repeatedly that things seem to work
- Make the "look forward" method so agents can see if there is a wall in front of them; don't have them walk through walls
- Make the agents turn randomly when they hit a wall. This should make them all skitter about in nice ant lines.
- Make the agents also "look forward" and turn when they're about to hit another person. This should make them all move randomly.
- You'll need to have new positions be tracked both by the Agent object and by the City object
- Test repeatedly that things seem to work
- Replace a single agent with a zombie (the start of the outbreak).
- Make the "look forward" method allow agents to see far in front of them
- Make the zombie move appropriately, as described above.
- Have the zombie check if it should bite a person (using the same "look forward" method)
- If it bites, tell the city to swap out the Human for a Zombie
- Test repeatedly that things seem to work
- Use the same general code you used for Zombies to see people to have Humans see zombies
- Use the same general code you used for Zombies to bite people to have people panic
- Test repeatedly that things seem to work
- Clean up any leftover issues or code.
Again, this is a hard one. If you have any problems or questions, feel free to ask!
Extensions
So many options...
- Extend the interface so that you can start, stop, and reset the simulation. Buttons would be a clean way of doing this.
- Try altering the parameters of the simulation, sch as how fast agents move, how many agents there are, how open the map is, etc. Document any changes in the simulation results--can you find a set of circumstances under which the population isn't wiped out?
- You can extend the behavior of individual agents--maybe zombies speed up when they see humans, or humans try to stay in large groups, or bitten humans die before they turn into zombies. Perhaps there is a Hero agent that is able to kill zombies?
Grading
This assignment will be graded based on approximately the following criteria:
- Program is able to graphically display the simulation as it is run (10%)
- Program includes an Agent abstract class, which is properly subclassed (10%)
- Program includes functional models of Humans (10%)
- Program includes functional models of Zombies (10%)
- Program includes functional models of PanickedHumans (5%)
- Humans can turn into Zombies, Humans can become Panicked, and PanickedHumans can calm down (10%)
- The City class keeps track of and displays all the different agents (20%)
- Program demonstrates proper cohesion and coupling (particularly in terms of information access), in accordance with good style (10%)
- Program is fully documented (10%)
- README is completed (5%)