CSCI E-70
Harvard University Extension School

Spring 2005

Java for Cellular User Applications

Assignment 3: Mini-project

2 Mar 2005 / Due 18 Mar 2005

A.  Reading

http://www.ibiblio.org/lifepatterns/october1970.html Original Sci. Amer. Article http://www.math.com/students/wonders/life/life.html Condensed introduction

http://www.ibiblio.org/lifepatterns/ Useful life links + fast AWT applet

Geary pp. 58-69 Swing threading

pp. 130-155 Animating/Double-buffering

Java Swing Tutorial Threads (intro; definition; essentials)

Threads and Swing

Animation (timers; animation; image rendering)

Mouse/MouseMotion event handling

Handed-out code Coordinates*.java, PointListener.java Custom application events

SimpleRunnable.java, UpdatingLabel.java Threading, timed auto-updating

B.  Questions

0.  Introduction

For this assignment you will be developing simulation application with fun visual animation. You are given significantly less structure and code than in previous assignments. Instead, we describe a specification of functionality and give recommendations for structure, along with a complete sample application handed out in class that exemplify the structural patterns we’re looking for. Our goal is to take substantial but digestible steps towards a production quality application.

1.  The Game of life

We all have to play it, so why not watch some artificial cells do it? You will be developing a “game of life” simulation, more formally known as a cellular automaton (SELL-you-ler ah-TOM-at-on). For some of you, this is a familiar leisure computer program you have played with in the past. If you have not seen it, there are many resources on the web that describe the rules, give demonstrations, and explain why simulating these cells are of theoretical interest. Google will take you right away to such sites. See above for a full introduction and tutorials, as well as links that delve into the obscure discoveries – the Game of Life, in Conway’s original form, is a mathematical planet for exploration unto itself!

The essential idea of a cellular automaton is to host a population of very simple cells based very loosely on the behavior cells of Earth-bound life itself. The universe is a fixed-size grid, usually square tiled, where each square on the grid can host one cell or be empty. Thus only two colors are required (“live”/“cell present” and “dead”/“cell not present”), plus gridlines in a third color. The class demonstration code uses two additional colors to display recent history (just born or just died). The simulation starts with an arbitrary, user-entered arrangement of live and dead cells. The simulation continues indefinitely by calculating the next generation based on the current generation, displaying that new generation, and repeating the process.

Generation n+1 is calculated entirely from generation n on a cell-by-cell basis as follows:

1. Calculate the neighbor count of a cell as it was in generation n. The neighbors include all eight surrounding cells. The count represents the number of neighboring cell locations that contain a live cell. (An empty cell location and a dead cell are synonymous)

2. Determine, strictly based on the count, if this cell should be alive or dead in generation n+1.

If there are one or fewer neighbors: cell remains dead if it was, or becomes dead if not

If there are exactly two neighbors: cell remains in its current state

If there are exactly three neighbors: cell stays alive if it was, or becomes alive if not

If there are more than three neighbors: cell dies of overcrowding, or remains dead if it was.

Ojo! Generation n+1 is calculated based entirely on the state of generation n. That is to say, as you work through a full pass on all the cells according to the rules above, you must base your neighbor counts on the cells as they were in generation n ; it is wrong to base them on a partially complete calculation of the current pass, i.e. generation n+1. Think about what that implies in your code and data structures.

Note the symmetry and simplicity of the rules. Note that also more possibilities than not cause the cell to die. This implies cell life, in the long run, is dispersed and stable in the simulated universe, rather than dense and constantly teeming. [But: only generally true; a few truly bizarre structures grow without bound, discovered in the ’90s!] However, the process towards stability is chaotic, and some would argue, beautiful. Out of simple patterns, complex turbulence, often with aesthetic appeal, appears and disappears at the apparent whim of the local cell life. The addition of a single cell can cause a stable (hibernation) pattern to become completely unstable and undergo drastic changes before re-stablizing.

2.  Your game of life

You be implementing the simulation described above. The simulation will occur in real time, necessitating the use of explicit persistent image buffering (in place of Swing’s default double buffering) and rendering, as well as an additional custom thread that uses real time. These concepts will be developed in the two classes before the assignment is due. Fret not too much; working demo code that isolates each of these concepts will be supplied. As usual, you are the system integrator and object designer.

