Path: utzoo!hoptoad!pacbell!ames!elroy!spl1!ddsw1!karl From: karl@ddsw1.MCS.COM (Karl Denninger) Newsgroups: alt.sources Subject: COSMOS Game (XENIX Specific), Part 03/03 Message-ID: <2170@ddsw1.MCS.COM> Date: 18 Nov 88 05:57:47 GMT Reply-To: karl@ddsw1.MCS.COM (Karl Denninger) Distribution: alt Organization: Macro Computer Solutions, Inc., Mundelein, IL Lines: 1837 Part 3 of 3, see part 1 for details #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'cosmos.c' <<'END_OF_FILE' X/* Spacewar - The final frontier X X This package is Copyright 1988 Karl Denninger. All rights reserved. X X All unauthorized mutants shall be destroyed, fed to vermin, and the X remains from this process will be prosecuted. X X*/ X X/* Definitions go below - Make sure you have these in front of include X files as these definitions should override the include files */ X X X#include "cosmos.h" X extern void clrin(); /* Interrupt handler */ extern void die(); /* Death by disconnect */ X int extx, exty; int quit; /* Halt variable */ char *buffer; /* Buffer pointer */ int numcomp; /* # of computer players */ char home[128]; /* Home directory */ int superuser, su2; /* Uid of the superuser */ int window; /* Window size, must be < 20 */ int foundchar = 0; /* Found character? */ int oldchar; /* Old character if one */ struct nameblock *ship; /* Pointer to ship's data */ struct nameblock name[MAXSHIPS]; struct grid onegrid; struct grid oldgrid; X X int squares[SIZE]; /* Squares table */ int drone = 0; /* Not a drone */ long numsecs; /* Seconds since epoch */ long nowsecs; /* Time now */ long startime; long minsday; /* Minutes/day */ long origmins; /* Original minutes */ long layoff; /* How long to reset limits */ int free_game; /* Is this a free game? */ X main(argc, argv) int argc; char *argv[]; X X{ X X static long points; /* Points accumulated */ X static int type; /* Class of ship */ X char shipname[40]; X X struct grid tempgrid; X int limited = 0; /* Limited user */ X int timed = 0; /* Timed user? */ X long now; X int tenwarned = 0; /* Warning flags */ X int fivewarned = 0; X int twowarned = 0; X int destx = -1; X int nomove = 0; X int desty = -1; X int safe = -1; /* Initially safe from collisions */ X int standir = 0; X int shipcount; X int scancount = 0, zx; X int ntfree = 0; /* Number of torpedoes free */ X int docked = 0; X int tmpint; /* Temp integer */ X int cheat = 0; X X int seg; /* Shared segment number */ X X int status; /* Status (ok/not ok) */ X int qcount = 0; /* Quit counter */ X int energy_count = 0; /* Temporary iterative counter */ X int stale_msg = TIME_PER_MSG;/* Stale message count */ X int tempenergy; X long size; X int oldx, oldy; X int key; X int tempint = 0; X X static int delta_x = 0; /* Initial delta 'x' */ X static int delta_y = 0; /* Initial delta 'y' */ X X int semid; X int flags; X char tempstr[80]; /* 80 Character string */ X char tempstr2[80]; /* 80 Character string */ X char tmp[80]; X FILE *fid; X int scanned = 0; X X struct nameblock namebuf; X struct torps torparray[MAXFTORPS]; X /* Array of torpedo coords */ X X long game = sizeof(ccount) + (sizeof(onename) * MAXSHIPS) + X (sizeof(onegrid) * MAXGRID) + (sizeof(onemsg) * MAXMSG); X X size = (game); /* Get size of game module */ X quit = 0; X printf("Cosmos V%s\n", VERSION); X printf("Copyright 1988 MCS Inc. & Karl Denninger\n"); X#ifdef LICENSEE X printf("Licensed to %s\n", LICENSEE); X#endif X fflush(stdout); X for (extx = 0; extx < SIZE; extx++) X squares[extx] = (extx * extx); X for (extx = 0; extx < MAXFTORPS; extx++) X torparray[extx].inuse = 0; /* Mark torpedo not in use */ X sprintf(tmp, "%s", HOME); X if ((fid = fopen(tmp, "r")) != NULL) { X fscanf(fid, "%s %d %d %d %d %d %d %d", home, &superuser, &su2, X &numcomp, &minsday, &origmins, &layoff, &free_game); X fclose(fid); X } X if ((seg = shmget(122L, size, IPC_CREAT|0660)) == -1) { X perror("create"); X puts("Cannot execute due to shared-segment create fault"); X exit(1); X } X if ((buffer = shmat(seg, (char *) NULL, 0)) == (char *) -1) { X perror("attach"); X puts("Cannot execute due to shared-segment attach fault"); X exit(1); X } X if ((semid = semget(122L, 1, 0660)) == -1) { X if ((semid = semget(122L, 1, 0660|IPC_CREAT)) == -1) { X perror("semaphone create"); X exit(1); X } X } else { X acquire(semid); X } X signal(SIGHUP, die); /* Save on hangups */ X signal(SIGINT, clrin); /* Clear input on ^C */ X signal(SIGQUIT, SIG_IGN); X signal(SIGCLD, SIG_IGN); /* No Zombies */ X X#ifdef ACCOUNTING X/* Now start accounting and figure out what time it is */ X X numsecs = addplayer(&limited, &timed, argc, argv[1]);/* Do accounting */ X startime = time((int *) 0L); /* Get current time */ X nowsecs = startime + numsecs; /* Set limit */ X if (numsecs <= 0) { X release(semid); X printf("You are out of time at present to play COSMOS\n"); X if (numsecs < 0) { /* No more credit */ X printf("Your account balance has reached zero\n"); X printf("Please contact the administrator\n"); X } else X printf("You must wait for %d minutes before playing again\n", layoff); X exit(0); X } X/* End time accounting stuff */ X#endif X X release(semid); X initscr(); X acquire(semid); X noecho(); X cbreak(); X intrflush(stdscr, FALSE); /* No flush on interrupt */ X#ifdef M_TERMINFO X typeahead(-1); /* No typeahead checks */ X#endif X srand((unsigned) time ((long *) 0L)); X if (argc == 1) X showfile("Hello", semid, 0); X erase(); X readgrid(0, 0, &onegrid); X if (onegrid.type == 0) { X mvaddstr(22,0,"Initializing game grid..."); X refresh(); X for (extx = 0; extx < SIZE; extx++) { X for (exty = 0; exty < SIZE; exty++) { X tempint = rand(); X if (tempint < 500) { X if (tempint < 30) { X if (tempint < 10) { X onegrid.type = NEGBASE; X onegrid.energy = 1000000L; X onegrid.shield = 100; X } else { X onegrid.type = VOID; X onegrid.energy = roll(SIZE); X onegrid.shield = roll(SIZE); X } X } else { X if (tempint < 250) { X onegrid.type = STAR; X onegrid.energy = 2000000L; X } else { X onegrid.type = PLANET; X onegrid.energy = 1000000L; X } X onegrid.shield = 0; X } X } else { X onegrid.type = EMPTY; X onegrid.shield = 0; X onegrid.energy = 0L; X } X storegrid(extx, exty, onegrid); X } X } X move(22,0); X clrtoeol(); X refresh(); X } X if ((ship = (struct nameblock *) getship(argc, argv[1], semid, &extx, &exty)) == NULL) { X#ifdef ACCOUNTING X delplayer(argc, argv[1], startime); X#endif X endwin(); X puts("Fatal placement error"); /* Can't place the ship */ X release(semid); /* Release semaphore */ X exit(0); /* Quit */ X } X#ifdef RANDOM_START X extx = roll(SIZE); X exty = roll(SIZE); X#endif X if ((extx == 0) && (exty == 0)) { X extx = roll(SIZE); X exty = roll(SIZE); X } X window = window_size[ship->type]; X sprintf(tmp, "Welcome %s (%c)", ship->name, ship->token); X putmsg(tmp); X X/* Now place the user's ship in the game. */ X X tempint = 0; X while (quit == 0) { X while ((extx < 0) || (extx >= SIZE)) X extx = roll(SIZE); X while ((exty < 0) || (exty >= SIZE)) X exty = roll(SIZE); X readgrid(extx, exty, &onegrid); X if (onegrid.type == EMPTY) X quit++; X else { X extx = roll(SIZE); exty = roll(SIZE); X tempint++; X if (tempint >= 200) { X endwin(); X release(semid); X puts("Cannot place ship!"); X } X } X } X onegrid.type = ship->token; X onegrid.shield = ship->shield; X onegrid.energy = ship->energy; X onegrid.align = 0; /* Neutral alignment */ X ship->human = 1; /* Human ship */ X storegrid(extx, exty, onegrid); X quit = 0; X erase(); X standout(); X mvaddstr(23,20," Press the key for assistance on COSMOS "); X standend(); X while (quit == 0) { X X/* Move torpedoes */ X movetorps(torparray, &ntfree); X readgrid(extx, exty, &onegrid); X if (onegrid.type == EMPTY) { X if (!limited) X penalize(); /* Make it hurt :-) */ X sprintf(tmp, "The %s (%c) explodes!", ship->name, ship->token); X putmsg(tmp); X explode(extx, exty, (ship->type * EXPLOSION), ship->type);/* Kill people near 'ya :-) */ X ship->token = 0; /* Delete from grid */ X ship->name[0] = 0; X onegrid.type = EMPTY; X onegrid.shield = 0; X onegrid.energy = 0; X onegrid.align = 0; X storegrid(extx, exty, onegrid); X release(semid); /* Release locks */ X (void) dispstatus(extx, exty, window, docked); X refresh(); X sleep(10); X erase(); /* Exit out from game */ X refresh(); X endwin(); X puts("Your ship has disintegrated!"); X#ifdef ACCOUNTING X if (!limited) X delplayer(argc, argv[1]); X#endif X exit(0); X } X X/* Insert here any routines which should be performed after each turn -- X specifically, those things which take energy when engaged such as shields */ X X if (scancount > 0) { X scancount--; X if (!scancount) { X mvaddstr(1, 44, " "); X for (zx = 2; zx < 17; zx++) { X mvaddstr(zx, 44, " "); X } X } X } X energy_count--; X if (energy_count < 0) { X energy_count = TIME_PER_EUNIT; X onegrid.energy--; X } X#ifdef RETIRE_MSGS X if (stale_msg-- <= 0) { X putmsg(""); X stale_msg = TIME_PER_MSG; X } X#endif X if (ship->wstatus & SHIELD_UP) { X onegrid.energy -= (ship->type * SHIELD_COST); X docked = 0; /* Undock the craft */ X } X if (ship->energy > onegrid.energy) X ship->energy = onegrid.energy; X if (ship->shield > onegrid.shield) X ship->shield = onegrid.shield; X if (ship->shield <= 0) { X ship->wstatus &= ~(SHIELD_UP); X ship->wstatus |= SHIELD_DEAD; X } else X ship->wstatus &= ~(SHIELD_DEAD); X if (ship->torps <= 0) { X ship->wstatus &= ~(TORPEDO_LOCK); X ship->wstatus |= TORPEDO_DEAD; X ship->numtorps = 0; /* Blown off */ X } else X if (num_torps[ship->type] > 0) X ship->wstatus &= ~(TORPEDO_DEAD); X if (ship->mines <= 0) { X ship->wstatus &= ~(MINE_LOCK); X ship->wstatus |= MINE_DEAD; X ship->nummines = 0; /* Blown off */ X } else X if (num_mines[ship->type] > 0) X ship->wstatus &= ~(MINE_DEAD); X ship->align = onegrid.align; /* Alignment */ X if (onegrid.hit) { X beep(); X move(23,20); X standout(); X if (onegrid.hit == 1) X printw("You've been hit!", onegrid.hit); X else X printw("You've been hit %d times!", onegrid.hit); X standend(); X clrtoeol(); X docked = 0; X onegrid.hit = 0; X } X storegrid(extx, exty, onegrid); X if ((ship->energy < 0) || (ship->life < 0) || (ship->hull < 0) || (ship->crew < 0)) { X if (!limited) X penalize(); /* Make it hurt :-) */ X sprintf(tmp, "The %s (%c) explodes!", ship->name, ship->token); X putmsg(tmp); X explode(extx, exty, (ship->type * EXPLOSION), ship->type);/* Kill people near 'ya :-) */ X ship->token = 0; /* Delete from grid */ X ship->name[0] = 0; X onegrid.type = EMPTY; X onegrid.shield = 0; X onegrid.energy = 0; X onegrid.align = 0; X storegrid(extx, exty, onegrid); X release(semid); /* Release locks */ X (void) dispstatus(extx, exty, window, docked); X refresh(); X sleep(10); X erase(); /* Exit out from game */ X refresh(); X endwin(); X puts("Your ship has disintegrated!"); X#ifdef ACCOUNTING X delplayer(argc, argv[1]); X#endif X exit(0); X } X status = dispstatus(extx, exty, window, docked); X if (ship->scanned) { X mvaddstr(23,20, "Captain! We're being scanned!!"); X ship->scanned = 0; X } X if (timed) { X now = time((long *) 0L); X if (now >= (nowsecs + 600)) { X if (!tenwarned) { X mvaddstr(23,20,"10 Minute warning!!!!"); X clrtoeol(); X beep(); X } X tenwarned++; X } X if (now >= (nowsecs + 300)) { X if (!fivewarned) { X mvaddstr(23,20,"5 Minute warning!!!!"); X clrtoeol(); X beep(); X } X fivewarned++; X } X if (now >= (nowsecs + 120)) { X if (!twowarned) { X mvaddstr(23,20,">TWO< Minute warning!!!! QUIT NOW!!"); X clrtoeol(); X beep(); X } X twowarned++; X } X if (now >= (nowsecs)) { X mvaddstr(23,20,"TIME HAS EXPIRED"); X clrtoeol(); X beep(); X release(semid); X refresh(); X sleep(10); X acquire(semid); X quit++; /* Exit the game next turn */ X } X } X release(semid); /* Release lock */ X mvaddstr(22,20,"Command -> "); X clrtoeol(); X oldx = extx; X oldy = exty; X extx = extx; X exty = exty; X/* X The purpose of this section of code is to insure that there is X something to do before going off and reading input. If there is X nothing to do, wait a second, then go update the display and try X again. X*/ X key = 0; X refresh(); /* Paint screen */ X nap(NAPTIME); X#ifdef SLOWDOWN X if (((ship->type >= 10) && (shipcount < 5)) || (cheat))/* Marauder... */ X shipcount = 5; /* Nearly always can move... */ X if (shipcount++ <= (ship->type / 3)) {/* If delay not expired */ X nomove = 0; X key = 0; /* No input allowed */ X } else { /* Otherwise... */ X#endif X nomove++; X shipcount = 0; /* Reset counter to zero */ X tempint = rdchkx(0); /* Check stdin for input */ X if (tempint) { /* If key has been hit */ X key = getchx(); /* Read it (special) */ X move(23,20); X clrtoeol(); X } X#ifdef SLOWDOWN X } X#endif X acquire(semid); /* Regain lock on segment */ X X/* End non-portable section */ X if (!status) /* If green */ X qcount = 0; /* Then reset exit marker */ X if ((key >= '0') && (key <= '9')) { X destx = -1; /* Clear if move key hit */ X desty = -1; X } X if (key == 0) { X if ((nomove) && (destx != -1) && (desty != -1)) { X key = give_dir(extx, exty, destx, desty); X if (key == -1) { /* Autopilot */ X destx = -1; X desty = -1; X mvaddstr(23,20,"Arrived at destination, Captain"); X clrtoeol(); X } X } X } X switch (key) { X case 0: X break; X case 24: /* ^X - only superuser */ X if ((getuid() == superuser) || (getuid() == su2)) { X modgame(semid); X oldx = extx; X oldy = exty; X erase(); X } X break; X case 23: /* ^W - only for superuser */ X if ((getuid() == superuser) || (getuid() == su2)){ X window = 20; X erase(); X } X break; X case 3: X if ((getuid() == superuser) || (getuid() == su2)) X cheat ^= (-1); /* Toggle cheat mode */ X break; X case 16: /* ^P - only superuser */ X if ((getuid() == superuser) || (getuid() == su2)) { X ship->points += ship->points; X } X break; X case '+': X release(semid); X execit("drone","drone");/* Execute drone */ X mvaddstr(23,20,"Enemy ship started..."); X clrtoeol(); X acquire(semid); X break; X case 'P': /* PLAYERS command */ X showplayers(semid, docked); X break; X case 'N': /* Name (rename ship) command */ X mvaddstr(22,20,"New Ship Name -> "); X release(semid); X refresh(); X get_str(tempstr); X acquire(semid); X strncpy(ship->name, tempstr, 19); X ship->name[19] = 0; X break; X case 12: X clear(); X break; X case 'Q': X if (status) { X if (++qcount == 1) { X mvaddstr(23,20,"Hit twice more to DESTRUCT"); X clrtoeol(); X } else { X if (qcount == 3) X quit++; X } X } else X quit++; X break; X case '?': X showfile("Help", semid, 1); X break; X case '8': X exty = exty + 1; X break; X case '7': X exty = exty + 1; X extx = extx - 1; X break; X case '1': X exty = exty - 1; X extx = extx - 1; X break; X case '9': X extx = extx + 1; X exty = exty + 1; X break; X case '3': X exty = exty - 1; X extx = extx + 1; X break; X case '2': X exty = exty - 1; X break; X case '4': X extx = extx - 1; X break; X case '6': X extx = extx + 1; X break; X case 'D': X docked = dock(extx, exty, &window); X break; X case 'B': X buildbase(semid, extx, exty); X break; X case 'b': X release(semid); X mvaddstr(22,20,"Broadcast -> "); X clrtoeol(); X refresh(); X get_str(tempstr); X sprintf(tempstr2, "%c: %s", ship->token, tempstr); X acquire(semid); X putmsg(tempstr2); X break; X case 'M': X enter_smove(&destx, &desty, semid); X if ((destx < 0) || (destx >= SIZE) || (desty < 0) || (desty >= SIZE)) { X destx = -1; X desty = -1; X } else { X move(23,20); X sprintf(tmp, "Autopilot engaged, destination %d %d", destx, desty); X addstr(tmp); X clrtoeol(); X } X break; X case 'l': X if (ship->lasers > 30) X phasers(semid, extx, exty); X else X if (roll(200) < ship->lasers) X phasers(semid, extx, exty); X else { X standout(); X mvaddstr(23,20,"Laser malfunction!"); X standend(); X clrtoeol(); X } X break; X case 'm': X if (ship->mines > 30) X mines(semid, extx, exty); X else { X if (roll(200) < ship->mines) X mines(semid, extx, exty); X else { X standout(); X mvaddstr(23,20,"Mine launcher malfunction!"); X standend(); X clrtoeol(); X } X } X break; X case 'S': X scanned = scan(semid, extx, exty, window);/* Look */ X if (scanned) X scancount = 50; X ship->energy -= roll(100); X break; X case 's': X if (ship->shield > 30) X ship->wstatus = ship->wstatus ^ SHIELD_UP; X else { X if (roll(200) < ship->shield) X ship->wstatus = ship->wstatus ^ SHIELD_UP; X else { X standout(); X mvaddstr(23,20,"Shield control malfunction!"); X standend(); X clrtoeol(); X } X } X break; X case 'R': /* Range/RAM Control */ X safe ^= -1; /* XOR it... */ X if (safe) X mvaddstr(23,20,"Ramming SAFETY ON"); X else { X standout(); X mvaddstr(23,20,"Ramming SAFETY OFF"); X standend(); X beep(); X } X clrtoeol(); X break; X case 't': /* Torpedoes! */ X if (ship->torps > 30) { X if (num_torps[ship->type]) X firetorps(extx, exty, torparray, semid, &ntfree, window); X else { X mvaddstr(23,20, "No torpedo capability"); X clrtoeol(); X } X } else { X if (roll(200) < ship->torps) X firetorps(extx, exty, torparray, semid, &ntfree, window); X else { X standout(); X mvaddstr(23,20,"Torpedo tube malfunction!"); X standend(); X clrtoeol(); X } X } X break; X X } X if (extx < 0) X extx = 0; X if (exty < 0) X exty = 0; X if (extx >= SIZE) X extx = SIZE - 1; X if (exty >= SIZE) X exty = SIZE - 1; X X/* Now check to see if the engines are working... */ X X if (ship->engines < 30) { X if (roll(200) > ship->engines) { X extx = oldx; /* If not, no movement! */ X exty = oldy; X standout(); X mvaddstr(23,20, "Engine failure!"); X standend(); X clrtoeol(); X } X } X X/* End Engine check */ X X if ((extx != oldx) || (exty != oldy)) { X docked = 0; /* Undock craft */ X readgrid(extx, exty, &oldgrid); X if (oldgrid.type == VOID) { /* Black hole */ X extx = oldgrid.energy; X exty = oldgrid.shield; /* Get new coords */ X readgrid(extx, exty, &oldgrid);/* Switch! */ X } X if (oldgrid.type != EMPTY) { /* Collision! */ X if ((safe) && (oldgrid.type != MINE)) { X extx = oldx; X exty = oldy; X readgrid(extx, exty, &tempgrid); X tempgrid.energy -= 300; X storegrid(extx, exty, tempgrid); X ship->energy -= 300; X destx = -1; X desty = -1; /* Cancel move */ X mvaddstr(23,20,"Collision avoided!"); X clrtoeol(); X } else { X mvaddstr(23,20, "Collision!"); X tempenergy = oldgrid.energy; X readgrid(oldx, oldy, &onegrid); X oldgrid.energy -= ((onegrid.energy / 2) + 1000); X if (oldgrid.energy < 0) { X if ((oldgrid.type >= 'A') && (oldgrid.type <= 'Z')) { X namebuf.token = oldgrid.type; X tempint = locship(&namebuf, 1); X namebuf.token = 0; X namebuf.name[0] = 0; X storename(tempint, namebuf); X } else { X if (oldgrid.type == MINE) { X mvaddstr(23,20,"The mine explodes!"); X refresh(); X explode(extx, exty, (MINE_BOOM * EXPLOSION), MINE_BOOM); X } else { X X mvaddstr(23,20, "FLASH! The item you hit is DESTROYED!"); X explode(extx, exty, (BIG_BOOM * EXPLOSION), BIG_BOOM); X } X } X clrtoeol(); X oldgrid.type = EMPTY; X } X storegrid(extx, exty, oldgrid); X extx = oldx; /* Go backwards */ X exty = oldy; X if (tempenergy < 0) X tempenergy = 0 - tempenergy; X onegrid.energy -= ((tempenergy / 2) + 1000); X storegrid(extx, exty, onegrid); X } X } else { X move(22,0); X clrtoeol(); X readgrid(oldx, oldy, &onegrid); X X onegrid.energy -= ((int) sqr(((extx - oldx) * (extx - oldx)) + ((exty - oldy) * (exty - oldy))) * (roll(E_RAND_PER_MOVE) + E_PER_MOVE)); X storegrid(extx, exty, onegrid); X onegrid.type = EMPTY; X onegrid.energy = 0L; X onegrid.shield = 0L; X onegrid.align = (char) 0; X storegrid(oldx, oldy, onegrid); X } X } X X readgrid(extx, exty, &onegrid); X if (onegrid.hit) /* If we have been hit */ X docked = 0; /* Undock craft for sure */ X if (docked) { /* If docked with the base */ X tmpint = (roll(RANDADD)+EADD) * ship->type; X onegrid.energy += (tmpint * docked); X ship->energy += (tmpint * docked); X if (onegrid.energy > e_require[ship->type]) { X onegrid.energy = e_require[ship->type]; X ship->energy = e_require[ship->type]; X } X if ((ship->shield < 100) && (ship->shield > 0)) { X if (docked != -1) { X ship->shield++; X onegrid.shield++; X } else { X ship->shield--; X onegrid.shield--; X } X } X if ((ship->engines < 100) && (ship->engines > 0)) X ship->engines += docked; X if ((ship->life < 100) && (ship->life > 0)) X ship->life += docked; X if ((ship->crew < 100) && (ship->crew > 0)) X ship->crew += docked; X if ((ship->hull < 100) && (ship->hull > 0)) X ship->hull += docked; X if ((ship->lasers < 100) && (ship->lasers > 0)) X ship->lasers += docked; X if ((ship->mines < 100) && (ship->mines > 0)) X ship->mines += docked; X if ((ship->torps < 100) && (ship->torps > 0)) X ship->torps += docked; X if (docked != -1) { X ship->numtorps++; X ship->nummines++; X } else { X ship->numtorps--; X ship->nummines--; X } X } X if (energy_count == 0) { /* If it's time */ X if ((ship->shield < 100) && (ship->shield > 0)) { X ship->shield++; X onegrid.shield++; X } X if ((ship->engines < 100) && (ship->engines > 0)) X ship->engines += 1; X if ((ship->life < 100) && (ship->life > 0)) X ship->life += 1; X if ((ship->crew < 100) && (ship->crew > 0)) X ship->crew += 1; X if ((ship->hull < 100) && (ship->hull > 0)) X ship->hull += 1; X if ((ship->lasers < 100) && (ship->lasers > 0)) X ship->lasers += 1; X if ((ship->torps< 100) && (ship->torps> 0)) X ship->torps += 1; X if ((ship->mines < 100) && (ship->mines> 0)) X ship->mines += 1; X } X if (ship->shield > 100) { X ship->shield = 100; X onegrid.shield = 100; X } X if (ship->engines > 100) X ship->engines = 100; X if (ship->life > 100) X ship->life = 100; X if (ship->crew > 100) X ship->crew = 100; X if (ship->hull > 100) X ship->hull = 100; X if (ship->torps > 100) X ship->torps = 100; X if (ship->lasers > 100) X ship->lasers = 100; X if (ship->mines > 100) X ship->mines = 100; X if (ship->numtorps > num_torps[ship->type]) X ship->numtorps = num_torps[ship->type]; X if (ship->nummines > num_mines[ship->type]) X ship->nummines = num_mines[ship->type]; X if (ship->nummines < 0) X ship->nummines = 0; X if (ship->numtorps < 0) X ship->numtorps = 0; X storegrid(extx, exty, onegrid); X } X sprintf(tmp, "%s (%c) leaves COSMOS", ship->name, ship->token); X putmsg(tmp); X if ((!status) && (!limited)) X saveship(extx, exty); /* Save position */ X clear(); X refresh(); X endwin(); X printf("Leaving the game with %d points\n", ship->points); X readgrid(extx, exty, &onegrid); /* Delete ship */ X onegrid.type = EMPTY; X storegrid(extx, exty, onegrid); X namebuf.token = ship->token; X tempint = locship(&namebuf, 1); X namebuf.token = 0; X namebuf.name[0] = 0; X storename(tempint, namebuf); X release(semid); X puts("Good bye!"); X shmdt(buffer); /* Detach shared segment */ X#ifdef ACCOUNTING X delplayer(argc, argv[1]); X#endif X exit(0); X} END_OF_FILE if test 23237 -ne `wc -c <'cosmos.c'`; then echo shar: \"'cosmos.c'\" unpacked with wrong size! fi # end of 'cosmos.c' fi if test -f 'funcs.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'funcs.c'\" else echo shar: Extracting \"'funcs.c'\" \(17674 characters\) sed "s/^X//" >'funcs.c' <<'END_OF_FILE' X/* Spacewar - The final frontier X X This package is Copyright 1988 Karl Denninger. All rights reserved. X X All unauthorized mutants shall be destroyed, fed to vermin, and the X remains from this process will be prosecuted. X X*/ X X/* Definitions go below - Make sure you have these in front of include X files as these definitions should override the include files */ X X#include "cosmos.h" X extern char *buffer; extern int quit; extern char home[128]; X extern struct nameblock *ship; extern struct nameblock name[MAXSHIPS]; extern struct grid onegrid; extern int extx, exty, window; X extern int oldchar; /* The character pre-read */ extern int foundchar; /* If one was pre-read */ X extern int drone; /* If this is a drone ship */ extern int squares[]; X char xq[2] = {7, 0}; X execit(file, arg0) char *file; char *arg0; X{ X if (!fork()) { /* If child */ X close(0); X close(1); X close(2); X setpgrp(); X execlp(file, arg0, (char *) NULL); X exit(0); X } X return; X} X void die() X{ X signal(SIGHUP, SIG_IGN); /* Ignore further hangups */ X quit++; /* Insure we exit */ X return; X} X sqr(x) int x; X{ X int last[2]; X int llim = 0; X int ulim = SIZE; X int p; X X last[0] = (SIZE / 2); X last[1] = 0; X X if (!x) X return(0); X while (x != squares[last[0]]) { X if ((squares[last[0]] <= x) && (squares[last[0] + 1] > x)) X return(last[0]); X if (squares[last[0]] < x) { /* If we're too low */ X llim = last[0]; /* Lower limit reset */ X p = last[0] + ((ulim - last[0]) / 2); X last[1] = last[0]; X last[0] = p; X } else { X ulim = last[0]; /* If too high */ X p = last[0] - ((last[0] - llim) / 2); X last[1] = last[0]; X last[0] = p; X } X } X return(last[0]); X} X X void clrin() X{ X X signal(SIGINT, clrin); /* Reset handler */ X ioctl(0, TCFLSH, 0); /* Flush input */ X return; X} X void beep() X{ X X write(1, xq, 1); X return; X} X X#ifndef M_TERMINFO X char *get_str(string) /* Get a string with proper echoing */ char *string; X{ X char *ptr; X int key; X X ptr = string; X while ((key = getchx()) != 10) { /* While not newline */ X if (key == 13) X return(string); X if ((key == 8) || (key == 127)) { /* Backspace? */ X if (ptr != string) { /* If not empty */ X ptr--; X *ptr = 0; X addch(8); X addch(32); X addch(8); X } else X continue; X } else { X *ptr = key; X ptr++; X addch(key); X } X refresh(); X } X *ptr = 0; /* Null terminate */ X refresh(); X return(string); X} X X#else X get_str(string) char *string; X{ X X echo(); X getstr(string); X noecho(); X return; X} X#endif X X/* Give direction code from source to destination */ X give_dir(x, y, destx, desty) int x; int y; int destx; int desty; X{ X int xx, yy; X int key = 0; X X xx = abs(x - destx); /* Get absolute distances */ X yy = abs(y - desty); X if (!xx && !yy) /* If both are 0 away... */ X return(-1); /* We are there */ X if (xx == yy) { /* If equal then use diagonal */ X if ((x < destx) && (y < desty)) /* If going up and right */ X key = '9'; /* Enter '9' */ X if ((x < destx) && (y > desty)) /* If going down and right */ X key = '3'; /* Enter '3' */ X if ((x > destx) && (y < desty)) /* If going up and right */ X key = '7'; /* Enter '1' */ X if ((x > destx) && (y > desty)) /* If going up and right */ X key = '1'; /* Enter '7' */ X } else { /* Otherwise move horiz. */ X if (xx > yy) { /* If 'x' axis is longer */ X if (x < destx) /* If we're left of dest */ X key = '6'; /* Move that way */ X else X key = '4'; /* If we're right of dest */ X } else { X if (y < desty) /* If we're left of dest */ X key = '8'; /* Move that way */ X else X key = '2'; /* If we're right of dest */ X } X } X return(key); /* Return direction code */ X} X enter_smove(x, y, semid) int *x, *y; int semid; X{ X static char line[80]; X int key; X char tmp[80]; X X if (ship->type < 3) { /* If a dinky ship return */ X mvaddstr(23,20,"Captain, we don't have a navigational mode."); X clrtoeol(); X return(0); X } X release(semid); X mvaddstr(22,20,"Destination -> "); X refresh(); X get_str(tmp); X acquire(semid); X if (tmp[0] == 0) { /* If line is blank */ X if (line[0] == 0) /* If no prior move */ X return(0); /* do nothing at all */ X strcpy(tmp, line); /* Otherwise resume old destination */ X move(23,20); X printw("Resuming course to %s", tmp); X } else X strcpy(line, tmp); /* Save coordinates for later use */ X return(sscanf(tmp, "%d %d", x, y)); X} X X/* This routine locates the closest of an object or class of objects within X the screen window. Used all over the place, especially by the drone. */ X int findobj(x, y, dist, lowobj, highobj, window)/* Locate direction */ int *x, *y; /* Current location */ int *dist; /* Distance to object */ int lowobj, highobj; /* Object desired */ int window; X X{ X struct grid ourgrid; /* Grid entry */ X int xx, yy; /* Temporary storage for search */ X int retval = 0; X int xr, yr; X int lastfound; X int dx, dy, dt; X X lastfound = (window/2) + 1; /* Initial location vector */ X for (xx = (*x - (window/2)); xx <= (*x + (window/2)); xx++) { X for (yy = (*y - (window/2)); yy <= (*y + (window/2)); yy++) { X if ((xx >= 0) && (xx < SIZE) && (yy >= 0) && (yy < SIZE)) { X readgrid(xx, yy, &ourgrid); X dx = abs(xx - *x); X dy = abs(yy - *y); X if (dx > dy) X dt = dx; X else X dt = dy; X if ((ourgrid.type >= lowobj) && X (ourgrid.type <= highobj) && X (ourgrid.type != ship->token) && X#ifdef FASTMATH X (sqr((dx * dx) + (dy * dy)) < lastfound) X ) { X lastfound = (int) sqr((dx * dx) + (dy * dy)); X#else X (dt < lastfound) X ) { X lastfound = dt; X#endif X retval = give_dir(*x, *y, xx, yy); X xr = xx; yr = yy; X } X } X } X } X *dist = lastfound; /* Show distance to target */ X *x = xr; /* Where it was found */ X *y = yr; /* in x,y notation system */ X return(retval); /* Exit w/character to get there */ X} X X X#ifdef NO_RDCHK X int getchx() X X{ X int chx; X if (!foundchar) { X read(0,&chx,1); X return(chx & 127); X } else { X foundchar = 0; X return(oldchar & 127); X } X} X X int rdchkx(fd) int fd; X{ X char chx[2]; X int flagtx; X int tmpx; X X if (foundchar == 0) { X flagtx = fcntl(0, F_GETFL, 0); /* Get flags */ X flagtx |= O_NDELAY; /* turn O_NDELAY on */ X fcntl(0, F_SETFL, flagtx); /* Set it */ X tmpx = read(0, chx, 1); X if (tmpx > 0) { X foundchar++; /* We have one */ X oldchar = chx[0]; /* Save the character */ X } X flagtx = fcntl(0, F_GETFL, 0); /* Get flags */ X flagtx &= ~O_NDELAY; /* turn O_NDELAY on */ X fcntl(0, F_SETFL, flagtx); /* Set it */ X } X return(foundchar); /* Tell 'em if read */ X} X X#else X rdchkx(fid) int fid; X{ X return(rdchk(fid)); X} X getchx() X{ X return(getch()); X} X X#endif X extern void givedamage(); X X int proximity(x, y, unit, distance, itemx, itemy) int x, y; int unit; int distance; int *itemx, *itemy; X{ X struct grid mygrid; X int xx, yy; X int exitval = 0; X X for (xx = (x - distance); xx <= (x + distance); xx++) { X for (yy = (y - distance); yy <= (y + distance); yy++) { X if ((xx != x) || (yy != y)) { X readgrid(xx, yy, &mygrid); X if (unit) { X if (mygrid.type == unit) { X exitval = 1; X *itemx = xx; X *itemy = yy; X break; X } X } else { X X if ((mygrid.type >= 'A') && (mygrid.type <= 'Z')) { X exitval = 1; X *itemx = xx; X *itemy = yy; X break; X } X if (mygrid.type == BASE) { X exitval = 2; X *itemx = xx; X *itemy = yy; X break; X } X } X } X } X } X return(exitval); X} X void explode(x, y, energy, dia) /* Explode - take damage next to boom */ int x, y, energy; int dia; /* Diameter of the blast */ X X/* This can be recursively called, do not use static variables! */ X X{ X int xx, yy; X struct grid expgrid; X char tmp[80]; X int radius; X int dx, dy, dt; X X radius = dia / 2; /* Divide by 2, produce radius */ X X sprintf(tmp, "Explosion at %d %d!", x, y); X putmsg(tmp); X if (drone == 0) X refresh(); X for (xx = (x - radius); xx <= (x + radius); xx++) { X for (yy = (y - (radius)); yy <= (y + (radius)); yy++) { X if ((xx >= 0) && (xx < SIZE) && (yy >= 0) && (yy < SIZE )) { X dx = abs(xx - x); X dy = abs(yy - y); X if (dx > dy) X dt = dx; X else X dt = dy; X readgrid(xx, yy, &expgrid); X if ((xx != x) || (yy != y)) { X#ifdef FASTMATH X givedamage(xx, yy, (int) energy / (int) sqr(((dx * dx) + (dy * dy))), (char *) NULL, 1); X#else X givedamage(xx, yy, (int) energy / dt, (char *) NULL, 1); X#endif X } X } X } X } X return; X} X void showplayers(semid, docked)/* Show the players in the game */ int semid; int docked; X{ X int x, count; X struct nameblock entry; X struct passwd *psw; X X release(semid); X erase(); X if (docked) X mvaddstr(1,15,"Ships in Use - From The Galactic Intelligence Agency"); X else X mvaddstr(1,15," Your ships' status in points, class & token"); X mvaddstr(3,0,"Tkn User Ship Name Class Points"); X x = 4; X count = 0; X while (count < MAXSHIPS) { X readname(count, &entry); X if (entry.token) { X if (entry.human) X psw = getpwuid(entry.uid); X else X psw = NULL; X if (entry.token == ship->token) X standout(); X if ((entry.token == ship->token) || (docked)) { X entry.name[MAXNAME-1] = 0;/* Just in case */ X mvaddch(x,1,entry.token); X if ((psw != NULL) && (entry.human)) X mvaddstr(x,6,psw->pw_name); X mvaddstr(x,20,entry.name); X move(x,44); X addstr(shiptypes[entry.type]); X move(x,61); X printw("%ld", entry.points);/* Current points */ X x++; X } X if (entry.token == ship->token) X standend(); X } X count++; X } X mvaddstr(23,0,"<<>> To Continue Your Game (others are still playing!)"); X refresh(); X x = getchx(); X erase(); X acquire(semid); X return; X} X int cdock(x, y, window) int x, y; int *window; X{ X int xx, yy; X int dist; X int located; X X xx = x; yy = y; X located = findobj(&xx, &yy, &dist, BASE, BASE, *window); X if ((abs(xx - x) < 2) && (abs(yy - y) < 2)) { X while (ship->points > pts[ship->type]) { X ship->type++; X ship->energy = (long) e_require[ship->type]; X *window = window_size[ship->type]; /* Change viewer */ X } X return(1); X } else X return(0); X} X int dock(x, y, window) int x, y; int *window; X{ X X int xx = -1; X int yy = -1; X int retval = 0; X struct grid tmpgrid; X int negbase; X X for (xx = -1; xx < 2; xx++) { X for (yy = -1; yy < 2; yy++) { X if (((xx + x) >= 0) && ((yy + y) >= 0) && ((xx + x) < SIZE) && ((yy + y) < SIZE)) { X readgrid((x + xx), (y + yy), &onegrid); X if ((onegrid.type == BASE) || (onegrid.type == NEGBASE)) { X if (onegrid.align == ship->align ) { X retval++; X negbase = onegrid.type; X } else { X mvaddstr(23,20,"Not your alliance!"); X clrtoeol(); X } X } X } X } X } X if (retval == 0) { X mvaddstr(23,20,"Nothing to dock with in range Sir."); X clrtoeol(); X } else { X while (ship->points > pts[ship->type]) { X beep(); X (ship->type)++; X move(23,20); X printw("Congratuations! You now command a %s", shiptypes[ship->type]); X clrtoeol(); X *window = window_size[ship->type]; /* Change viewer */ X ship->energy = e_require[ship->type]; /* Get max energy */ X clear(); X readgrid(x, y, &tmpgrid); X tmpgrid.energy = ship->energy; X storegrid(x, y, tmpgrid); X } X } X if (negbase == '-') X retval = -1; X return(retval); X} X putmsg(msg) char *msg; X X{ X X char *ptr; X struct grid onegrid; X struct nameblock name; X int *cur_msg; X long sizegrid; X int msgnum; X X sizegrid = (sizeof(onegrid) * SIZE * SIZE); X cur_msg = (int *) (buffer + sizeof(ccount) + (sizeof(name) * MAXSHIPS) + sizegrid); X msgnum = *cur_msg; X ptr = (char *) cur_msg; /* Get pointer */ X ptr += sizeof(msgnum); /* Point past index */ X ptr += (msgnum * MSGLEN); /* Point to next msg to store */ X strncpy(ptr, msg, 39); /* Store message */ X *(ptr + 35) = 0; /* Null terminate at 35 chars */ X msgnum++; X if (msgnum >= MAXMSG) X msgnum = 0; X *cur_msg = msgnum; X return(0); X} X dspmsg() X{ X X static int current_msg; X static int last_placed = 0; X int dispmsg; X char *ptr; X struct grid onegrid; X struct nameblock name; X static char msg0[40] = {0}; X static char msg1[40] = {0}; X static char msg2[40] = {0}; X static char msg3[40] = {0}; X int *iptr; X X iptr = (int *) (buffer + sizeof(ccount) + (sizeof(name) * MAXSHIPS) + (sizeof(onegrid) * SIZE * SIZE)); X current_msg = *iptr++; X ptr = (char *) iptr; X while (last_placed != current_msg) { X strcpy(msg3, msg2); /* Everyone down one */ X strcpy(msg2, msg1); X strcpy(msg1, msg0); X strcpy(msg0, (ptr + (MSGLEN * last_placed))); X last_placed++; X if (last_placed == MAXMSG) { X last_placed = 0; X } X } X mvaddstr(21,44,msg0); X clrtoeol(); X mvaddstr(20,44,msg1); X clrtoeol(); X mvaddstr(19,44,msg2); X clrtoeol(); X mvaddstr(18,44,msg3); X clrtoeol(); X return(0); X} X X saveship(x, y) int x, y; X{ X X int uid; X int fid; X char fname[80]; X int count; X struct shiprecord record; X X uid = getuid(); /* Who are we (really) */ X sprintf(fname, "%s/space.scorefile", HOMEDIR); X if ((fid = open(fname, O_RDWR|O_CREAT, 0660)) < 0) { X perror("scorefile"); X endwin(); X return(1); X } X count = 0; X while (read(fid, &record, sizeof(record)) == sizeof(record)) { X if (record.uid == uid) { X count++; /* Found record */ X lseek(fid, 0L - (sizeof(record)), 1); X break; X } X } X record.points = ship->points; X record.uid = uid; X record.type = ship->type; X record.x = x; X record.y = y; X record.energy = ship->energy; X strcpy(record.shipname, ship->name); X if (write(fid, &record, sizeof(record)) != sizeof(record)) X perror("saveship"); X close(fid); X return(0); X} X penalize() X{ X X int uid; X int fid; X char fname[80]; X int count; X struct shiprecord record; X X uid = getuid(); /* Who are we (really) */ X sprintf(fname, "%s/space.scorefile", HOMEDIR); X if ((fid = open(fname, O_RDWR|O_CREAT, 0660)) < 0) { X perror("scorefile"); X endwin(); X return(1); X } X count = 0; X while (read(fid, &record, sizeof(record)) == sizeof(record)) { X if (record.uid == uid) { X count++; /* Found record */ X lseek(fid, 0L - (sizeof(record)), 1); X break; X } X } X if (count > 0) { X record.points = (ship->points / 2); X ship->points = ship->points / 2; X record.uid = uid; X if (record.type > 1) /* Demoted... */ X record.type--; X record.energy = e_require[record.type]; /* Energy starting */ X record.x = roll(SIZE); X record.y = roll(SIZE); X strcpy(record.shipname, ship->name); X write(fid, &record, sizeof(record)); X } X close(fid); X return(0); X} X X int roll(max) int max; X{ X int x; X int mult; X X mult = 32767/max; /* Counts per unit */ X x = rand(); X return(x / mult); X} X X int locship(entry, flag) struct nameblock *entry; int flag; X X{ X int b = 0; X static int match; /* Match indicator */ X struct nameblock locbuf; X X match = -1; X while (b < MAXSHIPS) { X readname(b, &locbuf); X if (flag == 0) { X if (strcmp(locbuf.name, entry->name) == 0) { X match = b; X break; X } X } else { X if (locbuf.token == entry->token) { X match = b; X break; X } X } X b++; X } X return(match); X} X X X X acquire(semid) int semid; X{ X semoper(semid, -1); X} X release(semid) int semid; X{ X semoper(semid, 1); X} X semoper(semid, op) int semid; int op; X X{ X struct { X short sem_num; X short sem_op; X short sem_flg; X } sembuf; X X sembuf.sem_num = 0; X sembuf.sem_op = op; X sembuf.sem_flg = 0; X signal(SIGINT, SIG_IGN); X if (semop(semid, &sembuf, 1) == -1) { X if (drone == 0) X endwin(); X perror("semop"); X puts("FATAL ERROR: Please re-run the game"); X exit(1); X } X signal(SIGINT, clrin); X} X showfile(file, semid, ind) char *file; int semid; int ind; X{ X int x = 0, y; X FILE *fid; X char tmp[80]; X int key; X X release(semid); X clear(); X sprintf(tmp, "%s/%s", HOMEDIR, file); X if ((fid = fopen(tmp, "r")) == NULL) { X acquire(semid); X return; X } X if (ind) { X x = 2; X mvaddstr(0,0,"--> COSMOS Online Library Display Status >> "); X mvaddstr(1,0,"-------------------------------------------------------------------------------"); X } else X x = 0; X while (fgets(tmp, 80, fid) != NULL) { X if (x >= 22) { X if (ind) { X mvaddstr(22,0,"-------------------------------------------------------------------------------"); X } X mvaddstr(23,0," <<<< SPACE >>>> for the next page, to quit"); X if (ind) { X while (!rdchkx(0)) { X if (calcstatus(extx, exty, window, 0)) { X standout(); X mvaddstr(0,60,"RED"); X standend(); X } else X mvaddstr(0,60,"GREEN"); X clrtoeol(); X refresh(); X sleep(1); X } X } X refresh(); X key = getchx(); X if (ind) { X for (y = 2; y < 22; y++) { X move(y, 0); X clrtoeol(); X } X } else { X for (y = 0; y < 23; y++) { X move(y, 0); X clrtoeol(); X } X } X if ((key == 'q') || (key == 'Q')) { X acquire(semid); X erase(); X return; X } X if (ind) X x = 2; X else X x = 0; X } X mvaddstr(x++, 0, tmp); X clrtoeol(); X } X fclose(fid); X refresh(); X (void) getchx(); X erase(); X acquire(semid); X return; X} X readname(x, entry) int x; struct nameblock *entry; X{ X struct nameblock locrec; X char *ptr; X X ptr = buffer + sizeof(ccount) + (sizeof(locrec) * x); X memcpy(entry, ptr, sizeof(locrec)); X return(0); X} X char *storename(x, entry) int x; struct nameblock entry; X{ X char *ptr; X X ptr = buffer + sizeof(ccount) + (sizeof(entry) * x); X return((char *) memcpy(ptr, &entry, sizeof(entry))); X} X readgrid(x, y, entry) int x; int y; struct grid *entry; X X{ X int incr; X char *ptr; X long *ptrl; X X incr = sizeof(ccount) + sizeof(name) + (x * sizeof(onegrid) * SIZE); X incr += y * sizeof(onegrid); X ptr = (buffer + incr); X memcpy(entry, ptr, sizeof(onegrid)); X return(0); X} X storegrid(x, y, entry) int x; int y; struct grid entry; X{ X int incr; X char *ptr; X X incr = sizeof(ccount) + sizeof(name) + (x * sizeof(onegrid) * SIZE); X incr += y * sizeof(onegrid); X ptr = (buffer + incr); X memcpy(ptr, &entry, sizeof(entry)); X return(0); X} END_OF_FILE if test 17674 -ne `wc -c <'funcs.c'`; then echo shar: \"'funcs.c'\" unpacked with wrong size! fi # end of 'funcs.c' fi echo shar: End of archive 3 \(of 3\). cp /dev/null ark3isdone 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 -- Karl Denninger (karl@ddsw1.MCS.COM, ddsw1!karl) Data: [+1 312 566-8912], Voice: [+1 312 566-8910] Macro Computer Solutions, Inc. "Quality solutions at a fair price"