pacman/pacman.c
mark
mark
Sun Apr 4 15:20:18 AEST 1982
/*
/* PACMAN - written by Dave Nixon, AGS Computers Inc., July, 1981.
/* Converted for curses Feb 1982 by Mark Horton.
/*
/* Terminal handling for video games taken from aliens
/* the original version of aliens is from
/* Fall 1979 Cambridge Jude Miller
/*
/* Score keeping modified and general terminal handling (termcap routines
/* from UCB's ex) added by Rob Coben, BTL, June, 1980.
/*
/* If MSG is defined, the program uses the inter-process message facility
/* of UNIX/TS Augmented to optimize reading the tty while updating the
/* screen. Otherwise, the child process (reading the tty) writes
/* a temporary communications file, which the parent (updating the screen)
/* is constantly seeking to the beginning of and re-reading. (UGH!)
/* If your system has a non-blocking read (read-without-wait), it should
/* be implemented, and the child process could be dispensed with entirely.
*/
#include <stdio.h>
#include "pacdefs.h"
/*
* global variables
*/
extern char
message[];
extern char
initbrd[BRDY][BRDX],
display[BRDY][BRDX];
extern unsigned
pscore;
extern struct pac
monst[];
extern char monst_names[];
#ifdef A_BLINK
# define pflash A_BLINK
#else
# define pflash _STANDOUT
#endif
int pacsymb = PACMAN,
rounds, /* time keeping mechanism */
killflg,
delay,
potion,
goldcnt, /* no. of gold pieces remaining */
game,
monst_often,
monsthere,
boardcount = 1,
wmonst,
potintvl = POTINTVL,
potioncnt,
treascnt = 0;
extern
char *full_names[];
struct pac
pac;
struct pac
pacstart =
{
PSTARTX,
PSTARTY,
DNULL,
SLOW,
FALSE
};
struct pac
*pacptr = &pac;
#define DEFCHPERTURN 60
main(argc, argv)
char **argv;
{
register int tmp; /* temp variables */
register int pac_cnt;
register int monstcnt; /* monster number */
int tries;
long denom;
struct pac *mptr;
char gcnt[10];
char msgbuf[50];
int chperturn = DEFCHPERTURN;
game = 0;
if (argc > 1) {
game = argv[1][0] - '0';
if (game < 1 || game > 3)
game = 0;
if (argc > 2)
chperturn = atoi(argv[2]);
}
init(); /* global init */
for (pac_cnt = MAXPAC; pac_cnt > 0; pac_cnt--)
{
redraw:
erase();
potioncnt = 0;
treascnt = 0;
potion = FALSE;
SPLOT(0, 45, "SCORE: ");
(void) sprintf(msgbuf, "GAME: %s", game==1 ? "EASY" :
game==2 ? "MEDIUM" :
"HARD");
SPLOT(0, 65, msgbuf);
SPLOT(21, 45, "gold left = ");
(void) sprintf(gcnt, "%6d", goldcnt);
SPLOT(21, 57, gcnt);
/*
* We update the monsters every monst_often turns, to keep
* the CRT caught up with the computer. The fudge factor
* was calculated from the assumption that each full refresh
* outputs chperturn characters. The default is pessimistic
* based on ANSI and HP terminals w/verbose cursor addressing.
*/
denom = ((long) delay) * baudrate();
monst_often = (chperturn * 10000L + denom - 1) / denom;
if (monst_often < 1)
monst_often = 1;
if (potion == TRUE)
{
SPLOT(3, 45, "COUNTDOWN: ");
(void) sprintf(message, "%2d", potioncnt);
SPLOT(3, 60, message);
};
pacsymb = PACMAN;
killflg = FALSE;
(void) sprintf(message,
"delay = %3d, refresh = %3d", delay, monst_often);
SPLOT(22, 45, message);
/*
* PLOT maze
*/
for (tmp = 0; tmp < BRDY; tmp++)
{
SPLOT(tmp, 0, &(display[tmp][0]));
};
/* initialize a pacman */
pac = pacstart;
PLOT(pacptr->ypos, pacptr->xpos, pacsymb | pflash);
/* display remaining pacmen */
for (tmp = 0; tmp < pac_cnt - 1; tmp++)
{
PLOT(LINES >=24 ? 23 : 22, (MAXPAC * tmp), PACMAN);
};
/*
* Init. monsters
*/
for (mptr = &monst[0], monstcnt = 0; monstcnt < MAXMONSTER; mptr++, monstcnt++)
{
mptr->xpos = MSTARTX + (2 * monstcnt);
mptr->ypos = MSTARTY;
mptr->speed = SLOW;
mptr->dirn = DNULL;
mptr->danger = TRUE;
mptr->stat = START;
PLOT(mptr->ypos, mptr->xpos, monst_names[monstcnt]);
mptr->xdpos = mptr->xpos;
mptr->ydpos = mptr->ypos;
};
rounds = 0; /* timing mechanism */
update();
refresh();
tries = 0;
while ((pacptr->dirn == NULL) && (tries++ < 300))
{
napms(100);
poll(1);
}
/* main game loop */
do
{
if (rounds++ % MSTARTINTVL == 0)
{
startmonst();
};
pacman();
if (killflg == TURKEY)
break;
for (monstcnt = 0; monstcnt < (MAXMONSTER / 2); monstcnt++)
{
monster(monstcnt); /* next monster */
};
if (killflg == TURKEY)
break;
if (pacptr->speed == FAST)
{
pacman();
if (killflg == TURKEY)
break;
};
for (monstcnt = (MAXMONSTER / 2); monstcnt < MAXMONSTER; monstcnt++)
{
monster(monstcnt); /* next monster */
};
if (killflg == TURKEY)
break;
if (potion == TRUE)
{
(void) sprintf(message, "%2d", potioncnt);
SPLOT(3, 60, message);
if (potioncnt == 10 || potioncnt < 5)
beep();
if (--potioncnt <= 0)
{
SPLOT(3,45," ");
SPLOT(4,45," ");
SPLOT(5,45," ");
potion = FALSE;
pacptr->speed = SLOW;
pacptr->danger = FALSE;
for (monstcnt = 0; monstcnt < MAXMONSTER; monstcnt++)
{
monst[monstcnt].danger = TRUE;
}
}
}
if (treascnt && --treascnt == 0) {
display[TRYPOS][TRXPOS] = VACANT;
PLOT(TRYPOS, TRXPOS, VACANT);
}
if (rounds % monst_often == 0)
update(); /* score display etc */
refresh();
if (goldcnt <= 0)
{
potintvl -= 5;
if (potintvl <= 0)
potintvl = 5;
reinit();
goto redraw;
};
} while (killflg != TURKEY);
sprintf(msgbuf, "Oops! %s got you!\n", full_names[wmonst]);
SPLOT(5, 45, msgbuf);
flushinp();
refresh();
sleep(2);
}
SPLOT(8, 45, "THE MONSTERS ALWAYS TRIUMPH");
SPLOT(9, 45, "IN THE END!");
update();
over();
}
pacman()
{
register int sqtype;
register int mcnt;
register int tmpx, tmpy;
int deltat;
struct pac *mptr;
refresh();
/* pause; wait for the player to hit a key */
napms(delay);
/* get instructions from player, but don't wait */
poll(0);
/* remember current pacman position */
tmpx = pacptr->xpos;
tmpy = pacptr->ypos;
/* "eat" any gold */
/* update display array to reflect what is on terminal */
display[tmpy][tmpx] = VACANT;
/* what next? */
switch (pacptr->dirn)
{
case DUP:
pacsymb = (rounds%2) ? CUP : PUP;
switch (sqtype = display[tmpy + UPINT][tmpx])
{
case GOLD:
case VACANT:
case CHOICE:
case POTION:
case TREASURE:
/* erase where the pacman went */
PLOT(tmpy, tmpx, VACANT);
pacptr->ypos += UPINT;
break;
default:
pacptr->dirn = DNULL;
pacsymb = PACMAN;
break;
};
break;
case DDOWN:
pacsymb = (rounds%2) ? CDOWN : PDOWN;
switch (sqtype = display[tmpy + DOWNINT][tmpx])
{
case GOLD:
case VACANT:
case CHOICE:
case POTION:
case TREASURE:
/* erase where the pacman went */
PLOT(tmpy, tmpx, VACANT);
pacptr->ypos += DOWNINT;
break;
default:
pacptr->dirn = DNULL;
pacsymb = PACMAN;
break;
};
break;
case DLEFT:
if(tmpx == 0)
{
/* erase where the pacman went */
PLOT(tmpy, tmpx, VACANT);
pacptr->xpos = XWRAP;
sqtype = VACANT;
break;
};
pacsymb = (rounds%2) ? CLEFT : PLEFT;
switch (sqtype = display[tmpy][tmpx + LEFTINT])
{
case GOLD:
case VACANT:
case CHOICE:
case POTION:
case TREASURE:
/* erase where the pacman went */
PLOT(tmpy, tmpx, VACANT);
pacptr->xpos += LEFTINT;
break;
default:
pacptr->dirn = DNULL;
pacsymb = PACMAN;
break;
};
break;
case DRIGHT:
if(tmpx == XWRAP)
{
/* erase where the pacman went */
PLOT(tmpy, tmpx, VACANT);
pacptr->xpos = 0;
sqtype = VACANT;
break;
};
pacsymb = (rounds%2) ? CRIGHT : PRIGHT;
switch (sqtype = display[tmpy][tmpx + RIGHTINT])
{
case GOLD:
case VACANT:
case CHOICE:
case POTION:
case TREASURE:
/* erase where the pacman went */
PLOT(tmpy, tmpx, VACANT);
pacptr->xpos += RIGHTINT;
break;
default:
pacptr->dirn = DNULL;
pacsymb = PACMAN;
break;
};
break;
case DNULL:
pacsymb = PACMAN;
break;
}
/* did the pacman get any points or eat a potion? */
switch (sqtype)
{
case CHOICE:
case GOLD:
pscore += GOLDVAL;
goldcnt--;
break;
case TREASURE:
switch (boardcount) {
case 0:
case 1: pscore += 100; break;
case 2: pscore += 200; break;
case 3: case 4: pscore += 500; break;
case 5: case 6: pscore += 700; break;
case 7: case 8: pscore += 1000; break;
default:
case 9: case 10: pscore += 2000; break;
}
break;
case POTION:
SPLOT(3, 45, "COUNTDOWN: ");
potion = TRUE;
potioncnt = potintvl;
monsthere = 0;
pacptr->speed = FAST;
pacptr->danger = TRUE;
/* slow down monsters and make them harmless */
mptr = &monst[0];
for (mcnt = 0; mcnt < MAXMONSTER; mcnt++)
{
mptr->speed = SLOW;
mptr->danger = FALSE;
mptr++;
}
break;
}
/* did the pacman run into a monster? */
killflg = FALSE;
for (mptr = &monst[0], mcnt = 0; mcnt < MAXMONSTER; mptr++, mcnt++)
{
if ((mptr->xpos==pacptr->xpos) && (mptr->ypos==pacptr->ypos))
killflg = dokill(mcnt);
};
if (killflg != TURKEY)
{
PLOT(pacptr->ypos, pacptr->xpos, pacsymb | pflash);
};
}
More information about the Comp.sources.unix
mailing list