The additional thread will pace the animation the by waking up periodically and propagating an event to cause a new generation calculation as well as a display update. You will be creating this new thread using the java.lang.Thread class and the java.lang.Runnable interface. You will also use Java’s time features, including access to the system clock and controlled sleep intervals.

The off-screen buffer will contain the entire visual grid so that every call to paint() does not force the rendering algorithm to re-run just because part of the window has been exposed. This is an important performance consideration if the user is manipulating his desktop frequently. The off-screen buffer will only be recalculated when it receives notification that all or part of the model has changed. Note this can happen as a result of the pacing thread or user editing.

3.  The working application: basic features

The program should present a graphical display of the simulation. This will be a rectangular grid of cells. The user should be able to specify the X and Y dimension of this grid. It is not acceptable to do this on the command line. You may find it helpful to start off the grid with a random collection of cells turned on. When the user is ready, she notifies the program using some GUI control to commence the simulation. At this point the display updates itself at a fixed, short interval (< 1 sec). At every interval the next generation is displayed on the grid. Two other meaningful, labeled statistics should be shown: the generation number and the elapsed real time. The user can stop the simulation at any time in which the cells retain the state of the most recent generation. After stopping and restarting, you need to decide whether to reset all numerical statistics, and if not, what control to add to allow the user to reset manually. The class demonstration also has “clear grid” and “randomize” buttons; while not required, you may find these useful to add as you build and debug anyway.

4.  Added feature (also required)

Get some practice with mouse event handling by allowing the user to kill or create new cells. You decide if the simulation must be stopped or not to allow this – and indicate to the user somehow when it is and is not allowed (status text?). You will need to make use of the MouseListener and MouseMotionListener interfaces. You can capture mouse click events and map them to the logical grid cell. From here, you can manipulate a cell grid data model. Make sure you allow for dragging as well as clicking – there are some tricky cases when dragging! – think: ‘How does the user control whether she is activating or de-activating a particular location?’

5.  Documentation: JavaDoc and UML diagrams

Write JavaDoc style comments for all interfaces, public methods, and final static data. These comments should be aimed at another implementer with the same Java GUI knowledge as yourself. This effort should amount to a formalization of the good commenting practices you’re already working on. See the javadoc reference Sun web pages for more information.

Include four UML diagrams to illustrate the structure of your code. Bare-bones box and pointer diagrams are all that’s needed. This should not take more than 5 hours total. Initial effort will save much development time later. Therefore, it is highly recommended to do this first, as it will lend important structure before you commence hacking code. It will also be tremendously helpful for us to review these diagrams with you as we guide you through the first week.

  1. A layout diagram showing the hierarchy of all the components and containers in your application, with an indication of all the layouts used.
  2. An inheritance diagram showing the relationship of all of your classes and interfaces, and their relationship to any Java classes/interfaces from which they are derived.
  3. An event (sequence) diagram like the ones shown in class that show the methods called, in order during a complete, non-trivial GUI transaction. The two possibilities are when the user clicks on a cell to toggle its status, or when the refresh thread wakes up to calculate and cause the display of a new generation.
  4. Pseudocode or a flowchart (whichever you prefer) explicating the algorithm to calculate the next generation of cell life in the grid given the current generation.

6.  Extra credit – up to 10%

(Extra credit won’t be considered fully if there are large problems or gaps in the basics such as OO design, good layout behavior, clear GUI controls, good code style, non-crashingness, and documentation; however, you need not have a perfect submission on the required features to make up points in Extra Credit. Essentially, don’t go bananas on cool extra features until you’re fairly sure all the basics under the covers and above are in good shape – our threshold is approximately at the 80% level on the required bits.)

  1. Use a non-rectangular tessellation such as interlocking triangles, hexagons, or a combination of other regular polygons. Hit detection is hard and will require support of Graphics2D regions.

b.  Allow the user to change between three or more alternative rule sets at any time. One of these alternatives can be the original rules. You will need a good abstract model to gain this flexibility without needing to change the simulation engine.

c.  Any algorithmic customization feature, since this is merely one in an infinitude of possible life rules. Give the user a simple GUI (combo-box?) to select different canned algorithms.

d.  Any other GUI customization feature, such as sliders, color choosers, and text entry fields to further control simulation behavior, such as speed, # of generations to simulate, color of live/dead cells...

– Page 4 of 3 –