CS 51 Test Program # 2

Due: December 6th at 3:30 PM
(Design due: November 22nd, in class)

A test program is a laboratory that you complete on your own, without the help of others. It is a form of take-home exam. You may consult your text, your notes, your lab work, or our on-line examples and web pages, but use of any other source for code is forbidden. You may not discuss these problems with anyone aside from the course instructor. You may only ask the TA's for help with hardware problems or difficulties in retrieving your program from a disk or network.

This year is the 27th anniversary of the arcade game Pac-man. Pac-man was introduced in Japan in 1979 by Namco, Inc and then licensed to Midway and introduced in the U.S. the next year.

Those who would like to read a brief description of the history of this popular game (and find out why it isn't called Puck-man) might want to visit the Wikipedia article on Pac-Man. If you want to increase your familiarity with the official version of the game, you can find a working version on-line.

In case you haven't guessed, for your final test program we would like you to write a program that implements Pac-Man. Well, actually it might be more appropriate to describe what we want you to implement as proto-Pacman -- a game clearly related to Pac-Man but simplified in many ways to make the assignment more reasonable.

Our proto-Pacman game board is shown on the left. The basic game board is a maze of walls and passageways. Through these passageways will wander four colorful ghosts and "Pac-Man", a smiley face gone bad.

The ghosts travel down passageways moving ahead as long as there is only one path they can take. When a ghost reaches a cell in the maze where several passageways meet, it chooses among the passageways randomly (except that a ghost won't go back out using the passageway it just came from).

The player controls Pac-man's motion using the four arrow keys on the keyboard. When one of the buttons is pressed, Pac-Man begins moving in that direction if it is possible. (If there is a wall in the way, then the button press is ignored.) Once Pac-Man is moving in a particular direction, he keeps moving that way until he runs into a wall (in which case he just stops moving), or one of the other direction buttons is pressed.

Unfortunately for Pac-Man, the ghosts and Pac-Man exist in a predator-prey relationship. If any of the ghosts bump into Pac-Man, he perishes. In the arcade version, Pac-Man actually has several lives so that for one token a player gets to bump into at least three ghosts. Our game will only give Pac-Man one life. Bump into a ghost and the game is over.

The passageways initially contain little dots which Pac-Man appears to eat as he makes his way through the maze. In fact, the object of the game is to eat all the dots before bumping into any ghosts. Recognizing and announcing Pac-man's success (or failure) on the screen will earn you extra credit.

Some of the dots that were present in the arcade version of the game (the big ones) increase Pac-man's appetite so much that he can even eat ghosts. Since we won't have any big dots, this will never happen to your Pac-Man. Bumping into a ghost will always be fatal.

Implementation Details

XXXXXXXXXXXXXXXXXXX
X        X        X
X XX XXX X XXX XX X
X XX XXX X XXX XX X
X                 X
X XX X XXXXX X XX X
X    X   X   X    X
XXXX XXX X XXX XXXX
XXXX X       X XXXX
XXXX X XXXXX X XXXX
XXXX   XXXXX   XXXX
XXXX X XXXXX X XXXX
XXXX X       X XXXX
XXXX X XXXXX X XXXX
X        X        X
X XX XXX X XXX XX X
X  X           X  X
X  X X XXXXX X X  X
X    X   X   X    X
X XXXXXX X XXXXXX X
X                 X
XXXXXXXXXXXXXXXXXXX
To determine where the walls and passages within the maze are located, we will provide a text file containing a "map" of the maze. The file will contain one line for each row of the maze. Each line will contain one character for each column of the maze. Each cell corresponding to a wall will be represented by an "X". Each cell that is part of a passageway will be represented by a space. Thus, the "map" of the maze shown above looks like the text shown on the left. To represent this maze within your program, you should use a two-dimensional array. During its "begin" method, your program will read the lines from the file, draw the maze on the screen and store information describing the maze in the array. One nice feature of the maze we have constructed (which you can assume will be true of all mazes your program will ever see) is that the entire boundary is part of the wall. This means you never have to worry about a ghost or Pac-Man randomly walking outside the bounds of the board (like nibbles did) as long as you don't let things walk through walls. Rather than having a two-dimensional array of FilledRects, as was the case with Nibbles. Instead, it may be better to define a Cell class to represent the contents of a cell and use a two-dimensional array of Cells. The reason this may be better than

an array of FilledRects has to do with the fact that in this game a cell in the maze may be in one of three states (part of the wall, an unvisited passage cell, or a visited passage cell). If you use an array of FilledRects, you won't be able to simply test for "null". Both wall cells and visited passage cells will contain graphic objects. To tell them apart you would have to something like checking the color of the object. Alternately, if you define a Cell class, you can fill every element of the array with Cells and then include in the Cell class methods like "isWall", and "visit".

We will provide a Cell.java file in the starter folder, but will leave it to you to decide whether you find it simpler to use an array of Cells or an array of DrawbleInterface (recall that variables of type DrawableInterface can hold rectangles and ovals).

If you do use the Cell class then we suggest that each cell contain an instance variable of type DrawableInterface (to hold the graphics associated with the cell) and another variable (perhaps an int) that will represent information about the cell. For example 0 could represent an empty cell, 1 could represent an empty cell that has been visited, and 2 could represent a wall cell. These codes can make it fast and easy to determine what kind of cell it is while the game is running.

We will also provide you with predefined classes Position and Direction. The Position class is the same as the one used in Nibbles, while the Direction class has two extra features. First there is a new constant direction NONE, which may be useful for the beginning of the program when Pac-Man is not moving. It also has a new method:

    public Direction randomDirection()

which will be useful for helping the ghosts wander around at random.

Whether you use the Cell class or not, your program will involve the definition of four other classes:

Maze
The role of the Maze class will be similar to that of the NibbleField class from the Nibbles program, though it will likely be simpler if you make the array an array of Cells. It is responsible for keeping track of all of the cells in a two-dimensional array. It should also respond to requests asking if a position contains a wall, check to see if a cell has been visited (and erase its dot if it has not been). You will doubtless find a number of other methods that will be useful to have as part of the Maze class.

Ghost
The Ghost class will be an extension of ActiveObject that implements the random motion of the ghosts on the screen and the fatal interaction between ghosts and Pac-Man. We will provide a few ghostly images in files blueghost.gif, purpleghost.gif, redghost.gif, and yellowghost.gif. Like your Vehicles from the Frogger lab, the constructor for Ghosts will need to be passed the Pacman object as a parameter so that each Ghost can periodically send a message to Pac-Man to see if it has killed him. The Ghosts will also need to be passed the array that represents the maze so that they can figure out how to stay within the passages. When first created, a Ghost should randomly place itself in any cell that is not part of the maze wall. Although we would like to encourage you (with extra credit) to have your ghosts move smoothly between the cells of the maze (as ours do), the basic version of the program should be written so that ghosts (and Pac-Man) hop from cell to cell. There are two reasonable ways you could pick adjacent cells into which to move. You could first find all the adjacent passageway cells and then randomly pick one of them. Alternately, you could just repeatedly, randomly pick adjacent cells until you pick one that is not a wall and not the cell from which you arrived in your current cell. Note that ghosts are never allowed to reverse direction and go back where they just came from!

Pacman
The Pacman class will also be an extension of ActiveObject. Pac-Man will always start in row 12 and column 10, in a passageway just below the center of the board. Unlike the ghosts, Pac-man's motion will not be random, but instead will be guided by the user pushing the arrow keys. Pac-Man will also need to be passed the board as a parameter. It will use the board both to make sure that it stays in the passageways and to determine whether it has already visited a cell. The Pacman class will have to provide several methods so that it can respond to the direction buttons and to Ghosts who think they may have killed it.

PacmanController
The Controller for this program will have to input the maze description from a file named pacMaze and create the maze, and create the Pac-Man and Ghosts. It will also act as the listener for the arrow keys. My Pacman game runs in a window that is 475 by 650 pixels, though you may use other sizes if you like. The program uses a number of constants (many of which are pre-declared in the start-up code) to determine things like the size of the individual cells. If they are needed in other classes than the ones in which they are declared, you may make them public and refer to them as ClassName.aConst where ClassName is the name of the class where they are defined and aConst is the name of the constant. As always, instance variable will never be public.

The Design

As indicated in the heading of this document, you will need to turn in a design plan for your Pac-Man program well before the program itself. This design should be a clear and concise description of your planned organization of the program. Note that this design counts for 20% of your grade on the project, so take this requirement seriously.

Include in your design a sketch of each class (excluding Position and Direction) including the types and names of all instance variables you plan to use, and the headers of all methods you expect to write. You should write a brief description of the purpose/function of each instance variable and method. These should be sufficient to form the comments on each of these in your final program.

In addition, you should provide pseudo-code for any method whose implementation is at all complicated. In particular, if a method is complicated enough that it will invoke other methods you write (rather than just invoking methods provided by Java or our library), or involves a loop, then include pseudo-code for the method so that we will see how you expect to use your own methods.

Implementation Order

We strongly encourage you to proceed as suggested below to assure that you can turn in a running program. While a partial program will not receive full credit, a program that does not run at all generally receives a lower grade. Moreover it is easier to debug a program if you know that some parts do run correctly.

  1. Run the demonstration program.

  2. Write a program that reads the maze file and creates the maze from it. The maze file is named "pacMaze. This should result in a picture of the maze on the screen.

  3. Write enough of your Ghost class to make a ghost that can wander randomly without going through walls (don't worry about killing Pac-Man at this point). The ghosts should just hop from cell to cell without a smooth animation.

  4. Write a Pacman that pays attention to the arrow keys. Note that Pacman will continue in the same direction until it either runs into a wall (at which point it stops moving) or the user presses a key to move it in a new direction in which there is an empty cell.

  5. Add a method to Pac-Man and ghosts to allow the ghosts to try to kill Pac-Man.

  6. Add code to Pac-Man to make it erase the dot when it visits a cell for the first time.

  7. Add code to make sure that the ghosts and Pac-Man both stop moving if Pac-Man dies.

If you get stuck at an early stage of this project, please come see me. I can provide you with code for the early parts for a grade penalty. For example, if you cannot read in the board correctly, I can help you do that for a penalty of 5 points on the assignment.

Extensions

Since we have left out many of the features of the original Pac-man game, there are clearly many additional features you could add to your program. The base version of the program described above is worth a maximum of 90 points. We will award up to 20 points for extensions.

The version that I have running on line has several extra features that you may wish to add to your program. There are also several features from the original game that are not in the required portion of the game, but that will earn you extra points. Here are some suggestions for extra features:

Finally, let me emphasize that you will gain more points from writing really good, clear, well documented code than from adding any of these extensions. Make sure your base code is as good as you can make it (and that it works correctly) before moving on to extensions.

The Starter

As usual, I will provide a starter folder for this assignment. It is available on-line now.

Turning it in

Your design should be turned in on paper in class. Keep a copy for yourself since we will not be able to return them to you until after the last day of classes.

When your work is complete you should deposit in the dropoff folder a copy of the entire folder containing all of your files (check to make sure they are all there before you turn it in. Before you do this, make sure the folder name includes your name and the phrase "TP 2". Also make sure to double check your work for correctness, organization and style.

This program is due at 3:30 p.m. on December 6th, the last day of classes. While you may turn your program in late, you will be assessed a 10 point penalty for each day it is late. I.e., if you turn it in at 3:45 p.m. on December 6th, you will receive a 10 point penalty. If you turn it in at 3:45 p.m. on December 7th, you will receive a 20 point penalty, etc.

Grading Point Allocations

Value

Feature
Design preparation (20 pts total)
Syntax Style (15 pts total)
6 pts. Descriptive and helpful comments
2 pts. Good names
2 pts. Good use of constants
2 pts. Appropriate formatting
3 pts. Appropriate use of public/private
Semantic style (25 pts total)
5 pts. conditionals and loops
5 pts. General design/efficiency issues
5 pts. Parameters, variables, and scoping
5 pts. Good correct use of arrays
5 pts. Miscellaneous
Correctness (30 pts total)
5 pts. Board is drawn correctly
5 pts. Ghosts move correctly randomly on board
5 pts. Pac-Man moves correctly w/ key presses
5 pts. Ghosts can kill Pac-Man
5 pts. Pac-Man consumes dots
5 pts. Game ends correctly with Pac-Man succeeding or dying
Extensions (10 - 20 pts total)


Computer Science

051
Department of Computer Science
Pomona College