Released on Thursday March 31 and due before Midnight, Thursday April 14.
The design document for this project, design3.txt, is due before Midnight, Friday April 8.
Living organisms are probably the most complex things in the universe. They are extremely difficult to understand, let alone model mathematically, chemically, biologically or computationally. It's even harder to understand and model communities or ecologies of living organisms that interact and effect one another. The invention of modern computers have given us a new tool to model systems of living things and doing so is an important and popular subfield known as artificial life or sometimes just alife. Chris Langton, the computer scientist who coined the term in 1987, defined artificial life as follows.
Artificial life is the study of artificial systems that exhibit behavior characteristic of natural living systems. It is the quest to explain life in any of its possible manifestations, without restriction to the particular examples that have evolved on earth. This includes biological and chemical experiments, computer simulations, and purely theoretical endeavors. Processes occurring on molecular, social, and evolutionary scales are subject to investigation. The ultimate goal is to extract the logical form of living systems.
Microelectronic technology and genetic engineering will soon give us the capability to create new life forms in silico as well as in vitro, This capacity will present humanity with the most far-reaching technical,theoretical and ethical challenges it has ever confronted. The time seems appropriate for a gathering of those involved in attempts simulate or synthesize aspects of living systems.
Computational models of living things goes back further, of course. In 1984, A. K. Dewdney published an article Sharks and fish wage an ecological war on the toroidal planet Wa-Tor in the Computer Recreations column of Scientific American. It was an early example of a predator-prey simulation and has been implemented many times. Google for "wator" or "wa-tor" and you'll find lots of Java applets that stem from this article. The interactions of populations of predators and prey was a very early example of modeling living systems and can be modeled mathematically using Lotka-Volterra equations. Implementing a simulation system and experimenting with it is another way to explore the dynamics.
You are part of an advance team surveying the planet Wa-Tor and tasked with deciding whether or not it is suitable for a human colony. Wa-Tor is an unusual planet in two respects: it's shape is not the usual sphere, but a torus and it is completely covered by water. An initial bio-scan reveals that there are just three kinds of living things on Wa-Tor: a yellowish-green algae that gets energy from Wa-Tor's star and grows slowly, and two kinds of fish-like creatures which we'll call sharks and tuna. Tuna are small fish-like creatures that eat algae and are eaten by sharks. Sharks are large shark-like creature that eat the smaller tuna. Your job is to try to understand the Wa-Tor's food web and make sure that the planned human colony will not upset Wa-Tor's natural environment. You decide to build a simulation that you can use to study the interactions of the algae, tuna and sharks. As you learn more about the algae's growth rate and how often the sharks and tuna bare young and how much they have to eat, you can update the parameters in the simulation and better understand Wa-Tor's environment.
Wa-Tor is a torus shaped planet completely covered in water and inhabited by sharks, tuna and algae. |
Wa-Tor sharks eat Wa-Tor tuna. Nothing eats Wa-Tor sharks. |
Wa-Tor tuna eat Wa-Tor algae and are eaten by Wa-Tor sharks |
Wa-Tor algae just need starshine, which is plentiful,
and are eaten by Wa-Tor tuna. |
Simulate Wa-Tor using an array ocean with ROWS rows and COLS columns. For testing purposes, we will expect this to be 15x15. You can treat the rectangular array as a torus easily by having it wrap around. Moving a fish off the right edge, for example, will have it reappear on the left. The model is governed by the following parameters. All but the first two (the size of the ocean) are inputs to be read in from the user.
rows | integer number of rows in the ocean array |
cols | integer number of columns in the ocean array |
numSharks | integer number of sharks when the simulation begins |
numTunas | integer number of tunas when the simulation begins |
numAlgae | integer number of algae when the simulation begins |
starveShark | integer number of timeclicks until a shark dies of starvation if it has not eaten |
starveTuna | integer number of timeclicks until a tuna dies of starvation if it has not eaten |
reproShark | integer number of timeclicks until a shark is ready to reproduce |
reproTuna | integer number of timeclicks until a tuna is ready to reproduce |
grow | integer number of timeclicks until an alga is ready to grow |
Each cell in the ocean array will hold a structure that represents what is in the cell. In general, a cell can hold one shark, one tuna and one alga. We will give you the structure you must use for a cell (see the partial wator.h header file).
The simulation progresses in a series of "steps", one per timeClick (a unit of measure similar to what called a day in the distant past). For each step, you should iterate over all of the array cells and if one is filled with a living thing (fish or algae) decide what it will do for that step using the following rules.
At each step, each fish (shark or tuna) will
We've provided a partial header file for Wator. Your actual header file wator.h will include, of course, any additional structures or function prototypes that you might want or need for your simulation module. We are specifying this much since it is needed to specify the interface between your program and the creation.o module.
The partial header file we provide includes constants, structures that you must use in order to work with creation.o, the package that initializes the simulation by populating the world. You must use these structures as defined and in the way intended. In principle, you can modify them by adding additional, new fields, but please ensure you have a good reason to do so. This partial header file also includes the prototypes of three functions that you must implement. You may not change the prototypes of these functions.
You will have to write a function that prints a representation of the model. This is pretty simple and basically involves iterating over the cells in the ocean array and printing one character to represent what is in the cell. Here's what to print.
character |
cell state |
' ' |
nothing in the cell |
'>' |
cell contains only a shark |
'>' |
cell contains a shark and algae |
'~' |
cell contains only a tuna |
'*' |
cell contains only algae |
Note that a shark and an alga can coexist in the same cell of the ocean, but for display purposes, we only show the shark. Tuna and algae do not coexist, because the tuna always eats the algae, so if a cell is displayed as an alga, then an alga is all it contains.
if there is a tuna in this cell adjust age get the new position if there is no tuna in the new position move the tuna adjust timeLastMoved if there is an alga in the new position eat it (remove alga & reset starvation) else get closer to starving if she starved remove the tuna if she didn't starve - look into reproduction adjust reproduction time if it's time to reproduce reset reproduction time leave a baby behind if there is a shark the tuna gets eaten (remove tuna & reset shark starvation) else (there was a tuna in the new position, so the tuna can't move) adjust reproduction counter, but can't reproduce now adjust starvation counter if tuna starves remove itYou can mimic this same order for the code for sharks, which are simpler than tuna, since they can't be eaten.
While the complexity of this program may seem high, it's manageable when you break things down. The basic tasks you have to do include: reading the parameters from the user; creating the initial model; displaying the current state of the model; and advancing the model by one step. As an initial goal, consider reading the parameters, creating the model and displaying it. Once you have that working you can tackle the harder problem of advancing the model by one timeClick.
When advancing the model one timeClick, think about writing separate functions to move a shark, move a tuna, and grow algae. Considering each as a separate case reduces the complexity.
While you are debugging, you will find it useful to have several data files that provide input to test your program. Use I/O redirection to apply your program to a test case. Using the same test cases, as opposed to randomly entering input data, helps you recognize when something unexpected has changed. But, be sure to have several test cases so that different parts of your program are exercised. You can use the test files we've created, of course.
Here's a sample run that shows the output your program should generate. Ideally, your output should match this exactly, except for your greeting message and very minor differences (e.g., an extra newline here or there). In particular, for the sample data, your program and our reference program should lead to the same final state or at least a very similar final state (e.g., "the sharks all die off around step 200 and the tuna and algae live on" or "the sharks eat the last tuna around step 500 and then die off quickly. the algae then grow to occupy every cell.") Note that we represent a cell with a shark in it with the > character, a cell with a tuna in it using ~, and a cell with just algae in it with *. We have some test files that can be fed to your program using unix's input redirections. For example, if you have copied the directory /afs/umbc.edu/users/s/b/sbogar1/pub/wator/tests into the directory containing your project 3, then you should be able to type
% a.out < test/noSharks
Instead of reading input from the terminal window, your program will get its input from the file test/noSharks. Our output for these test files can be found here. We generated the output files by redirecting both the input and output, as in
a.out <tests/noAlgae >output/noAlgae
As you develop and debug your program, you might find it useful to run these and other test files though your program, capturing the output for later examination. You can read about our set of test files in tests/README.
You will want to do something like the following to compile your program
Actually, if you are doing this in a directory that only contains your project three files, you may be able to use Unix's ability to expand a file name with wild cards to do the following% gcc -ansi -Wall -c proj3.c % gcc -ansi -Wall -c wator.c % gcc proj3.o wator.o creation.o
% gcc -ansi -Wall -c *.c % gcc *.o
We will test your program using a special input file that should generate an identical end state if you have implemented things correctly. You can use the files in tests to exercise your program if you like. The test file we will use will be similar to these.
Since you must use separate compilation for this project, you will have several files that must be submitted for this project. The source file that contains main( ) MUST be called proj3.c, the file containing your simulation functions MUST be called wator.c, and the header file MUST be called wator.h. You don't need to submit creation.o. We'll find a copy somewhere. To submit your project, type the following at the Unix prompt. Note that the project name starts with uppercase 'P'.
submit cs201 Proj3 proj3.c wator.c wator.h
Do NOT forget to submit your wator.h file. Your program will NOT compile without it.
To verify that your project was submitted, you can execute the following command at the Unix prompt. It will show all files that you submitted in a format similar to the Unix 'ls' command.
submitls cs201 Proj3
If this project interests you, here are some things you might think about or do.
One thing you can discover in such a simulation is that not all parameter settings will lead to a stable environment, i.e., one in which sharks, tunas, and algae can all co-exist. If the algae completely die out, the entire food chain collapses. If some shark eats the last tuna, the sharks are doomed. If the parameters do allow for a stable ecology, the numbers of sharks, tuna and algae will go up and down and do so following a pattern. Here's an interesting question: can you characterize the parameter sets that lead to a stable environment? Does it depend on the size of the ocean?
In a large ocean you may also see some structures emerge -- like schools of tuna with sharks along the edge, feeding on them. Some of these "emergent phenomena" are difficult to model with mathematical equations and can best be explored through simulations like these.
There is a lot more you can do with this program to make it more interesting, like add simple graphics (using the curses library) or generating data that can be graphed with Microsoft Excel to see how the three populations grow and shrink over time. You must submit a basic program following the specifications we give and without any additional features. We'll grade you on this. But, we do encourage you to produce an enhanced version of your program. We won't give out extra credit for also making an advanced version. But if you do one, we promise that you will (1) have fun; (2) learn a lot; (3) have something you can add to your portfolio to impress prospective employers and friends; and (4) be stimulated. It beats watching TV. We will be happy to review your Proj3++ version, should you create one and to offer suggestions and advice on what to do to make an enhanced version.