3013 Project 2

Micro Pong

Due date: Monday, September 20th, by 11:59pm

Index


Overview

You can feel the tension in your neck as you furiously cram for your mid-term exams. Your eyes burn as you pore over pages of "required" reading, trying to soak up three weeks of material in one night. Your OS prof has been especially brutal, assigning scads of crap that only loosely tied into the class lectures. Ugh, you need a break, but you can't stand the thought of another slice of pizza or any more of your roommate's coffee. Then, suddenly, it hits you. Just the diversion you need ... a rousing game of Micro Pong!

This assignment is intended to introduce you to sharing data between processes with shared memory and synchronizing processes by using semaphores in the Unix operating system. You are to implement the program described below on any CCC Alpha machines (reno, bert, ernie, scooter, wpi ...)


Pong

You are to make a two player (one process per player) game of pong. Your pong game must be a typical pong game:

Here is a screen-shot of a possible game in action:

                           Billy: 8   Marky: 6

		|                                       |
		|                                       |
		|          =====                        |
		|                                       |
		|                                       |
		|                                       |
		|                                       |
		|                                       |
		|    *                                  |
		|                                       |
		|                                       |
		|                                       |
		|                                       |
		|                                       |
		|                                       |
		|                                       |
		|                                       |
		|                 =====                 |
		|                                       |
		|                                       |

                        j- left, k- right, space- stop

(You can try out the above game at: /cs/cs3013/pong)

You are free (and encouraged) to be creative with any of the game aspects, including speed, direction, paddle size, characters, keyboard controls, scoring ... you might try some of the suggested game "variations" below.


$&@#*! Curses

You will use the curses (actually, ncurses, a freeware implementation of the System V curses API with some clearly marked extensions) library to help with the text-based aspects of the program. The curses package is a subroutine library for terminal-independent screen-painting and input-event handling which presents a high-level screen model to the programmer, hiding differences between terminal types and doing automatic optimization of output to change one screen-full of text into another.

For this project, you will likely only need some basic functionality: how to create windows, refresh them, add characters and get input without waiting for a carriage return. The best way of learning curses is by following some examples:

In order to compile a program that uses curses you will need the -lncurses flag on the command line. Better yet, put it in a Makefile.

You should use the curses call:

       int nodelay(WINDOW *win, bool bf);
to make getch() a non-blocking call (you might try wgetch() if you are having difficulty making getch() non-blocking). In this case, if no input is ready, getch() returns ERR. If disabled (bf is FALSE), getch() then blocks until a key is pressed.

For more detailed information on curses you might try:


Shared Memory

Your pong game also must:

You will use shared memory as a means for users to share the game state information. You will use a semaphore (or more) to synchronize access to the shared game state by the two pong processes. The first pong process started will first try to attach to the shared memory (or semaphore), assuming the other pong program is already running. If the attach fails, however, pong will create the shared memory and semaphore and wait for the other pong to join the game by attaching.

Implementation of Unix semaphores and shared memory can be a bit ugly. To simplify use of shared memory and semaphores in this assignment, library routines to create and manipulate underlying Unix primitives have been provided. The source code containing these primitives is in shm.c. A header file containing prototype definitions for the routines is in shm.h. This makefile can be used to make your pong executable file by first building the shared memory library. You should download Makefile, shm.c and shm.h to your working directory. The routines provided in shm.c are:


/*
 * shmattach() - Attach to a shared memory segment with the given key. 
 *               Return NULL on failure.  
 */
void *shmattach(key_t key);

/*
 * shmcreate() - create the given amount of shared memory and return the 
 *	pointer to this memory.  Return NULL on failure.  We have imposed
 *	a limit of 2048 bytes for the total amount of shared memory created.
 */
void *shmcreate(key_t key, int cnt /* number of bytes */);

/*
 * shmdelete() - delete the shared memory associated with the given address.
 *	Return -1 on failure, zero on success.
 */
int shmdelete(void *sbShm);

/*
 * semattach() - attach to the semaphore indicated by key.  Return
 *             -1 if error.
 */
int semattach(key_t key);

/*
 * semcreate() - create a semaphore with the given initial count and the key.  
 *      Returns -1 on failure, a semaphore id on success.  
 */
int semcreate(key_t key, int cnt);

/*
 * semwait() - wait on the given semaphore.  Return -1 on error, zero on
 *	success.
 */
int semwait(int sem);

/*
 * semsignal() - signal the given semaphore.  Returns -1 on failure.
 */
int semsignal(int sem);

/*
 * semdelete() - delete the semaphore corresponding to the given sem id.  Returns
 *	-1 on failure, zero on success. 
 */
int semdelete(int sem);

/*
 * semcount() - return the count of the given sem id.  -1 on failure.
 */
int semcount(int sem);

Some simple samples showing how to use the above calls:


Signals

You will need to use Unix signals to handler timer interrupts and gracefully clean-up on a Ctrl-C. See the following samples:

Note, you must use the signal-alarm handler rather than usleep() or busy waiting, the latter will beat on the CPU.

See the samples section on the course web page for more signal samples.


Resource Cleanup

There is a fixed limit on the number of semaphores and shared memory segments that can be allocated on the system. These resources DO NOT automatically get cleaned up when a process exits abnormally. It is expected that your program will cleanup semaphore and shared memory segments that your program has allocated before it exits. To determine if your program terminates without cleaning up resources use the command ipcs. This command will list all message queues (not used in this project), shared memory, and semaphore resources that have been allocated. To cleanup your resources use the command ipcrm -m memid -s semid .... The following example illustrates use of these commands:

% ipcs
IPC status as of Thu Aug 29 19:52:24 1996
T     ID     KEY        MODE       OWNER    GROUP QBYTES
Message Queues:
T     ID     KEY        MODE       OWNER    GROUP SEGSZ
Shared Memory:
m   4224 0x278a0000 --rw-rw---- claypool    10122  1024
T     ID     KEY        MODE       OWNER    GROUP NSEMS
Semaphores:
s   2800 0x278a0000 --ra-ra----      cew    10122    15

% ipcrm -m 4224 -s 2800

% ipcs
IPC status as of Thu Aug 29 19:52:47 1996
T     ID     KEY        MODE       OWNER    GROUP QBYTES
Message Queues:
T     ID     KEY        MODE       OWNER    GROUP SEGSZ
Shared Memory:
T     ID     KEY        MODE       OWNER    GROUP NSEMS
Semaphores:

You might try the ipckill utility to aid you in removing these resources. Note, if someone wants to write a version of ipckill for Linux, I (and other Linux users) would greatly appreciate it.


Makefiles

A useful program for maintaining large programs that have been broken into many software modules is make. The program uses a file, usually named Makefile, that resides in the same directory as the source code. This file describes how to ``make'' a number of targets specified. To use, simply type "make" at the command line. WARNING: The operation line(s) for a target MUST begin with a TAB (do not use spaces). See the man page for make and gcc for additional information.

# 
# Makefile for pong program
#

CFLAGS = -g
LIBFLAGS = -lncurses

all: pong

pong: pong.c 
	gcc $(CFLAGS) pong.c shm.o -o pong $(LIBFLAGS)

shm.o: shm.c shm.h
	gcc -c shm.c

clean:
	/bin/rm -rf *.o core pong


Misc

Out of the number `7' (Ctrl-G) as a character will result in a beep on most terminals. Use it for simple sound effect enhancements!

Variations: To the basic pong described above, you might consider one or more of the below game variations:


Questions

Answer the following questions when you turn in your project:


Return to 3013 Home Page

Send all questions to the TA mailing list.