v05i010: Xchomp -- Pac-Man(tm) game for X Windows, Part01/03
Dan Heller
argv at island.uu.net
Sat Oct 14 05:39:13 AEST 1989
Submitted-by: Jerry Shekhel <eddie.mit.edu!polygen!jerry>
Posting-number: Volume 5, Issue 10
Archive-name: xchomp/part01
#! /bin/sh
# This is a shell archive. Remove anything before this line, then feed it
# into a shell via "sh file" or similar. To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix at uunet.uu.net if you want that tool.
# If this archive is complete, you will see the following message at the end:
# "End of archive 1 (of 3)."
# Contents: xchomp/Makefile xchomp/bitmaps xchomp/bitmaps/demo/
# xchomp/bitmaps/frame/ xchomp/bitmaps/fruit/
# xchomp/bitmaps/fruit/ff1.h xchomp/bitmaps/maze/
# xchomp/bitmaps/pac/ xchomp/contact.c xchomp/drivers.c
# xchomp/main.c xchomp/resources.c
# Wrapped by argv at island on Fri Oct 13 12:17:29 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
mkdir xchomp
if test -f 'xchomp/Makefile' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'xchomp/Makefile'\"
else
echo shar: Extracting \"'xchomp/Makefile'\" \(1002 characters\)
sed "s/^X//" >'xchomp/Makefile' <<'END_OF_FILE'
X
X#
X# MAKEFILE FOR XCHOMP
X#
X
X
X#
X# Add -DFRAME_DELAY=xxxxx to CFLAGS if the game runs too fast without it.
X# The "xxxxx" is the number of microseconds to wait between motion frames.
X#
X
XCFLAGS = -O
X
XCC = cc $(CFLAGS)
X
XOBJECTS = contact.o \
X demo.o \
X drivers.o \
X main.o \
X maze.o \
X props.o \
X resources.o \
X status.o
X
XBITMAPFILES = bitmaps/demo/*.h \
X bitmaps/frame/*.h \
X bitmaps/fruit/*.h \
X bitmaps/maze/*.h \
X bitmaps/pac/*.h
X
Xxchomp: $(OBJECTS)
X $(CC) -o xchomp $(OBJECTS) -lX11
X strip xchomp
X
Xcontact.o: contact.c xchomp.h
X $(CC) -c contact.c
X
Xdemo.o: demo.c xchomp.h
X $(CC) -c demo.c
X
Xdrivers.o: drivers.c xchomp.h
X $(CC) -c drivers.c
X
Xmain.o: main.c xchomp.h
X $(CC) -c main.c
X
Xmaze.o: maze.c xchomp.h
X $(CC) -c maze.c
X
Xprops.o: props.c xchomp.h
X $(CC) -c props.c
X
Xresources.o: resources.c xchomp.h bitmaps.h
X $(CC) -c resources.c
X
Xstatus.o: status.c xchomp.h
X $(CC) -c status.c
X
Xbitmaps.h: $(BITMAPFILES)
X cat $(BITMAPFILES) | sed '/^\#define/d' > bitmaps.h
END_OF_FILE
if test 1002 -ne `wc -c <'xchomp/Makefile'`; then
echo shar: \"'xchomp/Makefile'\" unpacked with wrong size!
fi
# end of 'xchomp/Makefile'
fi
if test ! -d 'xchomp/bitmaps' ; then
echo shar: Creating directory \"'xchomp/bitmaps'\"
mkdir 'xchomp/bitmaps'
fi
if test ! -d 'xchomp/bitmaps/demo/' ; then
echo shar: Creating directory \"'xchomp/bitmaps/demo/'\"
mkdir 'xchomp/bitmaps/demo/'
fi
if test ! -d 'xchomp/bitmaps/frame/' ; then
echo shar: Creating directory \"'xchomp/bitmaps/frame/'\"
mkdir 'xchomp/bitmaps/frame/'
fi
if test ! -d 'xchomp/bitmaps/fruit/' ; then
echo shar: Creating directory \"'xchomp/bitmaps/fruit/'\"
mkdir 'xchomp/bitmaps/fruit/'
fi
if test -f 'xchomp/bitmaps/fruit/ff1.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'xchomp/bitmaps/fruit/ff1.h'\"
else
echo shar: Extracting \"'xchomp/bitmaps/fruit/ff1.h'\" \(371 characters\)
sed "s/^X//" >'xchomp/bitmaps/fruit/ff1.h' <<'END_OF_FILE'
X#define ff1_width 20
X#define ff1_height 16
Xstatic char ff1_bits[] = {
X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x63, 0x00,
X 0xa0, 0x94, 0x00, 0xa0, 0x94, 0x00, 0xa0, 0x94, 0x00, 0xa0, 0x94, 0x00,
X 0xa0, 0x94, 0x00, 0xa0, 0x94, 0x00, 0xa0, 0x94, 0x00, 0x20, 0x63, 0x00,
X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
END_OF_FILE
if test 371 -ne `wc -c <'xchomp/bitmaps/fruit/ff1.h'`; then
echo shar: \"'xchomp/bitmaps/fruit/ff1.h'\" unpacked with wrong size!
fi
# end of 'xchomp/bitmaps/fruit/ff1.h'
fi
if test ! -d 'xchomp/bitmaps/maze/' ; then
echo shar: Creating directory \"'xchomp/bitmaps/maze/'\"
mkdir 'xchomp/bitmaps/maze/'
fi
if test ! -d 'xchomp/bitmaps/pac/' ; then
echo shar: Creating directory \"'xchomp/bitmaps/pac/'\"
mkdir 'xchomp/bitmaps/pac/'
fi
if test -f 'xchomp/contact.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'xchomp/contact.c'\"
else
echo shar: Extracting \"'xchomp/contact.c'\" \(5693 characters\)
sed "s/^X//" >'xchomp/contact.c' <<'END_OF_FILE'
X
X#include "xchomp.h"
X
X/*
X * This file contains player-ghost contact handling functions.
X * When a collision is detected, execution is vectored to one
X * of these functions, depending on the state of the ghost
X * with which the player collided.
X */
X
X
X/*
X * The following function is called when the player collides with
X * a solid ghost; the player dies. This is the death sequence.
X * The parameter to this function, as well as all of the collision
X * handling function, is the number (array index) of the ghost
X * with which the player collided. In this case, it doesn't matter.
X */
Xdie(dummy)
Xint dummy;
X{
X register int xx = x[PAC_SLOT], yy = y[PAC_SLOT], i, dx, dy;
X XImage *old, *new;
X
X /*
X * Since the player may be facing one of four directions at
X * the time of death, there would be way too many images for
X * me to draw in order to handle all possible cases. Therefore, I
X * only drew the images for the case in which the player is facing
X * left -- they are stored in dead_prot[]. The images for the
X * other cases are generated here, dynamically, by using the
X * Xlib image facilities. Since we can easily read and place
X * single pixels using images, we can rotate all the death frames
X * to the desired direction very easily. The final series of
X * bitmaps is stored in deadpac[].
X */
X new = XGetImage(display, dead_prot[1], 0, 0, GHOST_SIZE,
X GHOST_SIZE, 1, XYPixmap);
X for (i = 0; i < 11; i++) {
X old = XGetImage(display, dead_prot[i], 0, 0, GHOST_SIZE,
X GHOST_SIZE, 1, XYPixmap);
X for (dy = 0; dy < GHOST_SIZE; dy++)
X for (dx = 0; dx < GHOST_SIZE; dx++)
X if (pac == lpac)
X XPutPixel(new, dx, dy, XGetPixel(old, dx, dy));
X else if (pac == rpac)
X XPutPixel(new, dx, dy, XGetPixel(old, GHOST_SIZE - dx - 1, dy));
X else if (pac == dpac)
X XPutPixel(new, dx, dy, XGetPixel(old, GHOST_SIZE - dy - 1, dx));
X else
X XPutPixel(new, dx, dy, XGetPixel(old, dy, dx));
X XPutImage(display, deadpac[i], bitmapGC, new, 0, 0, 0, 0,
X GHOST_SIZE, GHOST_SIZE);
X XDestroyImage(old);
X }
X XDestroyImage(new);
X sleep(1);
X
X /* deactivate the fruit (if displayed) */
X if (fruit_shown) {
X XFillRectangle(display, save, clearGC, fruit_x - 2, fruit_y,
X FRUIT_WIDTH, FRUIT_HEIGHT);
X dd[fruit_y >> 4][fruit_x >> 4] = '\0';
X ++fruit_times;
X fruit_shown = False;
X }
X
X /*
X * Now we'll get rid of all of the ghosts on the screen,
X * and display the first frame of the death animation at the
X * position of the player.
X */
X XCopyArea(display, save, map, fullcopyGC, 0, 0, WIN_WIDTH,
X WIN_HEIGHT, 0, 0);
X XCopyPlane(display, deadpac[0], map, orGC, 0, 0, GHOST_SIZE,
X GHOST_SIZE, xx, yy, 1);
X XCopyArea(display, map, window, fullcopyGC, 0, 0, WIN_WIDTH,
X WIN_HEIGHT, 0, 0);
X XSync(display, False);
X sleep(1);
X
X /*
X * Now we'll cycle through the death animation frames using
X * our normal animation mechanism.
X */
X for (i = 0; i < 11; i++) {
X XCopyArea(display, save, map, fullcopyGC, xx, yy, GHOST_SIZE,
X GHOST_SIZE, xx, yy);
X XCopyPlane(display, deadpac[i], map, orGC, 0, 0, GHOST_SIZE,
X GHOST_SIZE, xx, yy, 1);
X XCopyArea(display, map, window, fullcopyGC, xx, yy, GHOST_SIZE,
X GHOST_SIZE, xx, yy);
X XSync(display, False);
X usleep(125000);
X }
X usleep(150000);
X
X /*
X * Now we'll remove everything except the maze from the
X * screen, and return.
X */
X XCopyArea(display, save, map, fullcopyGC, xx, yy, GHOST_SIZE,
X GHOST_SIZE, xx, yy);
X XCopyArea(display, map, window, fullcopyGC, xx, yy, GHOST_SIZE,
X GHOST_SIZE, xx, yy);
X XSync(display, False);
X dead = True;
X}
X
X
X/*
X * The following function is executed when the player collides
X * with a transparent or flashing ghost; the player eats the
X * ghost. The game pauses for a moment, displaying the value
X * of the eaten ghost, and then continues. The parameter is
X * the array index of the eaten ghost.
X */
Xeat(i)
Xint i;
X{
X register int xx = x[PAC_SLOT], yy = y[PAC_SLOT], j;
X static long val[] = { 200, 400, 800, 1600 };
X
X /*
X * The image we want to create here is the following: all of
X * the ghosts except the one being eaten are drawn, as well as
X * the score value of the eaten ghost in the position of the
X * player. We'll use the normal method: first create the image
X * on the map, and then copy the selected areas of the map onto
X * the window. The "copyGC" graphics context, at this point,
X * should contain the necessary clipping information.
X */
X for (j = 0; j < PAC_SLOT; j++)
X if (j != i)
X XCopyPlane(display, ghost[j][count], map, orGC, 0, 0,
X GHOST_SIZE, GHOST_SIZE, x[j], y[j], 1);
X XCopyPlane(display, eat_pix[eat_index], map, orGC, 0, 0,
X GHOST_SIZE, GHOST_SIZE, xx, yy, 1);
X XCopyArea(display, map, window, copyGC, 0, 0, WIN_WIDTH,
X WIN_HEIGHT, 0, 0);
X
X /* adjust the score and wait a second */
X print_score(val[eat_index]);
X eat_index = (eat_index + 1) & 0x03;
X XSync(display, False);
X sleep(1);
X
X /* remove all moving figures from the map */
X XCopyArea(display, save, map, copyGC, 0, 0, WIN_WIDTH,
X WIN_HEIGHT, 0, 0);
X
X /*
X * Now we'll change the ghost state, so that it appears
X * as a pair of harmless eyes seeking return to the ghost
X * box.
X */
X ghost[i] = eghost;
X drive[i] = go_home;
X contact[i] = noop;
X}
X
X
X/*
X * The following is the collision handler for ghost-eyes.
X * The eyes are harmless; this is a no-op.
X */
Xnoop(dummy)
Xint dummy;
X{
X}
X
END_OF_FILE
if test 5693 -ne `wc -c <'xchomp/contact.c'`; then
echo shar: \"'xchomp/contact.c'\" unpacked with wrong size!
fi
# end of 'xchomp/contact.c'
fi
if test -f 'xchomp/drivers.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'xchomp/drivers.c'\"
else
echo shar: Extracting \"'xchomp/drivers.c'\" \(20425 characters\)
sed "s/^X//" >'xchomp/drivers.c' <<'END_OF_FILE'
X
X#include "xchomp.h"
X
X/*
X * This file contains functions which control the motion of the player
X * and the ghosts.
X */
X
X
X/*
X * The following function is called explicitly during each animation
X * cycle, to control the motion of the player. It updates the position
X * variables (x[], y[]), the direction variables (ix[], iy[]), and the
X * array of clipping rectangles (rectangle[]).
X */
Xcontrol_pac()
X{
X register int xx = x[PAC_SLOT], yy = y[PAC_SLOT], i, dx, dy;
X register char *pc = md[yy >> 4] + (xx >> 4);
X register int *px = ix + PAC_SLOT, *py = iy + PAC_SLOT;
X
X /* check for a collision */
X for (i = 0; i < PAC_SLOT; i++) {
X dx = x[i] - xx;
X dy = y[i] - yy;
X if ((abs(dx) < 6) && (abs(dy) < 6))
X (*contact[i])(i);
X if (dead) return;
X }
X
X /*
X * The rest of this function determines the direction of the
X * player according to the surroundings and the last key pressed
X * by the user. This took a while to implement correctly, and I
X * don't quite recall all of the reasoning that went into the
X * implementation of this code.
X */
X
X if (!(xx & 0x0f) && !(yy & 0x0f)) {
X if (*px > 0) {
X if (pc[1]) *px = 0;
X }
X else if (*px < 0) {
X if (pc[-1]) *px = 0;
X }
X else if (*py < 0) {
X if (pc[-BLOCK_WIDTH]) *py = 0;
X }
X else if (pc[BLOCK_WIDTH]) *py = 0;
X switch (last_key) {
X case XK_Up:
X if (!pc[-BLOCK_WIDTH]) *py = (-2), *px = 0, pac = upac;
X break;
X case XK_Down:
X if (!pc[BLOCK_WIDTH]) *py = 2, *px = 0, pac = dpac;
X break;
X case XK_Left:
X if (!pc[-1]) *px = (-2), *py = 0, pac = lpac;
X break;
X case XK_Right:
X if (!pc[1]) *px = 2, *py = 0, pac = rpac;
X break;
X default: break;
X }
X check_dots();
X rectangle[PAC_SLOT].x = (x[PAC_SLOT] += *px) - 2;
X rectangle[PAC_SLOT].y = (y[PAC_SLOT] += *py) - 2;
X return;
X }
X
X if (*px > 0) {
X if (last_key == XK_Left)
X *px = (-2), pac = lpac;
X }
X else if (*px < 0) {
X if (last_key == XK_Right)
X *px = 2, pac = rpac;
X }
X else if (*py > 0) {
X if (last_key == XK_Up)
X *py = (-2), pac = upac;
X }
X else if (last_key == XK_Down)
X *py = 2, pac = dpac;
X rectangle[PAC_SLOT].x = (x[PAC_SLOT] += *px) - 2;
X rectangle[PAC_SLOT].y = (y[PAC_SLOT] += *py) - 2;
X}
X
X
X/*
X * The following function checks to see whether the player has
X * eaten something which is not a ghost -- a dot, a power-dot,
X * or the fruit. If so, the appropriate action is taken.
X */
Xcheck_dots()
X{
X register char *pi;
X register int i;
X register funcptr driver;
X static long fval[] = { 100, 200, 300, 300, 500, 700, 700,
X 1000, 1000, 2000, 2000, 3000, 3000,
X 5000 };
X
X /*
X * The following line produces a pointer to the character in the
X * dot information array (dd[]) which corresponds to the player's
X * position on the screen.
X */
X pi = dd[y[PAC_SLOT] >> 4] + (x[PAC_SLOT] >> 4);
X
X /* check for a regular dot */
X if (*pi == '.') {
X *pi = '\0';
X
X /* erase the dot from the background image */
X XFillRectangle(display, save, clearGC, x[PAC_SLOT] + 6,
X y[PAC_SLOT] + 6, 4, 4);
X print_score(10L);
X if (--numdots == 0) {
X completed = True;
X return;
X }
X }
X
X /* check for a power-dot */
X else if (*pi == 'O') {
X *pi = '\0';
X
X /*
X * Here we'll erase the power-dot from both the power-dot
X * map and the background map, so that it no longer flashes.
X */
X XFillRectangle(display, powermap, clearGC, x[PAC_SLOT],
X y[PAC_SLOT], GHOST_SIZE, GHOST_SIZE);
X XCopyArea(display, powermap, save, fullcopyGC, x[PAC_SLOT],
X y[PAC_SLOT], GHOST_SIZE, GHOST_SIZE, x[PAC_SLOT], y[PAC_SLOT]);
X print_score(50L);
X if (--numdots == 0) {
X completed = True;
X return;
X }
X
X /* set up ghost-eating mode */
X eat_index = 0;
X eat_mode = True;
X grey_tick = 0;
X count_sync = count;
X
X /*
X * Change the state of each solid ghost to that of a white
X * ghost running away from the player at half speed.
X */
X for (i = 0; i < PAC_SLOT; i++) {
X if ((driver = drive[i]) == follow) {
X drive[i] = run;
X contact[i] = eat;
X ghost[i] = gghost;
X ix[i] = -ix[i] / 2;
X iy[i] = -iy[i] / 2;
X }
X else if (driver == hover) {
X drive[i] = hover2;
X contact[i] = eat;
X ghost[i] = gghost;
X ix[i] /= 2;
X iy[i] /= 2;
X }
X else if ((driver == hover2) || (driver == run))
X ghost[i] = gghost;
X }
X }
X
X /* check for the fruit */
X else if (*pi == 'F') {
X *pi = '\0';
X print_score(fval[plevel]);
X
X /*
X * We have to do some fancy stuff here. We want to instantly
X * change the fruit on the screen to the image of a score value,
X * without stopping the game (as with ghost eating). The problem
X * is that this subroutine is called AFTER the background image has
X * been restored onto the map in the game loop, and therefore, AFTER
X * the clipping information has been set for the pending screen
X * update. Therefore, we have to copy this image onto BOTH off-
X * screen maps, and we have to reset the clipping information here,
X * so that the image is displayed on the screen immediately. This
X * would not be a problem if the score value images were the same
X * size as the player, as in the case of dots and power-dots.
X */
X XCopyPlane(display, fval_pix[plevel], save, fullcopyGC,
X 0, 0, FRUIT_WIDTH, FRUIT_HEIGHT, fruit_x - 2, fruit_y, 1);
X XCopyArea(display, save, map, fullcopyGC, fruit_x - 2,
X fruit_y, FRUIT_WIDTH, FRUIT_HEIGHT, fruit_x - 2, fruit_y);
X XSetClipRectangles(display, copyGC, 0, 0, rectangle,
X NUM_FIGURES + MAX_POWER_DOTS + 1, Unsorted);
X
X /*
X * Now we'll set the fruit frame counter to 43. The main loop will
X * clear the fruit area when it is at 50, so the fruit score value
X * will disappear nicely in a few seconds.
X */
X fruit_count = 43;
X }
X}
X
X
X/*-- GHOST DRIVERS -----------------------------------------------------*/
X
X
X/*
X * The rest of this file contains ghost drivers. These routines are invoked
X * through pointers, to control the motion of the ghosts. There are several
X * of these routines, corresponding to the several different ghost states.
X * The parameter to each of these is the ghost number (array index) for which
X * to update the direction arrays (ix[], iy[]).
X */
X
X
X/*
X * The function below causes ghosts to follow the player around, with a bit
X * of randomness thrown in as well.
X */
Xfollow(i)
Xregister int i;
X{
X register char *pc = md[y[i] >> 4] + (x[i] >> 4);
X register int dir = 0x0f, sense;
X register int *px = ix + i, *py = iy + i;
X int xx = x[i], yy = y[i], pmx = x[PAC_SLOT], pmy = y[PAC_SLOT];
X static intm find[3] = { { 0, 1, 2 }, { 3, 3, 4 }, { 5, 6, 7 } };
X
X static intm fxvec[16] = {
X { 0, 0, 0, 0, 0, 0, 0, 0 }, /* no way to go */
X { 2, 2, 2, 2, 2, 2, 2, 2 }, /* right only */
X { -2, -2, -2, -2, -2, -2, -2, -2 }, /* left only */
X { -2, 2, 2, -2, 2, -2, -2, 2 }, /* left or right */
X { 0, 0, 0, 0, 0, 0, 0, 0 }, /* down only */
X { 2, 2, 2, 0, 2, 0, 0, 2 }, /* down or right */
X { -2, -2, -2, -2, 0, 0, 0, 0 }, /* down or left */
X { -2, -2, 2, -2, 2, -2, 0, 0 }, /* down, left, or right */
X { 0, 0, 0, 0, 0, 0, 0, 0 }, /* up only */
X { 0, 0, 0, 0, 2, 2, 2, 2 }, /* up or right */
X { -2, 0, 0, -2, 0, -2, -2, -2 }, /* up or left */
X { 0, 0, 2, -2, 2, -2, -2, 2 }, /* up, left, or right */
X { 0, 0, 0, 0, 0, 0, 0, 0 }, /* up or down */
X { 0, 0, 2, 0, 2, 0, 0, 2 }, /* up, down, or right */
X { -2, 0, 0, -2, 0, 0, 0, 0 }, /* up, down, or left */
X { -2, 0, 0, -2, 2, 0, 0, 2 } }; /* any which way */
X
X static intm fyvec[16] = {
X { 0, 0, 0, 0, 0, 0, 0, 0 }, /* no way to go */
X { 0, 0, 0, 0, 0, 0, 0, 0 }, /* right only */
X { 0, 0, 0, 0, 0, 0, 0, 0 }, /* left only */
X { 0, 0, 0, 0, 0, 0, 0, 0 }, /* left or right */
X { 2, 2, 2, 2, 2, 2, 2, 2 }, /* down only */
X { 0, 0, 0, 2, 0, 2, 2, 0 }, /* down or right */
X { 0, 0, 0, 0, 2, 2, 2, 2 }, /* down or left */
X { 0, 0, 0, 0, 0, 0, 2, 2 }, /* down, left, or right */
X { -2, -2, -2, -2, -2, -2, -2, -2 }, /* up only */
X { -2, -2, -2, -2, 0, 0, 0, 0 }, /* up or right */
X { 0, -2, -2, 0, -2, 0, 0, 0 }, /* up or left */
X { -2, -2, 0, 0, 0, 0, 0, 0 }, /* up, left, or right */
X { -2, -2, -2, -2, 2, 2, 2, 2 }, /* up or down */
X { -2, -2, 0, 2, 0, 2, 2, 0 }, /* up, down, or right */
X { 0, -2, -2, 0, -2, 2, 2, 2 }, /* up, down, or left */
X { 0, -2, -2, 0, 0, 2, 2, 0 } }; /* any which way */
X
X /* first, find the directions in which this ghost can go */
X if (pc[1] || (*px < 0)) dir &= ~0x01;
X if (pc[-1] || (*px > 0)) dir &= ~0x02;
X if (pc[BLOCK_WIDTH] || (*py < 0)) dir &= ~0x04;
X if (pc[-BLOCK_WIDTH] || (*py > 0)) dir &= ~0x08;
X
X /* now choose the new direction for the ghost */
X if ((dir != 0x01) && (dir != 0x02) && (dir != 0x04) && (dir != 0x08)) {
X if ((random() & 0x0f) > 4)
X sense = find[sgn(pmy - yy) + 1][sgn(pmx - xx) + 1];
X else sense = random() & 0x07;
X *px = fxvec[dir][sense];
X *py = fyvec[dir][sense];
X }
X else {
X *px = *fxvec[dir];
X *py = *fyvec[dir];
X }
X}
X
X
X/*
X * The function below causes ghosts to run away from the player
X * at half speed. It is set up as the driver function during
X * the ghost-eating periods of the game.
X */
Xrun(i)
Xregister int i;
X{
X register char *pc = md[y[i] >> 4] + (x[i] >> 4);
X register int dir = 0x0f, sense;
X register int *px = ix + i, *py = iy + i;
X int xx = x[i], yy = y[i], pmx = x[PAC_SLOT], pmy = y[PAC_SLOT];
X static intm find[3] = { { 0, 1, 2 }, { 3, 3, 4 }, { 5, 6, 7 } };
X
X static intm rxvec[16] = {
X { 0, 0, 0, 0, 0, 0, 0, 0 }, /* no way to go */
X { 1, 1, 1, 1, 1, 1, 1, 1 }, /* right only */
X { -1, -1, -1, -1, -1, -1, -1, -1 }, /* left only */
X { 1, -1, -1, 1, -1, 1, 1, -1 }, /* left or right */
X { 0, 0, 0, 0, 0, 0, 0, 0 }, /* down only */
X { 0, 1, 0, 0, 0, 1, 1, 0 }, /* down or right */
X { 0, -1, -1, 0, 0, 0, -1, -1 }, /* down or left */
X { 1, 1, -1, 0, 0, 1, 1, -1 }, /* down, left, or right */
X { 0, 0, 0, 0, 0, 0, 0, 0 }, /* up only */
X { 1, 1, 0, 0, 0, 1, 1, 0 }, /* up or right */
X { 0, -1, -1, 0, 0, 0, -1, -1 }, /* up or left */
X { 1, -1, -1, 0, 0, 0, -1, -1 }, /* up, left, or right */
X { 0, 0, 0, 0, 0, 0, 0, 0 }, /* up or down */
X { 0, 1, 0, 0, 0, 1, 1, 0 }, /* up, down, or right */
X { 0, -1, -1, 0, 0, 0, -1, -1 }, /* up, down, or left */
X { 1, -1, 0, 0, 0, 0, 1, -1 } }; /* any which way */
X
X static intm ryvec[16] = {
X { 0, 0, 0, 0, 0, 0, 0, 0 }, /* no way to go */
X { 0, 0, 0, 0, 0, 0, 0, 0 }, /* right only */
X { 0, 0, 0, 0, 0, 0, 0, 0 }, /* left only */
X { 0, 0, 0, 0, 0, 0, 0, 0 }, /* left or right */
X { 1, 1, 1, 1, 1, 1, 1, 1 }, /* down only */
X { 1, 0, 1, 1, 1, 0, 0, 1 }, /* down or right */
X { 1, 0, 0, 1, 1, 1, 0, 0 }, /* down or left */
X { 0, 0, 0, 1, 1, 0, 0, 0 }, /* down, left, or right */
X { -1, -1, -1, -1, -1, -1, -1, -1 }, /* up only */
X { 0, 0, -1, -1, -1, 0, 0, -1 }, /* up or right */
X { -1, 0, 0, -1, -1, -1, 0, 0 }, /* up or left */
X { 0, 0, 0, -1, -1, -1, 0, 0 }, /* up, left, or right */
X { 1, 1, 1, 1, -1, -1, -1, -1 }, /* up or down */
X { 1, 0, 1, 1, -1, 0, 0, -1 }, /* up, down, or right */
X { 1, 0, 0, -1, 1, -1, 0, 0 }, /* up, down, or left */
X { 0, 0, 1, 1, -1, -1, 0, 0 } }; /* any which way */
X
X /* first, find the directions in which this ghost can go */
X if (pc[1] || (*px < 0)) dir &= ~0x01;
X if (pc[-1] || (*px > 0)) dir &= ~0x02;
X if (pc[BLOCK_WIDTH] || (*py < 0)) dir &= ~0x04;
X if (pc[-BLOCK_WIDTH] || (*py > 0)) dir &= ~0x08;
X
X /* now choose the new direction for the ghost */
X if ((dir != 0x01) && (dir != 0x02) && (dir != 0x04) && (dir != 0x08)) {
X sense = find[sgn(pmy - yy) + 1][sgn(pmx - xx) + 1];
X *px = rxvec[dir][sense];
X *py = ryvec[dir][sense];
X }
X else {
X *px = *rxvec[dir];
X *py = *ryvec[dir];
X }
X}
X
X
X/*
X * The function below causes ghosts to return to the ghost box at
X * high speed. It is set up as the driver for ghosts which have
X * been eaten.
X */
Xgo_home(i)
Xregister int i;
X{
X register char *pc = md[y[i] >> 4] + (x[i] >> 4);
X register int dir = 0x0f, sense;
X register int *px = ix + i, *py = iy + i;
X int xx = x[i], yy = y[i], pmx = door_x << 4, pmy = (door_y - 1) << 4;
X static intm find[3] = { { 0, 1, 2 }, { 3, 3, 4 }, { 5, 6, 7 } };
X
X static intm pxvec[16] = {
X { 0, 0, 0, 0, 0, 0, 0, 0 }, /* no way to go */
X { 4, 4, 4, 4, 4, 4, 4, 4 }, /* right only */
X { -4, -4, -4, -4, -4, -4, -4, -4 }, /* left only */
X { -4, 4, 4, -4, 4, -4, -4, 4 }, /* left or right */
X { 0, 0, 0, 0, 0, 0, 0, 0 }, /* down only */
X { 4, 4, 4, 0, 4, 0, 0, 4 }, /* down or right */
X { -4, -4, -4, -4, 0, 0, 0, 0 }, /* down or left */
X { -4, -4, 4, -4, 4, -4, 0, 0 }, /* down, left, or right */
X { 0, 0, 0, 0, 0, 0, 0, 0 }, /* up only */
X { 0, 0, 0, 0, 4, 4, 4, 4 }, /* up or right */
X { -4, 0, 0, -4, 0, -4, -4, -4 }, /* up or left */
X { 0, 0, 4, -4, 4, -4, -4, 4 }, /* up, left, or right */
X { 0, 0, 0, 0, 0, 0, 0, 0 }, /* up or down */
X { 0, 0, 4, 0, 4, 0, 0, 4 }, /* up, down, or right */
X { -4, 0, 0, -4, 0, 0, 0, 0 }, /* up, down, or left */
X { -4, 0, 0, -4, 4, 0, 0, 4 } }; /* any which way */
X
X static intm pyvec[16] = {
X { 0, 0, 0, 0, 0, 0, 0, 0 }, /* no way to go */
X { 0, 0, 0, 0, 0, 0, 0, 0 }, /* right only */
X { 0, 0, 0, 0, 0, 0, 0, 0 }, /* left only */
X { 0, 0, 0, 0, 0, 0, 0, 0 }, /* left or right */
X { 4, 4, 4, 4, 4, 4, 4, 4 }, /* down only */
X { 0, 0, 0, 4, 0, 4, 4, 0 }, /* down or right */
X { 0, 0, 0, 0, 4, 4, 4, 4 }, /* down or left */
X { 0, 0, 0, 0, 0, 0, 4, 4 }, /* down, left, or right */
X { -4, -4, -4, -4, -4, -4, -4, -4 }, /* up only */
X { -4, -4, -4, -4, 0, 0, 0, 0 }, /* up or right */
X { 0, -4, -4, 0, -4, 0, 0, 0 }, /* up or left */
X { -4, -4, 0, 0, 0, 0, 0, 0 }, /* up, left, or right */
X { -4, -4, -4, -4, 4, 4, 4, 4 }, /* up or down */
X { -4, -4, 0, 4, 0, 4, 4, 0 }, /* up, down, or right */
X { 0, -4, -4, 0, -4, 4, 4, 4 }, /* up, down, or left */
X { 0, -4, -4, 0, 0, 4, 4, 0 } }; /* any which way */
X
X if (xx == pmx) {
X if (yy == pmy) {
X
X /*
X * The ghost is right above the door to the ghost box.
X * We'll send it down into the box. We're assuming
X * here that the ghost box is shaped a certain way.
X * If not, the results will be unpredictable.
X */
X *px = 0;
X *py = 4;
X return;
X }
X else if (yy == (pmy + 48)) {
X
X /*
X * The ghost is all the way inside the box. Here it'll
X * be "reborn" -- its state will be changed to that of a
X * solid ghost hovering inside the ghost box.
X */
X drive[i] = hover;
X loops[i] = 0;
X ghost[i] = bghost;
X contact[i] = die;
X *px = 2;
X *py = 0;
X return;
X }
X }
X else {
X
X /* otherwise, find the directions in which this ghost can go */
X if (pc[1] || (*px < 0)) dir &= ~0x01;
X if (pc[-1] || (*px > 0)) dir &= ~0x02;
X if (pc[BLOCK_WIDTH] || (*py < 0)) dir &= ~0x04;
X if (pc[-BLOCK_WIDTH] || (*py > 0)) dir &= ~0x08;
X
X /* now choose the new direction for the ghost */
X if ((dir != 0x01) && (dir != 0x02) && (dir != 0x04) && (dir != 0x08)) {
X sense = find[sgn(pmy - yy) + 1][sgn(pmx - xx) + 1];
X *px = pxvec[dir][sense];
X *py = pyvec[dir][sense];
X }
X else {
X *px = *pxvec[dir];
X *py = *pyvec[dir];
X }
X }
X}
X
X
X/*
X * The function below drives the solid ghosts inside the ghost box.
X * They simply hover around in a circular pattern. Randomness is
X * used to decide when the ghosts leave the box.
X */
Xhover(i)
Xregister int i;
X{
X register int yy = y[i] >> 4, xx = x[i] >> 4;
X char *pc = md[yy] + xx;
X register int *px = ix + i, *py = iy + i;
X
X if (xx == door_x)
X if (yy == (door_y - 1)) {
X
X /*
X * The ghost is now completely outside the box; we will
X * change its driver so that it follows the player around
X */
X drive[i] = follow;
X follow(i);
X return;
X }
X else if (yy == (door_y + 1))
X
X /*
X * The ghost is directly underneath the door to the
X * outside. We'll use the number of loops it has made
X * inside the box, as well as a bit of randomness,
X * to determine whether or not to send it out.
X */
X if ((++loops[i]) > 1)
X if ((random() & 0x0f) > 7) {
X *px = 0, *py = (-2);
X return;
X }
X
X /*
X * The rest of the function drives the ghost around the
X * box in a circular counterclockwise pattern.
X */
X if (*px > 0) {
X if (pc[1]) *px = 0, *py = (-2);
X }
X else if (*px < 0) {
X if (pc[-1]) *px = 0, *py = 2;
X }
X else if (*py > 0) {
X if (pc[BLOCK_WIDTH]) *px = 2, *py = 0;
X }
X else if (pc[-BLOCK_WIDTH]) *px = (-2), *py = 0;
X}
X
X
X/*
X * The function below is just like hover() above, except that
X * it handles the motion of ghosts inside the box during
X * the ghost-eating periods of the game -- they move at half
X * speed.
X */
Xhover2(i)
Xregister int i;
X{
X register int yy = y[i] >> 4, xx = x[i] >> 4;
X char *pc = md[yy] + xx;
X register int *px = ix + i, *py = iy + i;
X
X if (xx == door_x)
X if (yy == (door_y - 1)) {
X drive[i] = run;
X run(i);
X return;
X }
X else if (yy == (door_y + 1))
X if ((++loops[i]) > 1) {
X *px = 0, *py = (-1);
X return;
X }
X
X if (*px > 0) {
X if (pc[1]) *px = 0, *py = (-1);
X }
X else if (*px < 0) {
X if (pc[-1]) *px = 0, *py = 1;
X }
X else if (*py > 0) {
X if (pc[BLOCK_WIDTH]) *px = 1, *py = 0;
X }
X else if (pc[-BLOCK_WIDTH]) *px = (-1), *py = 0;
X}
END_OF_FILE
if test 20425 -ne `wc -c <'xchomp/drivers.c'`; then
echo shar: \"'xchomp/drivers.c'\" unpacked with wrong size!
fi
# end of 'xchomp/drivers.c'
fi
if test -f 'xchomp/main.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'xchomp/main.c'\"
else
echo shar: Extracting \"'xchomp/main.c'\" \(8900 characters\)
sed "s/^X//" >'xchomp/main.c' <<'END_OF_FILE'
X
X#define EXTERN
X#include "xchomp.h"
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X XEvent event;
X int dummy;
X XCharStruct chars;
X unsigned long event_mask;
X
X /* open the display */
X display = XOpenDisplay(NULL);
X screen = DefaultScreen(display);
X root = DefaultRootWindow(display);
X depth = DefaultDepth(display, screen);
X black = BlackPixel(display, screen);
X white = WhitePixel(display, screen);
X
X /* get a font */
X font = XLoadFont(display, "fixed");
X XQueryTextExtents(display, font, "000000", 6, &dummy,
X &ascent, &descent, &chars);
X
X /*
X * We want to suspend the game in case the window is iconified.
X * This is more difficult than it sounds. On the Sun, iconification
X * seems to produce an UnmapNotify event -- very nice. DECwindows,
X * however, informs the application by generating a PropertyNotify
X * event on a DEC-specific property -- very nasty. The atom is
X * not defined in any of the DECwindows headers, so we will try
X * to get its value from the server, and use it later. We are
X * hoping here that all non-DECwindows servers will return None
X * for this atom.
X */
X DEC_icon_atom = XInternAtom(display, "DEC_WM_ICON_STATE", True);
X
X /* assemble resources */
X create_ghost();
X create_pac();
X create_fruit();
X create_maze_symbols();
X create_demo_images();
X create_window(argc, argv);
X create_GCs();
X create_maps();
X
X /* select the event mask for the window */
X event_mask = ExposureMask | KeyPressMask;
X if (DEC_icon_atom == None)
X event_mask |= StructureNotifyMask;
X else event_mask |= PropertyChangeMask;
X XSelectInput(display, window, event_mask);
X
X /* display the window */
X XMapWindow(display, window);
X while (True) {
X XNextEvent(display, &event);
X if (event.xany.window != window) continue;
X if (event.type == Expose) break;
X }
X
X /*-- The Game Starts Here -----------------------------------------*/
X {
X register int i, num_clips;
X char c_buf;
X XComposeStatus status;
X
X static int flash_ticks[] = {
X 13, 8, 4, 1, 13, 8, 4, 1,
X 8, 4, 1, 4, 1, 8, 4, 1,
X 0, 0, 8, 4, 0, 0, 1, 0 };
X static int off_ticks[] = {
X 19, 14, 10, 7, 19, 14, 10, 7,
X 14, 10, 7, 10, 7, 14, 10, 7,
X 1, 1, 14, 10, 1, 1, 7, 1 };
X static int screens[] = {
X 1, 1, 1, 1, 2, 2, 2, 2,
X 3, 3, 3, 4, 4, 5, 5, 5,
X 1, 2, 6, 6, 3, 4, 6, 5 };
X
X high_score = 0L;
X
X demo:
X
X /* run the demo screen */
X demo_seq();
X
X /* initialize the game */
X lives = 3;
X level = (-1);
X score = 0L;
X print_score(0L);
X
X new_screen:
X
X /* advance the level */
X plevel = (++level > 13) ? 13 : level;
X flash_tick = flash_ticks[level % 24];
X off_tick = off_ticks[level % 24];
X display_level(True);
X
X /* initialize dynamic parameters */
X completed = False;
X fruit_times = 0;
X
X /* build the maze */
X clear_maps();
X read_maze(screens[level % 24] - 1);
X
X new_life:
X
X /* initialize more dynamic parameters */
X last_key = XK_Left;
X dead = False;
X eat_mode = False;
X count = (-1);
X fruit_count = (-1);
X fruit_shown = False;
X position_players();
X
X /* display the number of lives */
X (void)set_lives(lives);
X
X /* copy the maze to the map and the screen */
X XCopyArea(display, save, map, fullcopyGC, 0, 0,
X WIN_WIDTH, WIN_HEIGHT, 0, 0);
X XCopyArea(display, map, window, fullcopyGC, 0, 0,
X WIN_WIDTH, WIN_HEIGHT, 0, 0);
X
X /* display the ready message */
X get_ready();
X
X
X /*-- The Animation Loop ----------------------------------------*/
X
X while (True) {
X
X /*-- Xlib Event Section -------------------------------------*/
X
X while (QLength(display) > 0) {
X XNextEvent(display, &event);
X if (event.xany.window != window) continue;
X switch (event.type) {
X case KeyPress:
X XLookupString(&event, &c_buf, 1, &last_key, &status);
X if (last_key == XK_space)
X if (!pause_seq())
X goto demo;
X break;
X case UnmapNotify:
X while (True) {
X XNextEvent(display, &event);
X if (event.xany.window != window) continue;
X if (event.type == MapNotify) break;
X }
X XCopyArea(display, map, window, fullcopyGC, 0, 0,
X WIN_WIDTH, WIN_HEIGHT, 0, 0);
X restore_status();
X if (!pause_seq())
X goto demo;
X break;
X case PropertyNotify:
X if (event.xproperty.atom != DEC_icon_atom) break;
X while (True) {
X XNextEvent(display, &event);
X if (event.xany.window != window) continue;
X if (event.type != PropertyNotify) continue;
X if (event.xproperty.atom == DEC_icon_atom) break;
X }
X XCopyArea(display, map, window, fullcopyGC, 0, 0,
X WIN_WIDTH, WIN_HEIGHT, 0, 0);
X restore_status();
X if (!pause_seq())
X goto demo;
X break;
X case Expose:
X XCopyArea(display, map, window, fullcopyGC, 0, 0,
X WIN_WIDTH, WIN_HEIGHT, 0, 0);
X restore_status();
X break;
X default: break;
X }
X }
X
X /*-- Adjust Frame Counter -----------------------------------*/
X
X count = (count + 1) & 0x0f;
X
X /*-- Flashing Power-Dot And Fruit Section -------------------*/
X
X num_clips = NUM_FIGURES;
X
X if (count == 0) {
X
X /* it's time to flash the power-dots */
X XCopyArea(display, powermap, save, powerGC, 0, 0,
X WIN_WIDTH, WIN_HEIGHT, 0, 0);
X num_clips = NUM_FIGURES + MAX_POWER_DOTS;
X
X /* see if it's time to display or erase the fruit */
X if (fruit_times < 2) {
X if (++fruit_count == 30) {
X XCopyPlane(display, fruit_pix[plevel], save, fullcopyGC,
X 0, 0, GHOST_SIZE, GHOST_SIZE, fruit_x, fruit_y, 1);
X num_clips = NUM_FIGURES + MAX_POWER_DOTS + 1;
X dd[fruit_y >> 4][fruit_x >> 4] = 'F';
X fruit_shown = True;
X }
X else if (fruit_count == 50) {
X XFillRectangle(display, save, clearGC, fruit_x - 2,
X fruit_y, FRUIT_WIDTH, FRUIT_HEIGHT);
X dd[fruit_y >> 4][fruit_x >> 4] = '\0';
X fruit_count = 0;
X ++fruit_times;
X num_clips = NUM_FIGURES + MAX_POWER_DOTS + 1;
X fruit_shown = False;
X }
X }
X }
X
X /*-- Set Clipping Information -------------------------------*/
X
X XSetClipRectangles(display, copyGC, 0, 0, rectangle,
X num_clips, Unsorted);
X
X /*-- Restore Background Image -------------------------------*/
X
X XCopyArea(display, save, map, copyGC, 0, 0, WIN_WIDTH,
X WIN_HEIGHT, 0, 0);
X
X /*-- Motion Control Section ---------------------------------*/
X
X control_pac();
X if (dead || completed) break;
X for (i = 0; i < PAC_SLOT; i++)
X if (!(x[i] & 0x0f) && !(y[i] & 0x0f))
X (*drive[i])(i);
X for (i = 0; i < PAC_SLOT; i++) {
X rectangle[i].x = (x[i] += ix[i]) - 2;
X rectangle[i].y = (y[i] += iy[i]) - 2;
X }
X
X /*-- Flashing Ghost Section ---------------------------------*/
X
X /*
X * If we're in the middle of a ghost-eating period, this section
X * handles the timing and changes ghost states when necessary
X */
X if (eat_mode)
X if (count == count_sync) {
X ++grey_tick;
X if (grey_tick == flash_tick) {
X for (i = 0; i < PAC_SLOT; i++)
X if (ghost[i] == gghost)
X ghost[i] = fghost;
X }
X else if (grey_tick == off_tick) {
X eat_mode = False;
X for (i = 0; i < PAC_SLOT; i++)
X if (drive[i] == run) {
X ghost[i] = bghost;
X contact[i] = die;
X drive[i] = follow;
X x[i] &= ~0x1; y[i] &= ~0x01;
X ix[i] *= 2; iy[i] *= 2;
X }
X else if (drive[i] == hover2) {
X ghost[i] = bghost;
X contact[i] = die;
X drive[i] = hover;
X x[i] &= ~0x1; y[i] &= ~0x01;
X ix[i] *= 2; iy[i] *= 2;
X }
X }
X }
X
X /*-- Offscreen Figure Overlay -------------------------------*/
X
X for (i = 0; i < PAC_SLOT; i++)
X XCopyPlane(display, ghost[i][count], map, orGC, 0, 0,
X GHOST_SIZE, GHOST_SIZE, x[i], y[i], 1);
X XCopyPlane(display, pac[count], map, orGC, 0, 0,
X GHOST_SIZE, GHOST_SIZE, x[PAC_SLOT], y[PAC_SLOT], 1);
X
X /*-- Screen Update ------------------------------------------*/
X
X XCopyArea(display, map, window, copyGC, 0, 0, WIN_WIDTH,
X WIN_HEIGHT, 0, 0);
X
X /*-- Synchronization And Delay ------------------------------*/
X
X XSync(display, False);
X
X#ifdef FRAME_DELAY
X usleep(FRAME_DELAY);
X#endif
X
X } /* while */
X
X /*-- End of Animation Loop -------------------------------------*/
X
X if (dead) {
X if (set_lives(lives - 1)) {
X sleep(2);
X goto new_life;
X }
X game_over();
X goto demo;
X }
X
X if (completed) {
X finish();
X goto new_screen;
X }
X }
X /*-- The Game Ends Here -------------------------------------------*/
X
X do_exit();
X}
X
X
Xdo_exit()
X{
X XUnmapWindow(display, window);
X XUnloadFont(display, font);
X XFlush(display);
X XCloseDisplay(display);
X exit(1);
X}
END_OF_FILE
if test 8900 -ne `wc -c <'xchomp/main.c'`; then
echo shar: \"'xchomp/main.c'\" unpacked with wrong size!
fi
# end of 'xchomp/main.c'
fi
if test -f 'xchomp/resources.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'xchomp/resources.c'\"
else
echo shar: Extracting \"'xchomp/resources.c'\" \(12858 characters\)
sed "s/^X//" >'xchomp/resources.c' <<'END_OF_FILE'
X
X#include "xchomp.h"
X#include "bitmaps.h"
X
X
X/*
X * This file contains all of the functions which build the image and
X * window/pixmap resources for the game, as well as the graphics
X * contexts.
X */
X
Xcreate_window(argc, argv)
Xint argc;
Xchar *argv[];
X{
X XSizeHints hints;
X char *name = "xchomp";
X
X window = XCreateSimpleWindow(display, root, 0, 0, WIN_WIDTH,
X WIN_HEIGHT + GHOST_SIZE + 2, 1, black, white);
X
X icon = XCreatePixmapFromBitmapData(display, root, icon_bits,
X ICON_WIDTH, ICON_HEIGHT, 1, 0, 1);
X
X hints.flags = PSize | PMinSize | PMaxSize;
X hints.width = hints.min_width = hints.max_width = WIN_WIDTH;
X hints.height = hints.min_height = hints.max_height = WIN_HEIGHT + GHOST_SIZE + 2;
X
X XSetStandardProperties(display, window, name, name, icon,
X argv, argc, &hints);
X}
X
X
Xcreate_pac()
X{
X int i;
X
X lpac[3] = XCreatePixmapFromBitmapData(display, root, pacl1_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X lpac[2] = XCreatePixmapFromBitmapData(display, root, pacl2_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X lpac[1] = XCreatePixmapFromBitmapData(display, root, pacl3_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X lpac[0] = XCreatePixmapFromBitmapData(display, root, pacl4_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X lpac[4] = lpac[3];
X lpac[5] = lpac[2];
X lpac[6] = lpac[1];
X lpac[7] = lpac[0];
X for (i = 8; i < 16; i++)
X lpac[i] = lpac[i - 8];
X
X rpac[3] = XCreatePixmapFromBitmapData(display, root, pacr1_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X rpac[2] = XCreatePixmapFromBitmapData(display, root, pacr2_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X rpac[1] = XCreatePixmapFromBitmapData(display, root, pacr3_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X rpac[0] = lpac[0];
X rpac[4] = rpac[3];
X rpac[5] = rpac[2];
X rpac[6] = rpac[1];
X rpac[7] = rpac[0];
X for (i = 8; i < 16; i++)
X rpac[i] = rpac[i - 8];
X
X upac[3] = XCreatePixmapFromBitmapData(display, root, pacu1_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X upac[2] = XCreatePixmapFromBitmapData(display, root, pacu2_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X upac[1] = XCreatePixmapFromBitmapData(display, root, pacu3_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X upac[0] = lpac[0];
X upac[4] = upac[3];
X upac[5] = upac[2];
X upac[6] = upac[1];
X upac[7] = upac[0];
X for (i = 8; i < 16; i++)
X upac[i] = upac[i - 8];
X
X dpac[3] = XCreatePixmapFromBitmapData(display, root, pacd1_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X dpac[2] = XCreatePixmapFromBitmapData(display, root, pacd2_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X dpac[1] = XCreatePixmapFromBitmapData(display, root, pacd3_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X dpac[0] = lpac[0];
X dpac[4] = dpac[3];
X dpac[5] = dpac[2];
X dpac[6] = dpac[1];
X dpac[7] = dpac[0];
X for (i = 8; i < 16; i++)
X dpac[i] = dpac[i - 8];
X
X dead_prot[0] = lpac[0];
X dead_prot[1] = lpac[1];
X dead_prot[2] = lpac[2];
X dead_prot[3] = lpac[3];
X dead_prot[4] = XCreatePixmapFromBitmapData(display, root, pdie4_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X dead_prot[5] = XCreatePixmapFromBitmapData(display, root, pdie5_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X dead_prot[6] = XCreatePixmapFromBitmapData(display, root, pdie6_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X dead_prot[7] = XCreatePixmapFromBitmapData(display, root, pdie7_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X dead_prot[8] = XCreatePixmapFromBitmapData(display, root, pdie8_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X dead_prot[9] = XCreatePixmapFromBitmapData(display, root, pdie9_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X dead_prot[10] = XCreatePixmapFromBitmapData(display, root, pdie10_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X
X for (i = 0; i < 11; i++)
X deadpac[i] = XCreatePixmap(display, root, GHOST_SIZE, GHOST_SIZE, 1);
X
X small_pac = XCreatePixmapFromBitmapData(display, root, pacsmall_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X}
X
X
Xcreate_ghost()
X{
X int i;
X
X bghost[0] = XCreatePixmapFromBitmapData(display, root, frame1_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X bghost[2] = XCreatePixmapFromBitmapData(display, root, frame2_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X bghost[6] = XCreatePixmapFromBitmapData(display, root, frame3_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X bghost[1] = bghost[4] = bghost[5] = bghost[0];
X bghost[3] = bghost[2];
X bghost[7] = bghost[6];
X for (i = 8; i < 16; i++)
X bghost[i] = bghost[i - 8];
X
X gghost[0] = XCreatePixmapFromBitmapData(display, root, grey1_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X gghost[2] = XCreatePixmapFromBitmapData(display, root, grey2_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X gghost[6] = XCreatePixmapFromBitmapData(display, root, grey3_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X gghost[1] = gghost[4] = gghost[5] = gghost[0];
X gghost[3] = gghost[2];
X gghost[7] = gghost[6];
X for (i = 8; i < 16; i++)
X gghost[i] = gghost[i - 8];
X
X for (i = 0; i < 8; i++) fghost[i] = gghost[i];
X for (i = 8; i < 16; i++) fghost[i] = bghost[i];
X
X eghost[0] = XCreatePixmapFromBitmapData(display, root, eye_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X for (i = 1; i < 16; i++) eghost[i] = eghost[0];
X}
X
X
Xcreate_maze_symbols()
X{
X int i;
X Pixmap empty;
X static char index[] = { '1', '2', '3', '4', '5', '6', '7', '8',
X 'a', 'b', 'c', 'd', 'v', 'e', 'g', '-',
X 'j', '[', 'm', 'n', 'o', 'q', ']', 's',
X 't', 'u', '^', '|', 'w', 'x', 'y', 'z',
X '.', 'O' };
X static char *data[] = { m1_bits, m2_bits, m3_bits, m4_bits, m5_bits,
X m6_bits, m7_bits, m8_bits, ma_bits, mb_bits,
X mc_bits, md_bits, mdown_bits, me_bits, mg_bits,
X mhorz_bits, mj_bits, mleft_bits, mm_bits, mn_bits,
X mo_bits, mq_bits, mright_bits, ms_bits, mt_bits,
X mu_bits, mup_bits, mvert_bits, mw_bits, mx_bits,
X my_bits, mz_bits, mdot_bits, mpower_bits };
X
X empty = XCreatePixmapFromBitmapData(display, root, mempty_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X for (i = 0; i < 128; maze[i++] = empty);
X
X for (i = 0; i < sizeof(index); i++)
X maze[index[i]] = XCreatePixmapFromBitmapData(display, root,
X data[i], GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X}
X
X
Xcreate_maps()
X{
X map = XCreatePixmap(display, root, WIN_WIDTH, WIN_HEIGHT, depth);
X save = XCreatePixmap(display, root, WIN_WIDTH, WIN_HEIGHT, depth);
X powermap = XCreatePixmap(display, root, WIN_WIDTH, WIN_HEIGHT, depth);
X}
X
X
X
Xcreate_fruit()
X{
X fruit_pix[0] = XCreatePixmapFromBitmapData(display, root, fcherry_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X fruit_pix[1] = XCreatePixmapFromBitmapData(display, root, fstraw_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X fruit_pix[2] = XCreatePixmapFromBitmapData(display, root, fwater_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X fruit_pix[3] = fruit_pix[2];
X fruit_pix[4] = XCreatePixmapFromBitmapData(display, root, fapple_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X fruit_pix[5] = XCreatePixmapFromBitmapData(display, root, fgrape_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X fruit_pix[6] = fruit_pix[5];
X fruit_pix[7] = XCreatePixmapFromBitmapData(display, root, fbell_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X fruit_pix[8] = fruit_pix[7];
X fruit_pix[9] = XCreatePixmapFromBitmapData(display, root, fclock_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X fruit_pix[10] = fruit_pix[9];
X fruit_pix[11] = XCreatePixmapFromBitmapData(display, root, fxlogo_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X fruit_pix[12] = fruit_pix[11];
X fruit_pix[13] = XCreatePixmapFromBitmapData(display, root, fkey_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X
X fval_pix[0] = XCreatePixmapFromBitmapData(display, root, ff1_bits,
X FRUIT_WIDTH, FRUIT_HEIGHT, 1, 0, 1);
X fval_pix[1] = XCreatePixmapFromBitmapData(display, root, ff2_bits,
X FRUIT_WIDTH, FRUIT_HEIGHT, 1, 0, 1);
X fval_pix[2] = XCreatePixmapFromBitmapData(display, root, ff3_bits,
X FRUIT_WIDTH, FRUIT_HEIGHT, 1, 0, 1);
X fval_pix[3] = fval_pix[2];
X fval_pix[4] = XCreatePixmapFromBitmapData(display, root, ff4_bits,
X FRUIT_WIDTH, FRUIT_HEIGHT, 1, 0, 1);
X fval_pix[5] = XCreatePixmapFromBitmapData(display, root, ff5_bits,
X FRUIT_WIDTH, FRUIT_HEIGHT, 1, 0, 1);
X fval_pix[6] = fval_pix[5];
X fval_pix[7] = XCreatePixmapFromBitmapData(display, root, ff6_bits,
X FRUIT_WIDTH, FRUIT_HEIGHT, 1, 0, 1);
X fval_pix[8] = fval_pix[7];
X fval_pix[9] = XCreatePixmapFromBitmapData(display, root, ff7_bits,
X FRUIT_WIDTH, FRUIT_HEIGHT, 1, 0, 1);
X fval_pix[10] = fval_pix[9];
X fval_pix[11] = XCreatePixmapFromBitmapData(display, root, ff8_bits,
X FRUIT_WIDTH, FRUIT_HEIGHT, 1, 0, 1);
X fval_pix[12] = fval_pix[11];
X fval_pix[13] = XCreatePixmapFromBitmapData(display, root, ff9_bits,
X FRUIT_WIDTH, FRUIT_HEIGHT, 1, 0, 1);
X
X eat_pix[0] = XCreatePixmapFromBitmapData(display, root, fg1_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X eat_pix[1] = XCreatePixmapFromBitmapData(display, root, fg2_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X eat_pix[2] = XCreatePixmapFromBitmapData(display, root, fg3_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X eat_pix[3] = XCreatePixmapFromBitmapData(display, root, fg4_bits,
X GHOST_SIZE, GHOST_SIZE, 1, 0, 1);
X}
X
X
Xcreate_GCs()
X{
X XGCValues gcv;
X unsigned long mask;
X
X mask = GCForeground | GCBackground | GCFunction |
X GCFont | GCGraphicsExposures;
X
X /* resolve colors */
X if ((black | white) == black)
X normal = True;
X else if ((black | white) == white)
X normal = False;
X else {
X black &= white;
X normal = False;
X }
X
X /* context for copying; used for animation */
X gcv.foreground = black;
X gcv.background = white;
X gcv.function = GXcopy;
X gcv.font = font;
X gcv.graphics_exposures = False;
X copyGC = XCreateGC(display, root, mask, &gcv);
X
X /* context for copying; used for full size areas */
X gcv.foreground = black;
X gcv.background = white;
X gcv.function = GXcopy;
X gcv.font = font;
X gcv.graphics_exposures = False;
X fullcopyGC = XCreateGC(display, root, mask, &gcv);
X
X /* context for overlaying; used for animation */
X gcv.foreground = black;
X gcv.background = white;
X gcv.function = normal ? GXor : GXand;
X gcv.font = font;
X gcv.graphics_exposures = False;
X orGC = XCreateGC(display, root, mask, &gcv);
X
X /* context for clearing */
X gcv.foreground = white;
X gcv.background = black;
X gcv.function = GXcopy;
X gcv.font = font;
X gcv.graphics_exposures = False;
X clearGC = XCreateGC(display, root, mask, &gcv);
X
X /* context for inverting */
X gcv.foreground = white;
X gcv.background = black;
X gcv.function = GXinvert;
X gcv.font = font;
X gcv.graphics_exposures = False;
X gcv.plane_mask = black ^ white;
X invertGC = XCreateGC(display, root, mask | GCPlaneMask, &gcv);
X
X /* context for flashing the power dots */
X gcv.foreground = black;
X gcv.background = white;
X gcv.function = normal ? GXxor : GXequiv;
X gcv.plane_mask = black ^ white;
X gcv.font = font;
X gcv.graphics_exposures = False;
X powerGC = XCreateGC(display, root, mask | GCPlaneMask, &gcv);
X
X /* context of depth 1; used for transferring onto bitmaps */
X gcv.foreground = 1;
X gcv.background = 0;
X gcv.function = GXcopy;
X gcv.font = font;
X gcv.graphics_exposures = False;
X bitmapGC = XCreateGC(display, bghost[0], mask, &gcv);
X}
X
X
Xcreate_demo_images()
X{
X demo_map[0] = XCreatePixmapFromBitmapData(display, root, bigc_bits,
X 48, 48, 1, 0, 1);
X demo_map[1] = XCreatePixmapFromBitmapData(display, root, bigh_bits,
X 48, 48, 1, 0, 1);
X demo_map[2] = XCreatePixmapFromBitmapData(display, root, bigo_bits,
X 48, 48, 1, 0, 1);
X demo_map[3] = XCreatePixmapFromBitmapData(display, root, bigm_bits,
X 48, 48, 1, 0, 1);
X demo_map[4] = XCreatePixmapFromBitmapData(display, root, bigp_bits,
X 48, 48, 1, 0, 1);
X}
X
X
Xclear_maps()
X{
X XFillRectangle(display, powermap, clearGC, 0, 0, WIN_WIDTH, WIN_HEIGHT);
X XFillRectangle(display, save, clearGC, 0, 0, WIN_WIDTH, WIN_HEIGHT);
X XFillRectangle(display, map, clearGC, 0, 0, WIN_WIDTH, WIN_HEIGHT);
X}
END_OF_FILE
if test 12858 -ne `wc -c <'xchomp/resources.c'`; then
echo shar: \"'xchomp/resources.c'\" unpacked with wrong size!
fi
# end of 'xchomp/resources.c'
fi
echo shar: End of archive 1 \(of 3\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 3 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 3 archives.
rm -f ark[1-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
More information about the Comp.sources.x
mailing list