karl@ddsw1.MCS.COM (Karl Denninger) (11/18/88)
This is the first of three archives containing COSMOS, a multiuser space game for Xenix machines. Note that this code is SPECIFIC to Xenix V/386. It MIGHT run on System V 80386 machines, the further you get away from this the less likely you are to have success. In particular, you absolutely must have: o SVID-compliant shared memory and semaphores. o A large segment size (500K or so), or a completely flat address space. o Paging would be nice :-) o A working curses. o A 'nap' call is highly recommended (short sleep). FORGET EVEN TRYING to run this on a '286 -- it won't work. On Microport, it won't even compile without severely crippling the size of the grid. NOTE: This is shareware, but not crippleware. If you don't want it, then don't keep it. Flames to /dev/null. #! /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 <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 1 (of 3)." # Contents: Makefile Manifest README buildbase.c dispstatus.c # getship.c givedamage.c makechoice.c mines.c modgame.c phasers.c # players.c rmseg.c scan.c # Wrapped by karl@ddsw1 on Thu Nov 17 23:53:03 1988 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'Makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Makefile'\" else echo shar: Extracting \"'Makefile'\" \(1538 characters\) sed "s/^X//" >'Makefile' <<'END_OF_FILE' X# X# Makefile for Space - a multiuser game X# X# Copyright 1988 Macro Computer Solutions, Inc and Karl Denninger. X# X# All rights reserved. X# X# Unauthorized duplication, distribution, or modification is X# prohibited by Federal and State law and will be prosecuted under X# civil and criminal law. X CC=cc X# X# First CFLAGS line is for terminfo, others for termcap X# CFLAGS= -s -DM_TERMINFO -Ox -DVERSION=\"0.9.9B\" -DSYSID=\"386\" -DSYSV X#CFLAGS= -s -DM_TERMCAP -Ox -Dcbreak=crmode -DVERSION=\"0.9.9B\" -DSYSID=\"386\" -DSYSV LDFLAGS= -s -o X# X# Now we have two library call lines, first for terminfo, then termcap X# LIBS= -lcurses -lx -lm X#LIBS= -ltcap -ltermcap -lx -lm X# X# Then the rest of the stuff X# INC_DEP=/usr/include/stdio.h\ X /usr/include/sys/types.h\ X /usr/include/fcntl.h\ X /usr/include/signal.h\ X /usr/include/setjmp.h\ X /usr/include/pwd.h\ X /usr/include/termio.h\ X /usr/include/sys/file.h\ X /usr/include/memory.h\ X cosmos.h XFILES= cosmos.o\ X funcs.o\ X dispstatus.o\ X getship.o\ X buildbase.o\ X phasers.o\ X givedamage.o\ X mines.o\ X scan.o\ X modgame.o\ X torpedoes.o\ X players.o X all: cosmos rmseg drone X cosmos: $(INC_DEP) $(FILES) X $(CC) $(LDFLAGS) cosmos $(FILES) $(LIBS) X rmseg: $(INC_DEP) rmseg.o X $(CC) $(LDFLAGS) rmseg rmseg.o X drone: $(INC_DEP) drone.o funcs.o givedamage.o getship.o dispstatus.o \ X buildbase.o phasers.o makechoice.o torpedoes.o X $(CC) $(LDFLAGS) drone drone.o funcs.o givedamage.o getship.o \ X dispstatus.o buildbase.o phasers.o makechoice.o torpedoes.o -lcurses -lx -lm X clean: X rm drone cosmos rmseg *.o END_OF_FILE if test 1538 -ne `wc -c <'Makefile'`; then echo shar: \"'Makefile'\" unpacked with wrong size! fi # end of 'Makefile' fi if test -f 'Manifest' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Manifest'\" else echo shar: Extracting \"'Manifest'\" \(734 characters\) sed "s/^X//" >'Manifest' <<'END_OF_FILE' X File Name Archive # Description X----------------------------------------------------------- X Help 2 X Makefile 1 X Manifest 1 This shipping list X README 1 X buildbase.c 1 X cosmos.c 3 X cosmos.h 2 X dispstatus.c 1 X drone.c 2 X funcs.c 3 X getship.c 1 X givedamage.c 1 X makechoice.c 1 X mines.c 1 X modgame.c 1 X phasers.c 1 X players.c 1 X rmseg.c 1 X scan.c 1 X torpedoes.c 2 END_OF_FILE if test 734 -ne `wc -c <'Manifest'`; then echo shar: \"'Manifest'\" unpacked with wrong size! fi # end of 'Manifest' fi if test -f 'README' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'README'\" else echo shar: Extracting \"'README'\" \(6745 characters\) sed "s/^X//" >'README' <<'END_OF_FILE' Welcome to COSMOS! X This is the first public release of the COSMOS game for Xenix and some Unix machines. We hope you will find it to be a fun diversion from your normal routine -- but be careful not to become addicted to it! X X The following is our statement of policy with regards to the COSMOS package and it's copyright, as well as general information on porting and compatibility. X XFirst, the dry stuff we have to dispense with: X COSMOS is Copyright 1988 by MCS, Inc. and Karl Denninger All component files in this 'shar' archive are considered covered by this copyright, both individually and as a compilation. All rights reserved. X Limited distribution rights are granted to the public as follows: X o Non-profit distribution of this SHAR file, in it's entirety, is permitted X freely. If modifications are made, the unmodified files MUST be provided in X any and all derivitive works. X o Non-profit and personal use of this software is permitted on an X unrestricted basis. X o No derivitive or direct product of this work, whether composed of this X package in whole or part, may be sold or used for profit without the express X written consent of MCS, Inc. and Karl Denninger. "Profit" shall be defined X as monetary compensation in excess of direct costs for the transfer of code X or documentation contained in COSMOS, or compensation paid to secure the X right to execute COSMOS on a host CPU. (If in doubt, ask. In general, X having COSMOS available on a pay-for system is ok, as long as you don't X charge specifically for COSMOS' use). X o Copyright notices and any other legends or trademarks must not be removed X from the software and any accompanying documentation. X X COSMOS is SHAREWARE. We request a $25.00 donation for each executing CPU. In return, you'll be placed on our mailing list and alerted to new versions of COSMOS, as well as receiving a nicely-printed users manual. It is expected that after evaluating the game, you will either remove it from use or register the package. X Please send checks to: X Macro Computer Solutions, Inc. X415 S.E. Garfield Mundelein, IL 60060 Attn: COSMOS Shareware X X X DISCLAIMER OF WARRANTY AND LIABILITY. X MCS and Karl Denninger hereby disclaim any and all warranties and liabilities with regards to this package. COSMOS is provided "as is", and the user is warned that there is no guarantee of completeness or correctness, nor of fitness for any purpose whatsoever. The user is wholly responsible for the results of compiling and using COSMOS, without limitation. X X Installation: X COSMOS is designed to execute on a SCO Xenix V/386 installation. As such, it should compile without changes in it's supplied form. Other operating systems may require SUBSTANTIAL modifications. To be able to support COSMOS, you require at a minimum: X o Shared memory support per SVID (SVR2 or better) o Semaphore support, per SVID. o A segment size limitation (if any) in excess of 500K. Linear address X spaces are highly preferred. This package WILL NOT run on a 80286. Don't X even bother trying. X o A working CURSES implementation. X X Highly recommended: o A 'nap()' system call (short sleep). X X If you have all the items noted above, you can probably build COSMOS. If you're on a Xenix V/386 machine, you'll certainly be able to do so (in fact, it should build without modifications). X Do all the usual things, peek in the Makefile and cosmos.h to make sure things look reasonable to you, and type 'make'. X Place the binary files (cosmos and drone) in a publically-locatable directory. The executable 'rmseg' is provided to clean up after the COSMOS game; it removes the shared segment and semaphore identifiers if needed. X X To install: X Make a directory, and place the Help and Hello files in it. Make these world readable. SGID cosmos, in a binary directory, to your games group X(which should also own the directory you have the Help in). X Create /etc/cosmos, in the form: X X/pub/games/lib/cosmos/ 100 101 6 120 120 480 X XFields: X X1. Base directory: where to find the Help and Hello files, as well as the X place you want COMSOS to keep it's scorefile. Should NOT be publically X accessible (660 is a good mode). X X2. First "god user" UID. X3. Second "god user" UID. X X Both of these users can use the ^X, ^W and ^P functions. X X4. The number of drone ships you will allow to be in the game. X WARNING: If this is too large, you'll have a VERY slow system! :-) 6 is X reasonable for most 80386 machines. X X5. Time limit values for captive users. Currently incomplete, these values X are used if ACCOUNTING is #defined in cosmos.h You may put any values X you wish in here at present, but they MUST be present. X XExit the editor and make sure this file is readable by the COSMOS group. X Once this has been done, you are ready to play. Type 'cosmos' to start. All documentation is online. X X X THEORY OF OPERATION X COSMOS is a shared-memory real-time space adventure. It is designed around a single semaphore for locking, and a large shared memory segment for data storage. All information that is considered globally "accurate" is contained in this shared segment, which is created by the first player entering the game. X The game system meters out time in discrete "chunks", the size of which are under the control of the system installer. Drone ships operate using the same rules and strategy as the human players, but are penalized slightly to allow the humans some semblance of a chance in combat. X COSMOS is designed to decommission drones when there are no human players in the game. After a few turns, the drones will put themselves to sleep until one or more players reenter the game. X X RESOURCE CONSUMPTION X COSMOS requires about 500K of shared memory in it's default configuration. When the game is in play, this is mapped into each players virtual process space, and thus consumes physical memory. During quiescent times of no playing, the operating system should page this segment out to disk. X Drones are likewise stopped, but the process(es) in question continue to remain alive on the system, albiet in suspended animation. X If this is a concen, you may modify the drone code to exit when they detect a lack of human players. Similarly, it would be simple to add the required support to delete the shared segment and semaphore when the last process exits, although this is not currently done (not doing so keeps the game grid around for the next player). X Of course, system reboots and crashes will cause the segment to be removed :-) X X XEnjoy -- and watch that load average! X X-- 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" END_OF_FILE if test 6745 -ne `wc -c <'README'`; then echo shar: \"'README'\" unpacked with wrong size! fi # end of 'README' fi if test -f 'buildbase.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'buildbase.c'\" else echo shar: Extracting \"'buildbase.c'\" \(3900 characters\) sed "s/^X//" >'buildbase.c' <<'END_OF_FILE' X/* Base Building routines X Contains routines for both player and computer people.... */ X X/* Copyright 1988 Karl Denninger & MCS, Inc. X All rights reserved */ X X X#include "cosmos.h" X extern char *buffer; extern int drone; extern struct nameblock *ship; X cbuildbase(semid, x, y, window) int semid; int x, y; int window; X X{ X X int kb; X int xx, yy; X int dist; X struct grid onegrid; X struct grid anothergrid; X char tmp[80]; X X release(semid); X xx = x; yy = y; X kb = findobj(&xx, &yy, &dist, PLANET, PLANET, window); X acquire(semid); X xx = 0; yy = 0; X switch(kb) { X case '8': X xx = 0; yy = 1; X break; X case '9': X xx = 1; yy = 1; X break; X case '6': X yy = 0; xx = 1; X break; X case '3': X yy = -1; xx = 1; X break; X case '2': X xx = 0; yy = -1; X break; X case '1': X xx = -1; yy = -1; X break; X case '4': X xx = -1; yy = 0; X break; X case '7': X xx = -1; yy = 1; X break; X } X xx += x; X yy += y; X readgrid(xx, yy, &onegrid); X if (onegrid.type == PLANET) { /* If now a planet */ X onegrid.shield += 10; /* Add one shield level */ X printf("Build %d\n", (onegrid.shield/10)); X fflush(stdout); X ship->energy -= BUILDCOST; /* It's expensive! */ X ship->points += 50; /* One point for a build */ X readgrid(x, y, &anothergrid); X anothergrid.energy = ship->energy; X storegrid(x, y, anothergrid); X } else { /* Can't build anything else */ X return(0); X } X if (onegrid.shield >= 100) { /* If we have a base.. */ X if (roll(200) < 2) X onegrid.type = NEGBASE; /* Change it to a neg. base */ X else X onegrid.type = BASE; /* Change it to a base */ X onegrid.align = ship->align; /* It's yours, or neutral */ X sprintf(tmp, "A new base appears at %d %d", xx, yy); X putmsg(tmp); X ship->points += 200; /* 200 for a base... */ X } X storegrid(xx, yy, onegrid); X release(semid); X sleep(BUILDTIME); /* Sleep for BUILDTIME secs */ X acquire(semid); X return(0); X} X X X buildbase(semid, x, y) int semid; int x, y; X X{ X X int kb; X int xx, yy; X struct grid onegrid; X struct grid anothergrid; X char tmp[80]; X X release(semid); X mvaddstr(22,20,"Build -> "); X clrtoeol(); X refresh(); X kb = getchx(); X acquire(semid); X if (ship->wstatus & SHIELD_UP) { X mvaddstr(23,20,"Captain! We can't deploy troops through the shields!"); X clrtoeol(); X return(0); X } X xx = 0; yy = 0; X switch(kb) { X case '8': X xx = 0; yy = 1; X break; X case '9': X xx = 1; yy = 1; X break; X case '6': X yy = 0; xx = 1; X break; X case '3': X yy = -1; xx = 1; X break; X case '2': X xx = 0; yy = -1; X break; X case '1': X xx = -1; yy = -1; X break; X case '4': X xx = -1; yy = 0; X break; X case '7': X xx = -1; yy = 1; X break; X } X xx += x; X yy += y; X if ((xx < 0) || (xx >= SIZE) || (yy < 0) || (yy >= SIZE)) { X mvaddstr(23,20,"Can't build there"); X clrtoeol(); X return(0); X } X readgrid(xx, yy, &onegrid); X if (onegrid.type == PLANET) { /* If now a planet */ X onegrid.shield += 10; /* Add one shield level */ X move(23,20); X printw("Build %d", (onegrid.shield/10)); X release(semid); X refresh(); X acquire(semid); X ship->energy -= BUILDCOST; /* It's expensive! */ X ship->points += 50; /* One point for a build */ X readgrid(x, y, &anothergrid); X anothergrid.energy = ship->energy; X storegrid(x, y, anothergrid); X } else { /* Can't build anything else */ X mvaddstr(23,20,"Nothing there to build!"); X clrtoeol(); X return(0); X } X if (onegrid.shield >= 100) { /* If we have a base.. */ X if (roll(200) < 2) X onegrid.type = NEGBASE; /* Change it to a neg. base */ X else X onegrid.type = BASE; /* Change it to a base */ X onegrid.align = ship->align; /* It's yours, or neutral */ X sprintf(tmp, "A new base appears at %d %d", xx, yy); X putmsg(tmp); X mvaddstr(23,20,"You have built a BASE!"); X ship->points += 200; /* 200 for a base... */ X } X storegrid(xx, yy, onegrid); X release(semid); X sleep(BUILDTIME); /* Sleep for BUILDTIME secs */ X acquire(semid); X return(0); X} X END_OF_FILE if test 3900 -ne `wc -c <'buildbase.c'`; then echo shar: \"'buildbase.c'\" unpacked with wrong size! fi # end of 'buildbase.c' fi if test -f 'dispstatus.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'dispstatus.c'\" else echo shar: Extracting \"'dispstatus.c'\" \(6141 characters\) sed "s/^X//" >'dispstatus.c' <<'END_OF_FILE' X/* Dispstatus.c */ X X#include "cosmos.h" X extern char *buffer; extern int drone; extern struct nameblock *ship; X calcstatus(x, y, window, docked) /* Calc green/red, no display */ int x, y; int window; int docked; X X{ X int scanx, scany; /* Scanner variables */ X struct grid onegrid; /* One grid entry */ X int scx, scy, tempint, tempx; X int othership = 0; X int ally =0; X int enemy = 0; X long oldenergy; X int xx = 0, yx = 0; X static int retval; X X readgrid(x, y, &onegrid); /* Get present situation */ X ship->shield = onegrid.shield; /* Update */ X oldenergy = ship->energy; X if (onegrid.energy < ship->energy) X ship->energy = onegrid.energy; X scanx = x - (window / 2); /* Start here on each axis */ X scany = y - (window / 2); X scx = 0; X scy = window; X othership = 0; X tempint = scanx; X while (scany <= (y + (window / 2))) { X scx = 0; X scanx = tempint; X while (scanx <= (x + (window / 2))) { X if ((scanx < 0) || (scany < 0) || (scanx >= SIZE) || (scany >= SIZE)) X ; X else { X readgrid(scanx, scany, &onegrid); X if (onegrid.hit) { X if ((scx != x) && (scy != y)) { X if ((onegrid.type < 'A') || (onegrid.type > 'Z')) { X onegrid.hit = 0; X storegrid(scanx, scany, onegrid); X } X } X } X if ((onegrid.type >= 'A') && (onegrid.type <= 'Z')) { X if (onegrid.align == ship->align) { X othership++; X ally++; X } else { X othership++; X enemy++; X } X } X X } X scx++; X scanx++; X } X scany++; X scy--; X } X othership--; /* We'll always be there */ X if (othership == 0) { X retval = 0; X } else { X retval = 1; X } X return(retval); X} X dispstatus(x, y, window, docked) int x, y; int window; int docked; X X{ X int scanx, scany; /* Scanner variables */ X struct grid onegrid; /* One grid entry */ X int scx, scy, tempint, tempx; X int othership = 0; X int ally =0; X int enemy = 0; X long oldenergy; X int xx = 0, yx = 0; X int lastfound; X int dx, dy; X static int retval; X X X for (xx = 0; xx <= (window + 1); xx++) { X mvaddstr(xx,0,"|"); X mvaddstr(xx,(window * 2)+2,"|"); X } X readgrid(x, y, &onegrid); /* Get present situation */ X ship->shield = onegrid.shield; /* Update */ X oldenergy = ship->energy; X if (onegrid.energy < ship->energy) X ship->energy = onegrid.energy; X scanx = x - (window / 2); /* Start here on each axis */ X scany = y - (window / 2); X scx = 0; X scy = window; X move(scy + 1, 1); X for (xx = 0;xx <= (window * 2); xx++) X addstr("="); X lastfound = ((window / 2) + 1); X move(scy + 1, (window - (strlen(">Scanner<") / 2)+1)); X addstr(">Scanner<"); X othership = 0; X tempint = scanx; X while (scany <= (y + (window / 2))) { X scx = 0; X scanx = tempint; X while (scanx <= (x + (window / 2))) { X dx = (scanx - x) * (scanx - x); X dy = (scany - y) * (scany - y); X if ((scanx < 0) || (scany < 0) || X (scanx >= SIZE) || (scany >= SIZE) X#ifdef FASTMATH X || ((int) sqr(dx + dy) >= lastfound) X#endif X ) X mvaddch(scy, (scx * 2)+1, 32); X else { X readgrid(scanx, scany, &onegrid); X if (onegrid.hit) X standout(); X if (docked == -1) X mvaddch(scy, (scx * 2)+1, onegrid.type); X else { X if (onegrid.type == NEGBASE) { X mvaddch(scy, (scx * 2)+1, BASE); X } else { X mvaddch(scy, (scx * 2)+1, onegrid.type); X } X } X if (onegrid.hit) { X standend(); X if ((scx != x) && (scy != y)) { X if ((onegrid.type < 'A') || (onegrid.type > 'Z')) { X onegrid.hit = 0; X storegrid(scanx, scany, onegrid); X } X } X } X if ((onegrid.type >= 'A') && (onegrid.type <= 'Z')) { X if (onegrid.align == ship->align) { X othership++; X ally++; X } else { X othership++; X enemy++; X } X } X X } X scx++; X scanx++; X } X scany++; X scy--; X } X move(0,44); X printw(">> The S.S. %s <<", ship->name); X clrtoeol(); X move(2,59); X printw("Energy... %ld", ship->energy); X clrtoeol(); X move(3,59); X printw("Engines.. %d", ship->engines); X clrtoeol(); X move(4,59); X printw("Lasers... %d", ship->lasers); X clrtoeol(); X move(5,59); X if ((ship->wstatus & MINE_DEAD) == 0) X printw("Mine Lch. %d", ship->mines); X clrtoeol(); X move(6,59); X if ((ship->wstatus & TORPEDO_DEAD) == 0) X printw("Torp Lch. %d", ship->torps); X clrtoeol(); X move(7,59); X printw("Shield... %d", ship->shield); X clrtoeol(); X move(8,59); X printw("Crew Lvl. %d", ship->crew); X clrtoeol(); X move(9,59); X printw("Life Supt %d", ship->life); X clrtoeol(); X move(10,59); X printw("Hull..... %d", ship->hull); X clrtoeol(); X move(11,59); X if (docked) X addstr("Ship..... DOCKED"); X clrtoeol(); X move(12,59); X othership--; /* We'll always be there */ X if (othership == 0) { X printw("Status... GREEN"); X retval = 0; X } else { X retval = 1; X if (ship->wstatus & SHIELD_UP) X printw("Status... YELLOW"); X else X printw("Status... RED"); X } X clrtoeol(); X move(13,59); X if (ship->wstatus & SHIELD_DEAD) X addstr("Shield... INOPERABLE"); X else { X if (ship->wstatus & SHIELD_UP) X addstr("Shield... UP"); X else X addstr("Shield... DOWN"); X } X clrtoeol(); X move(14,59); X if (ship->wstatus & LASERS_DEAD) X addstr("Lasers... INOPERABLE"); X else { X if (ship->wstatus & LASERS_LOCK) X addstr("Lasers... LOCKED"); X else X addstr("Lasers... STBY"); X } X clrtoeol(); X move(15,59); X if (ship->wstatus & MINE_DEAD) X clrtoeol(); X else { X if (ship->wstatus & MINE_LOCK) X addstr("Mines.... LOCKED"); X else X addstr("Mines.... STBY"); X printw(" /%d", ship->nummines); X } X clrtoeol(); X move(16,59); X if (ship->wstatus & TORPEDO_DEAD) X clrtoeol(); X else { X if (ship->wstatus & TORPEDO_LOCK) X addstr("Torps.... LOCKED"); X else X addstr("Torps.... STBY"); X printw(" /%d", ship->numtorps); X } X clrtoeol(); X mvaddstr(17,43,"------------------------------------"); X dspmsg(); /* Show any messages */ X mvaddstr(22,0,"Current Position"); X move(23,0); X printw("X = %3d, Y = %3d", x, y); X if (oldenergy > ship->energy) { X mvaddstr(23,20,"You've been HIT!"); X clrtoeol(); X beep(); X } X if (ship->gods) { X/* mvaddstr(23,20,"You feel a supernatural force nearby"); X clrtoeol(); */ X ship->gods = 0; X } X if (oldenergy < ship->energy) { X mvaddstr(23,20,"Energy transfer to you in progress"); X clrtoeol(); X } X return(retval); X} X END_OF_FILE if test 6141 -ne `wc -c <'dispstatus.c'`; then echo shar: \"'dispstatus.c'\" unpacked with wrong size! fi # end of 'dispstatus.c' fi if test -f 'getship.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'getship.c'\" else echo shar: Extracting \"'getship.c'\" \(5450 characters\) sed "s/^X//" >'getship.c' <<'END_OF_FILE' X/* Getship.c - get a new ship type */ X X#include "cosmos.h" X X#define MAXCPNAMES 21 /* Number of names defined below */ static char *cpname[MAXCPNAMES] = { X "Andrus", "Nomad", "Colossus", "W.O.P.R.", "Joshua", X "James", "Zoonix", "Regula", "Andromeda", "Eteries", X "Freightliner", "Unreliable", "Pegasus", "Sturgeon", "Challenger", X "Enterprise", "Relient", "Excalibur", "Botany Bay", "Columbia", X "Yugo" }; X X extern char *buffer; extern char home[128]; extern int drone; extern struct nameblock *ship; X X X char *getcship(semid, xx, yy) int semid; int *xx, *yy; X X{ X X static struct nameblock shipx; X X struct shiprecord record; X struct passwd *psw; X struct nameblock entry; X int uid; X int fid; X int index; X char fname[80], tmp[80]; X int count; X int quit = 0; X long temp; X int key; X int x; X X strcpy(shipx.name, "_Computer"); X shipx.type = roll(11); /* Select a ship type */ X if (shipx.type == 0) X shipx.type++; X shipx.name[MAXNAME-1] = 0; X#ifdef DEBUG X *xx = 1; X *yy = 1; X#else X *xx = roll(SIZE - 1); X *yy = roll(SIZE - 1); X#endif X shipx.energy = (long) e_require[shipx.type]; /* Get max energy */ X shipx.points = (long) pts[shipx.type - 1]; /* Points to start */ X shipx.shield = 100; X shipx.crew = 100; X shipx.life = 100; X shipx.engines = 100; X shipx.hull = 100; X shipx.lasers = 100; X shipx.torps = 100; X shipx.mines = 100; X shipx.numtorps = num_torps[shipx.type]; /* Copy over config values */ X shipx.nummines = num_mines[shipx.type]; X shipx.wstatus = weapons[shipx.type]; X printf("Computer ship is called the %s, a %s with %ld pts.\n", shipx.name, shiptypes[shipx.type], shipx.points); X fflush(stdout); X quit = 0; X key = 'A'; X while (quit == 0) { X entry.token = key; X if ((index = locship(&entry, 1)) < 0) X quit++; X else X key++; X } X shipx.token = key; X entry.token = 0; X x = locship(&entry, 1); /* Find open slot */ X if (x == -1) { X puts("Too many players!"); X release(semid); X exit(0); X } X sprintf(tmp, "%s %d", cpname[roll(MAXCPNAMES)], (x + 1)); X strcpy(shipx.name, tmp); X storename(x, shipx); X return((char *) buffer + sizeof(ccount) + (sizeof(shipx) * x) ); X} X X char *getship(cx, ptr, semid, xx, yy) int cx; char *ptr; int semid; int *xx, *yy; X X{ X X static struct nameblock shipx; X X int cxx; X struct shiprecord record; X struct passwd *psw; X struct nameblock entry; X int uid; X int fid; X int index; X char fname[80]; X int count; X int quit = 0; X long temp; X int key; X int x; X X cxx = cx; X mvaddstr(1,20,"Ship Assignment - The Admiral's Quarters"); X mvaddstr(3,0,"Tkn Ship Name Class Points"); X x = 4; X count = 0; X while (count < MAXSHIPS) { X readname(count, &entry); X if (entry.token) { X entry.name[MAXNAME-1] = 0; /* Just in case */ X mvaddch(x,0,entry.token); X mvaddstr(x,5,entry.name); X move(x,30); X addstr(shiptypes[entry.type]); X move(x,47); X printw("%ld", entry.points); /* User's points */ X x++; X } X count++; X } X refresh(); 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(fname); X endwin(); X return((char *) NULL); 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 release(semid); X mvaddstr(18,0, "Please name your vessel: "); X refresh(); X get_str(shipx.name); X acquire(semid); X strcpy(record.shipname, shipx.name); X shipx.type = 2; X shipx.points = pts[(shipx.type - 1)]; X record.uid = getuid(); X record.type = 1; X record.points = 0L; X record.energy = e_require[shipx.type]; X write(fid, &record, sizeof(record)); X } else { X shipx.type = record.type; X shipx.points = record.points; X shipx.energy = record.energy; X strncpy(shipx.name, record.shipname, MAXNAME); X shipx.name[MAXNAME-1] = 0; X *xx = record.x; X *yy = record.y; X } X close(fid); X while (shipx.points > pts[shipx.type]) { X shipx.type++; X move(20,0); X standout(); X shipx.energy = 0; /* Make sure you get full tanks */ X printw("Congratuations! You have been promoted to captain of a %s", shiptypes[shipx.type]); X standend(); X clrtoeol(); X } X if (!shipx.energy) X shipx.energy = (long) e_require[shipx.type];/* Max energy */ X shipx.shield = 100; X shipx.crew = 100; X shipx.life = 100; X shipx.engines = 100; X shipx.hull = 100; X shipx.lasers = 100; X shipx.torps = 100; X shipx.mines = 100; X shipx.numtorps = num_torps[shipx.type]; /* Copy over config values */ X shipx.nummines = num_mines[shipx.type]; X shipx.wstatus = weapons[shipx.type]; X while (quit == 0) { X release(semid); X move(21,0); X printw("Your ship is called the %s, a %s with %ld pts.", shipx.name, shiptypes[shipx.type], shipx.points); X clrtoeol(); X mvaddstr(22,0,"Enter desired ship token: "); X refresh(); X if (cxx > 1) { X key = *ptr; X cxx = 1; X } else X key = getchx(); X if ((key >= 'a') && (key <= 'z')) X key = key - 32; X if ((key < 'A') || (key > 'Z')) X continue; X addch(key); X refresh(); X entry.token = key; X acquire(semid); X if ((index = locship(&entry, 1)) >= 0) X mvaddstr(23,0, "In use, try again"); X else X quit++; X } X shipx.token = key; X shipx.uid = getuid(); X entry.token = 0; X x = locship(&entry, 1); /* Find open slot */ X if (x == -1) { X endwin(); X puts("Too many players!"); X release(semid); X return((char *) NULL); X } X storename(x, shipx); X return((char *) buffer + sizeof(ccount) + (sizeof(shipx) * x)); X} END_OF_FILE if test 5450 -ne `wc -c <'getship.c'`; then echo shar: \"'getship.c'\" unpacked with wrong size! fi # end of 'getship.c' fi if test -f 'givedamage.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'givedamage.c'\" else echo shar: Extracting \"'givedamage.c'\" \(4738 characters\) sed "s/^X//" >'givedamage.c' <<'END_OF_FILE' X/* Give Damage to another object */ X X#include "cosmos.h" X extern int drone; extern struct nameblock *shp; X void givedamage(x, y, edmg, shp, explosion) int x, y; int edmg; struct nameblock *shp; int explosion; X{ X int shiedmg; X char tmp[80]; X int xx, hitperson; X struct grid ogrid; X struct nameblock oname; X X shiedmg = edmg / EPERSHIELD; X if (shp != NULL) X shp->points += (edmg / 200); /* Give the hitter points */ X readgrid(x, y, &ogrid); X ogrid.hit++; /* Make it light up */ X if ((ogrid.type == EMPTY) || (ogrid.type == VOID)) {/* Nothing? */ X storegrid(x, y, ogrid); /* Save it back */ X return; /* Get the heck out */ X } X if ((ogrid.type == BASE) || (ogrid.type == NEGBASE)) { X if (ogrid.shield == 100) { X sprintf(tmp, "Base under attack at %d %d", x, y); X putmsg(tmp); X } X if (ogrid.shield > shiedmg) { X ogrid.shield -= shiedmg; X edmg = 0; X } else { X ogrid.shield = 0; X } X ogrid.energy -= edmg; X } X if (shp != NULL) X if (drone == 0) { X move(23,20); X } X if ((ogrid.shield <= 0) && ((ogrid.type == BASE) || (ogrid.type == NEGBASE))) { X if (shp != NULL) { X if (ogrid.align != shp->align) X shp->points += 1000; /* Pts iff not yours */ X } X ogrid.type = PLANET; X ogrid.shield = 0; X storegrid(x, y, ogrid); X if (shp != NULL) X if (drone == 0) { X printw("FLASH! The base is DESTROYED!"); X } X explode(x, y, (BASE_DEATH * EXPLOSION), BASE_DEATH); X } else { X if (shp != NULL) { X if (drone == 0) { X printw("Scored hit on '%c'", ogrid.type); X } X clrtoeol(); X } X } X if ((ogrid.type >= 'A') && (ogrid.type <= 'Z')) { /* A shp? */ X xx = 0; X hitperson = -1; X while (hitperson == -1) { X readname(xx, &oname); X if (oname.token == ogrid.type) X hitperson = xx; X xx++; X } X if (hitperson >= 0) /* Big shp has better shield */ X shiedmg = shiedmg / ((oname.type / 2) + 2); X if (oname.wstatus & SHIELD_UP) { X if (ogrid.shield > shiedmg) { X ogrid.shield -= shiedmg; X edmg = 0; X } else { X edmg -= ((ogrid.shield * ((oname.type / 2) + 2)) * EPERSHIELD); X ogrid.shield = 0; X } X } X ogrid.energy -= edmg; /* No diff for raw E hits */ X if (hitperson >= 0) { /* Systems are less fragile */ X edmg = edmg / oname.type;/* Divide by type */ X if (!explosion) { /* If not an explosion */ X xx = roll(8); X switch(xx) { X case 0: X oname.engines -= edmg/100; X break; X case 1: X oname.life -= edmg/150; X break; X case 2: X oname.crew -= edmg/200; X break; X case 3: X oname.shield -= edmg/75; X break; X case 4: X oname.hull -= edmg/300; X break; X case 5: X oname.lasers -= edmg/500; X break; X case 6: X oname.torps -= edmg/200; X break; X case 7: X oname.mines -= edmg/50; X break; X } X } else { /* Explosion hurts everything */ X oname.engines -= edmg/(75 + roll(50)); X oname.life -= edmg/(100 + roll(100)); X oname.crew -= edmg/(150 + roll(100)); X oname.shield -= edmg/(50 + roll(50)); X oname.hull -= edmg/(200 + roll(200)); X oname.lasers -= edmg/(400 + roll(200)); X oname.torps -= edmg/(150 + roll(100)); X oname.mines -= edmg/(25 + roll(50)); X } X } X storename(hitperson, oname); X if (ogrid.energy < 0) { /* If a shp blows up */ X if (shp != NULL) X shp->points += (oname.points / 5); X } X } else { X if (ogrid.type != VOID) { X if (ogrid.shield > 0) X ogrid.shield -= (edmg/100); X if (ogrid.shield <= 0) { X ogrid.shield = 0; X ogrid.energy -= edmg; X } X } X } X if (ogrid.energy < 0) { X if (drone == 0) X mvaddstr(23,20,"FLASH! There is an explosion!"); X if ((ogrid.type < 'A') || (ogrid.type > 'Z')) { X if ((ogrid.type == MINE) || (ogrid.type == TORPEDO)) { X if (shp != NULL) X shp->points += 25; X ogrid.type = EMPTY; X storegrid(x, y, ogrid); X if (roll(NUKECHANCE) < 2) /* Nuke? */ X explode(x, y, (NUKE_MINE * EXPLOSION), X NUKE_MINE);/* Nuclear mine */ X else X explode(x, y, (MINE_BOOM * EXPLOSION), X MINE_BOOM);/* Normal Mine */ X } X if (ogrid.type == PLANET) { X if (shp != NULL) X shp->points += 3000; X ogrid.type = EMPTY; X storegrid(x, y, ogrid); X explode(x, y, (BIG_BOOM * EXPLOSION), BIG_BOOM); /* Oh oh ! */ X sprintf(tmp, "Planet destroyed at %d %d", x, y); X putmsg(tmp); X } X if (ogrid.type == STAR) { X if (shp != NULL) X shp->points += 8000; X ogrid.type = VOID; X ogrid.energy = roll(SIZE); X ogrid.shield = roll(SIZE); X storegrid(x, y, ogrid); X explode(x, y, (NOVA * (EXPLOSION * 2)), NOVA); /* Ouch! */ X sprintf(tmp, "NOVA at %d %d!", x, y); X putmsg(tmp); X } X } else { X ogrid.type = EMPTY; X storegrid(x, y, ogrid); X explode(x, y, (SHIP_DEATH * EXPLOSION), SHIP_DEATH); X } X } X storegrid(x, y, ogrid); X return; X} END_OF_FILE if test 4738 -ne `wc -c <'givedamage.c'`; then echo shar: \"'givedamage.c'\" unpacked with wrong size! fi # end of 'givedamage.c' fi if test -f 'makechoice.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'makechoice.c'\" else echo shar: Extracting \"'makechoice.c'\" \(4177 characters\) sed "s/^X//" >'makechoice.c' <<'END_OF_FILE' X/* Space module MAKECHOICE - run the drone ship */ X X#include "cosmos.h" extern char *buffer; extern struct nameblock *ship; X checkchoice(x, y, key, lastret) /* Is this a wise choice? */ int x, y; int key; int *lastret; X X{ X static int keyvec[10] = {'1', '4', '7', '8', '9', '6', '3', '2', 0}; X int retval; X int xx, yy; X struct grid ourgrid; X int quit = 0; X int infloop = 0; X X retval = key; X if (key == 0) { X if (roll(10) > 8) { X retval = keyvec[roll(7)]; X } else { X retval = *lastret; X } X } X quit = 0; X while (quit == 0) { X infloop++; /* Infinite loop detector */ X xx = x; yy = y; X switch(retval) { X case '8': X yy = y + 1; X break; X case '7': X yy = y + 1; X xx = x - 1; X break; X case '1': X yy = y - 1; X xx = x - 1; X break; X case '9': X xx = x + 1; X yy = y + 1; X break; X case '3': X yy = y - 1; X xx = x + 1; X break; X case '2': X yy = y - 1; X break; X case '4': X xx = x - 1; X break; X case '6': X xx = x + 1; X break; X } X if ((xx >= 0) && (yy >= 0) && (xx < SIZE) && (yy < SIZE)) { X readgrid(xx, yy, &ourgrid); X if (ourgrid.type == EMPTY) { /* Found an out */ X quit++; X *lastret = retval; X return(retval); X } X } X retval = keyvec[roll(8)]; X if (infloop > 15) { /* Can't find a way out */ X retval = 0; /* So don't move anywhere */ X quit++; X printf("Can't find path; sit\n"); X fflush(stdout); X } X } X *lastret = retval; X return(retval); X} X makechoice(x, y, window, lastkey) int x, y; int window; int *lastkey; X{ X int xx, yy; /* Temp storage */ X int threat; /* If there is a threat... */ X int dist; /* Distance from 'mark' */ X int key; /* Code to be returned */ X static int list[10] = {'1','4','7','8','9','6','3','2',0 }; X static int conv[10] = {'9','6','3','2','1','4','7','8',0 }; X X /* See if it's ok to hunt bases, energy must be full */ X X if (ship->energy > (e_require[ship->type] - (e_require[ship->type]/5))) { /* Full? */ X xx = x; yy = y; X key = findobj(&xx, &yy, &dist, BASE, BASE, window); X if (key) { /* Oh boy! I see a base! */ X if (dist < 3) { X for (xx = 0; xx < 9; xx++) { /* Back off! */ X if (list[xx] == key) { X *lastkey = conv[xx]; X return(conv[xx]); X } X } X } else { X if (dist > 6) { /* Move in */ X *lastkey = key; X return(key); /* Return move code */ X } X *lastkey = 'L'; /* Shoot it! */ X return('L'); /* And out */ X } X } X } X xx = x; yy = y; X key = findobj(&xx, &yy, &dist, 'A', 'Z', window); X if (!key) { /* There is a ship in range */ X if (ship->wstatus & SHIELD_UP) X return('s'); /* Drop shields */ X } else { X if (!(ship->wstatus & SHIELD_UP)) { X if (dist > 4) { /* If a good distance */ X if ((ship->energy > (e_require[ship->type] / 5)) && X (ship->numtorps) && (ship->torps) && X (roll(dist - 4) > 1)) X return('t'); /* Fire torpedoes at ship */ X } X if (!(ship->wstatus & SHIELD_DEAD)) { /* Not dead */ X return('s'); /* Raise shields! */ X } X } X if (ship->energy > (e_require[ship->type] / 5)) {/* Attack! */ X if (roll(dist) > 2) { /* If we outroll it */ X *lastkey = key; X return(key); /* Move in */ X } else { X *lastkey = 'l'; X return('l'); /* Else shoot! */ X } X } else { X for (xx = 0; xx < 9; xx++) { X if (list[xx] == key) { X *lastkey = conv[xx]; X return(conv[xx]); X } X } X } X } /* There is no ship in range to attack or run from */ X if (ship->energy < (e_require[ship->type] / 5)) {/* If low on power */ X xx = x; yy = y; X key = findobj(&xx, &yy, &dist, BASE, BASE, window); X if (key) { X if (dist == 1) { X *lastkey = 'D'; X return('D'); /* Dock */ X } else X return(key); /* Go to the base */ X } X } X if (ship->energy < (e_require[ship->type] / 5) /* Need to build here */ X xx = x; yy = y; X key = findobj(&xx, &yy, &dist, PLANET, PLANET, window); X if (key) { X if (dist == 1) X return('B'); /* Build */ X else X return(key); /* Go to the planet */ X } X } /* Otherwise power is ok */ X if (*lastkey == 'D') { /* If docked... */ X if (ship->energy != e_require[ship->type]) X return('D'); /* Continue if not full */ X else { X *lastkey = 0; X return(0); X } X } X return(*lastkey); X} END_OF_FILE if test 4177 -ne `wc -c <'makechoice.c'`; then echo shar: \"'makechoice.c'\" unpacked with wrong size! fi # end of 'makechoice.c' fi if test -f 'mines.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'mines.c'\" else echo shar: Extracting \"'mines.c'\" \(1503 characters\) sed "s/^X//" >'mines.c' <<'END_OF_FILE' X/* Put a mine in someone's way :-) */ X X#include "cosmos.h" extern char *buffer; extern int drone; extern struct nameblock *ship; X extern int window; extern void givedamage(); X mines(semid, x, y) int semid; int x, y; X{ X X X struct grid ourgrid; X int xx = 0, yy = 0; X int key = 0; X X if ((ship->mines < 30) || (ship->wstatus & MINE_DEAD)) X return(0); /* Weapon is dead */ X if (ship->nummines <= 0) { X mvaddstr(23,20,"No more mines on board!"); X clrtoeol(); X return(0); X } X mvaddstr(15,59,"Mines.... ARMED"); X clrtoeol(); X mvaddstr(22,20,"Mines (1) -> "); X clrtoeol(); X release(semid); X refresh(); X key = getchx(); X acquire(semid); X switch(key) { X case '8': X xx = 0; X yy = 1; X break; X case '9': X xx = 1; X yy = 1; X break; X case '6': X xx = 1; X yy = 0; X break; X case '3': X xx = 1; X yy = -1; X break; X case '2': X xx = 0; X yy = -1; X break; X case '1': X xx = -1; X yy = -1; X break; X case '4': X xx = -1; X yy = 0; X break; X case '7': X xx = -1; X yy = 1; X break; X } X if ( ((x + xx) >= SIZE) || ((x + xx) < 0) || ((y + yy) >= SIZE) || ((y + yy) < 0)) X return(0); X readgrid((x + xx), (y + yy), &ourgrid); X if (ourgrid.type != EMPTY) { X mvaddstr(23,20,"EMERGENCY OVERRIDE! That space is not empty!"); X clrtoeol(); X return(0); X } X ourgrid.type = MINE; X ourgrid.energy = MINE_ENERGY; /* Low value deliberately */ X ourgrid.shield = 0; X ourgrid.hit = 0; X storegrid((x + xx), (y + yy), ourgrid); /* Save it */ X ship->nummines--; /* Laid one */ X return(0); X} END_OF_FILE if test 1503 -ne `wc -c <'mines.c'`; then echo shar: \"'mines.c'\" unpacked with wrong size! fi # end of 'mines.c' fi if test -f 'modgame.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'modgame.c'\" else echo shar: Extracting \"'modgame.c'\" \(4582 characters\) sed "s/^X//" >'modgame.c' <<'END_OF_FILE' X/* Modgame - change game parameters */ X X#include "cosmos.h" X extern int extx, exty; X modgame(semid) int semid; X{ X X struct grid ourgrid; X struct nameblock ourname; X int key; X char tmp[80]; X int xx, yy, x, y; X X release(semid); X mvaddstr(23,20,"Modify <G>rid, <S>hip, <F>ind or <T>eleport > "); X clrtoeol(); X refresh(); X key = toupper(getchx()); X switch (key) { X case 'T': X mvaddstr(23,20,"Teleport to -> "); X clrtoeol(); X refresh(); X echo(); X get_str(tmp); X noecho(); X if (!tmp[0]) { X acquire(semid); X return; X } X if (sscanf(tmp, "%d %d", &xx, &yy) != 2) { X acquire(semid); X return; X } X acquire(semid); X readgrid(xx, yy, &onegrid); X if (onegrid.type != EMPTY) { X mvaddstr(23,20,"Space not empty"); X clrtoeol(); X refresh(); X sleep(2); X return; X } X readgrid(extx, exty, &onegrid); X storegrid(xx, yy, onegrid); X onegrid.type = EMPTY; X onegrid.energy = 0; X onegrid.shield = 0; X storegrid(extx, exty, onegrid); X extx = xx; X exty = yy; X break; X case 'F': X mvaddstr(23,20,"Find what -> "); X clrtoeol(); X refresh(); X key = toupper(getchx()); X if (!key) { X acquire(semid); X return; X } X move(23,40); X printw("Find %c", key); X refresh(); X for (x = 0; x < SIZE; x++) { X for (y = 0; y < SIZE; y++) { X readgrid(x, y, &ourgrid); X if (ourgrid.type == key) { X move(23,40); X printw("Found at %d %d", x, y); X clrtoeol(); X refresh(); X sleep(5); X break; X } X } X } X acquire(semid); X break; X case 'G': X mvaddstr(23,20,"X Y coordinates > "); X clrtoeol(); X refresh(); X get_str(tmp); X if (tmp[0] == 0) { X acquire(semid); X return; X } X if (sscanf(tmp, "%d %d", &x, &y) != 2) { X mvaddstr(23,20,"Invalid coordinates"); X clrtoeol(); X acquire(semid); X return; X } X if ((x < 0) || (y < 0) || (x >= SIZE) || (y >= SIZE)) { X mvaddstr(23,20,"Invalid coordinates"); X clrtoeol(); X acquire(semid); X return; X } X readgrid(x, y, &ourgrid); X move(22,20); X printw("Type = %d, E = %d, Shield = %d", ourgrid.type, ourgrid.energy, ourgrid.shield); X clrtoeol(); X mvaddstr(23,20,"New type (`.,@*+) > "); X clrtoeol(); X refresh(); X key = getchx(); X acquire(semid); X ourgrid.type = EMPTY; X switch(key) { X case '.': X case ' ': X ourgrid.type = EMPTY; X ourgrid.shield = 0; X ourgrid.energy = 0; X break; X case '@': X ourgrid.type = PLANET; X ourgrid.shield = 0; X ourgrid.energy = 10000000L; X break; X case '*': X ourgrid.type = STAR; X ourgrid.shield = 0; X ourgrid.energy = 20000000L; X break; X case ',': X ourgrid.type = MINE; X ourgrid.energy = 5L; X ourgrid.shield = 0; X break; X case '`': X ourgrid.type = ASTEROID; X ourgrid.energy = 500000L; X ourgrid.shield = 20; X break; X case '+': X ourgrid.type = BASE; X ourgrid.energy = 10000000L; X ourgrid.shield = 100; X break; X } X move(22,20); X printw("Type = %d, E = %d, Shield = %d", ourgrid.type, ourgrid.energy, ourgrid.shield); X mvaddstr(23,20,"Energy = "); X clrtoeol(); X refresh(); X get_str(tmp); X sscanf(tmp, "%d", &ourgrid.energy); X mvaddstr(23,20,"Shield = "); X clrtoeol(); X refresh(); X get_str(tmp); X sscanf(tmp, "%d", &ourgrid.shield); X storegrid(x, y, ourgrid); X break; X case 'S': X mvaddstr(23,20,"Ship letter> "); X clrtoeol(); X refresh(); X key = getchx(); X for (x = 0; x < MAXSHIPS; x++) { X readname(x, &ourname); X if (ourname.token == key) { X move(23,20); X printw("Type = %d, E = %d, Sh = %d, Pts = %d", ourname.type, ourname.energy, ourname.shield, ourname.points); X clrtoeol(); X mvaddstr(22,20,"New Type = "); X clrtoeol(); X refresh(); X get_str(tmp); X sscanf(tmp, "%d", &ourname.type); X mvaddstr(22,20,"New E = "); X clrtoeol(); X refresh(); X get_str(tmp); X sscanf(tmp, "%d", &ourname.energy); X mvaddstr(22,20,"New Shield = "); X clrtoeol(); X refresh(); X get_str(tmp); X sscanf(tmp, "%d", &ourname.shield); X mvaddstr(22,20,"New Points = "); X clrtoeol(); X refresh(); X get_str(tmp); X sscanf(tmp, "%d", &ourname.points); X acquire(semid); X ourname.gods++; X storename(x, ourname); X for (x = 0; x < SIZE; x++) { X for (y = 0; y < SIZE; y++) { X readgrid(x, y, &ourgrid); X if (ourgrid.type == ourname.token) { X X ourgrid.energy = ourname.energy; X ourgrid.shield = ourname.shield; X storegrid(x, y, ourgrid); X } X } X } X return(0); X } X } X } X return; X} END_OF_FILE if test 4582 -ne `wc -c <'modgame.c'`; then echo shar: \"'modgame.c'\" unpacked with wrong size! fi # end of 'modgame.c' fi if test -f 'phasers.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'phasers.c'\" else echo shar: Extracting \"'phasers.c'\" \(2943 characters\) sed "s/^X//" >'phasers.c' <<'END_OF_FILE' X/* Phaser/laser fire - Part of the COSMOS universe X X Copyright 1988 Karl Denninger & MCS, Inc. X All rights reserved X X*/ X X#include "cosmos.h" X extern char *buffer; extern int drone; extern struct nameblock *ship; X extern int window; extern void givedamage(); X phasers(semid, x, y) int semid; int x, y; X{ X X static int xx, yy; X static int x1, y1; X static char tmp[80]; X static char tmp2[80]; X X struct grid onegrid; X struct grid ourgrid; X char args[40]; X char *arg[3]; X long edmg; X long shiedmg; X int hitperson; X struct nameblock onename; X int dist; X X if (ship->wstatus & LASERS_DEAD) X return(0); /* Weapon is dead */ X mvaddstr(14,59,"Lasers... ARMED"); X clrtoeol(); X mvaddstr(22,20,"Lasers -> "); X clrtoeol(); X release(semid); X refresh(); X get_str(args); X acquire(semid); X if (args[0]) X strcpy(tmp2, args); X strcpy(tmp, tmp2); X if ((!isdigit(tmp[0])) && (tmp[0] != '-')) { X if (ship->type < 3) { /* Small doesn't have lock */ X mvaddstr(23,20,"We don't have weapons locking!"); X clrtoeol(); X return(0); X } X xx = x; X yy = y; X if (!findobj(&xx, &yy, &dist, toupper(tmp[0]), toupper(tmp[0]), window)) { X mvaddstr(23,20,"Target not found"); X clrtoeol(); X return(0); X } else { X x1 = (xx - x); X y1 = (yy - y); X } X } else { X if ((arg[0] = strtok(tmp, ":, ")) == NULL) { X mvaddstr(23,20,"Requires two parameters"); X clrtoeol(); X return(0); X } else X x1 = atoi(arg[0]); X if ((arg[1] = strtok((char *) NULL, ":, ")) == NULL) { X mvaddstr(23,20,"Requires two parameters"); X clrtoeol(); X return(0); X } else X y1 = atoi(arg[1]); X } X if (((x + x1) < 0) || ((x + x1) >= SIZE) X || ((y + y1) < 0) || ((y + y1) >= SIZE)) { X mvaddstr(23,20,"Invalid coordinates"); X clrtoeol(); X return(0); X } X if ((x1 == 0) && (y1 == 0)) { X mvaddstr(23,20,"Silly -- you can't shoot yourself!"); X clrtoeol(); X return(0); X } X edmg = (int) ((800 + roll(700)) * ship->type) / sqr((x1 * x1) + (y1 * y1) + 1); X readgrid((x + x1), (y + y1), &ourgrid); /* Anything there? */ X if ((ourgrid.type != EMPTY) && (ourgrid.type != VOID)) { X readgrid(x, y, &ourgrid); X ship->energy -= (200 * ship->type); X ourgrid.energy -= (200 * ship->type); X storegrid(x, y, ourgrid); X givedamage((x + x1), (y + y1), edmg, ship, 0); /* Give it damage */ X } X return(0); X} X cphasers(x, y, startobj, endobj) int x, y; int startobj, endobj; X{ X X int xx, yy; X int dist; X int go; X int tmpx, dir; X int edmg; X struct grid ourgrid; X X if (ship->lasers < 30) { X if (roll(200) > ship->lasers) X return(0); X } X xx = x; yy = y; X dir = findobj(&xx, &yy, &dist, startobj, endobj, window); X if (dir == 0) X return(0); /* No target in range */ X if (dir) { X edmg = ((1000 + roll(700)) * ship->type) / sqr(((xx - x) * (xx - x)) + ((yy - y) * (yy - y)) + 1); X readgrid(x, y, &ourgrid); X ship->energy -= (200 * ship->type); X ourgrid.energy -= (200 * ship->type); X storegrid(x, y, ourgrid); X givedamage(xx, yy, edmg, ship, 0); /* Give it damage */ X } X return(1); X} END_OF_FILE if test 2943 -ne `wc -c <'phasers.c'`; then echo shar: \"'phasers.c'\" unpacked with wrong size! fi # end of 'phasers.c' fi if test -f 'players.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'players.c'\" else echo shar: Extracting \"'players.c'\" \(348 characters\) sed "s/^X//" >'players.c' <<'END_OF_FILE' int addplayer(limited, timed, ac, av) int *limited; /* Return, NZ = limited player */ int *timed; /* Return, NZ = timed player */ int ac; /* Count of arguments */ char *av; /* Second argument */ X{ X X} X void delplayer(ac, av, start) int ac; /* Count of arguments */ char *av; /* Second argument */ long start; /* Game start time */ X{ X X} END_OF_FILE if test 348 -ne `wc -c <'players.c'`; then echo shar: \"'players.c'\" unpacked with wrong size! fi # end of 'players.c' fi if test -f 'rmseg.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'rmseg.c'\" else echo shar: Extracting \"'rmseg.c'\" \(1430 characters\) sed "s/^X//" >'rmseg.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 struct nameblock name; struct grid onegrid; X main() X{ X int seg; /* Shared segment number */ X char *buffer; /* Buffer pointer */ X X int size; X int x, y; /* X & Y coordinates of ship */ X int key; X int quit = 0; /* Halt variable */ X int tempint; X X struct nameblock namebuf; X long game = (sizeof(onename) * MAXSHIPS) + sizeof(ccount) + X (sizeof(onegrid) * MAXGRID) + (sizeof(onemsg) * MAXMSG); X size = (game); /* Get size of game module */ X X printf("COSMOS Maintenance cleanup\n"); X printf("Remove segment %s\n",VERSION); 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 (shmctl(seg, IPC_RMID, 0)) { X perror("destroy"); X puts("Cannot delete segment"); X exit(1); X } X if ((seg = semget(122L, 1, IPC_CREAT|0660)) == -1) { X perror("create"); X puts("Cannot execute due to semaphore create fault"); X exit(1); X } X if (semctl(seg, IPC_RMID, 0)) { X perror("destroy"); X puts("Cannot delete semaphore"); X exit(1); X } X X exit(0); X} END_OF_FILE if test 1430 -ne `wc -c <'rmseg.c'`; then echo shar: \"'rmseg.c'\" unpacked with wrong size! fi # end of 'rmseg.c' fi if test -f 'scan.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'scan.c'\" else echo shar: Extracting \"'scan.c'\" \(2693 characters\) sed "s/^X//" >'scan.c' <<'END_OF_FILE' X/* Cosmos - A game of the cosmos */ X X#include "cosmos.h" extern char *buffer; extern struct nameblock *ship; X scan(semid, x, y, window) int semid, x, y; int window; X{ X X int xx, yy; X int z = 0, zx; X int dist; X int key; X struct grid ourgrid; X struct nameblock name; X int vector; X X release(semid); X mvaddstr(22,20,"Scan object -> "); X refresh(); X key = getchx(); X acquire(semid); X if ((key == 10) || (key == 13) || (key == 0)) X return(0); X else { X xx = x; yy = y; X vector = findobj(&xx, &yy, &dist, key, key, window_size[ship->type]); X if (vector == 0) { X mvaddstr(23,20,"No object found"); X clrtoeol(); X return(0); /* Nothing to scan */ X } X readgrid(xx, yy, &ourgrid); X for (zx = 1; zx < 17; zx++) { X mvaddstr(zx, 44, " "); X } X if ((ourgrid.type >= 'A') && (ourgrid.type <= 'Z')) { X name.token = key; X z = locship(&name, 1); X readname(z, &name); X name.scanned++; X storename(z, name); X move(1,44); X printw("'%c', a %s", name.token, shiptypes[name.type]); X clrtoeol(); X move(2,49); X z = name.energy; X printw("%9ld", z); X move(3,49); X printw("%9d", (name.engines + roll(20) - 10)); X move(4,49); X printw("%9d", (name.lasers + roll(20) - 10)); X move(5,49); X if ((ship->wstatus & MINE_DEAD) == 0) X printw("%9d", (name.mines + roll(20) - 10)); X else X addstr(" "); X move(6,49); X if ((ship->wstatus & TORPEDO_DEAD) == 0) X printw("%9d", (name.torps + roll(20) - 10)); X else X addstr(" "); X move(7,49); X printw("%9d", (ourgrid.shield + roll(20) - 10)); X move(8,49); X printw("%9d", (name.crew + roll(20) - 10)); X move(9,49); X printw("%9d", (name.life + roll(20) - 10)); X move(10,49); X printw("%9d", (name.hull + roll(20) - 10)); X move(13,49); X if (name.wstatus & SHIELD_DEAD) X addstr("INOPER."); X else { X if (name.wstatus & SHIELD_UP) X addstr("UP "); X else X addstr("DOWN "); X } X clrtoeol(); X move(14,49); X if (name.wstatus & LASERS_DEAD) X addstr("INOPER."); X else { X if (name.wstatus & LASERS_LOCK) X addstr("LOCKED "); X else X addstr("STBY "); X } X move(15,49); X if (name.wstatus & MINE_DEAD) X addstr(" "); X else { X if (name.wstatus & MINE_LOCK) X addstr("LOCK"); X else X addstr("STBY"); X printw("/%d", name.nummines); X } X move(16,49); X if (ship->wstatus & TORPEDO_DEAD) X addstr(" "); X else { X if (ship->wstatus & TORPEDO_LOCK) X addstr("LOCK"); X else X addstr("STBY"); X printw("/%d", name.numtorps); X } X } else { X move(2,49); X z = ourgrid.energy; X printw("%9ld", z); X move(7,49); X printw("%9d", ourgrid.shield); X } X } X return(1); X} X END_OF_FILE if test 2693 -ne `wc -c <'scan.c'`; then echo shar: \"'scan.c'\" unpacked with wrong size! fi # end of 'scan.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 -- 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"
karl@ddsw1.MCS.COM (Karl Denninger) (11/18/88)
Part 2 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 <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 2 (of 3)." # Contents: Help cosmos.h drone.c torpedoes.c # Wrapped by karl@ddsw1 on Thu Nov 17 23:53:07 1988 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'Help' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Help'\" else echo shar: Extracting \"'Help'\" \(13308 characters\) sed "s/^X//" >'Help' <<'END_OF_FILE' X************************ COSMOS On-Line Assistance ************************** X Note: If your screen is "screwed up" your terminal type is set incorrectly. X X Numeric Celestial Objects on Grid X -Pad- X @ - Planet A-Z - Spaceship X 7 8 9 * - A Star (Computer or Man) X 4 5 6 <<< Move in ` - A Asteroid + - StarBase X 1 2 3 direction , - A Mine . - Empty Space X A Void is a "space" b - Broadcast message l - Fire Lasers m - Lay a Mine t - Fire a Torpedo + - Add another enemy ship to game s - Raise/lower (toggle) shields X A - Set your alliance (unimpl.) M - Move on autopilot to coordinates B - Build a base on a planet N - Change ship's name (if docked) C - Capture an object (unimplemented) P - Players in game (docked) or status D - Dock with a starbase Q - Quit (save if GREEN status) R - Disable/Enable Ramming protection S - Scan an object in view X X Movement: X X Basic Movement is done with the numeric keypad. Some ships can "home" X in on a given coordinate using the "M" command. This command will X only function in ships which include it as part of their navigation X subsystem (first available on the Frigate). X X The coordinate grid is layed out in x, y, with the 'x' axis being X the horizontal. Your current position is always displayed in the X lower left corner of the playscreen. X X The "M" (capital 'm') command will take you to a destination at X best-rate-of-travel speed if your ship is equipped with an autopilot X (small ships lack the machinery). The autopilot is intelligent X enough to stop the ship if there is an obstruction you would X otherwise impact with, but not intelligent to steer around it X automatically. Enter the destination coordinates when you use the X "M" command with a single space or tab between them, "X" first. X X A "M" command entered without coordinates will use the last stored X destination position. X X Shields: X X These consume energy when in use. When your shields are up, X the shields will take the damage (in percent operability) before X your main energy stores and the remainder of the ship are affected. X If your shield level drops to zero or below, your shields will X be "blown down" and you will suffer damage from this as well as the X hit which causes the shields to drop (as they are no longer functional). X X Shields provide some protection against collisions. X X You may not be able raise your shields if they are below 30% efficiency. X X XEnergy: X X If you run out you're dead. Don't allow this to happen. The best X way to get more energy is to dock with a starbase. See "building X bases" for information on this. X X Some energy is used to maintain the ships' functions. An additional X amount if required whenever you move, when you use shields or weapons, X or when you build upon a planet. X X Building Bases: X X To build a base, a player moves next to a planet and uses the "B" X command. You will be asked for a direction, enter the key on the X keypad (numeric) corresponding to the direction of the planet you X wish to build upon. X X 10 Builds are required to create a base, and each one requires 500 X Energy units from your ship. X X Lasers: X X Lasers are fired with the 'l' key. You must aim these weapons at X the position you wish to hit _relative_ to your current location, or X in ships which have targeting (anything larger than a courier) you X may aim by ship name. Thus, to hit an object at 102, 100 if you X are at 100, 100 would require a "laser" coordinate entry of "2 0". X X Larger ships have more powerful lasers. X X Note that either an object's letter (case is irrelavent) or the X relative coordinates must be entered at the prompt, followed by X <return>. A null (ie: return only) entry will use the last entered X coordinates or ship to target on. X X Projectiles: X X Torpedoes move at a reasonable rate -- you may be able to outrun X them. Torpedoes also have a definite range dependant on the X launcher's guidance capabilities, at which point they automatically X detonate regardless of whether they are in range of a target. X X Torpedoes explode on impact with any other object in the game. X X All torpedoes are guided by the "parent" ship which fires it. As a X result, if the parent ship should die, the torpedo will cease X activity (effectively be "dead). The torpedo does carry limited X detection facilities in it's nose, as will "track" or home in on a X target if it is not specified in absolute terms. Small ships have X an "in flight" torpedo limit due to their limited computer resources X for guidance. X X To fire a torpedo, enter either the ship's letter or the relative X coordinates to fire upon, as with lasers. As with lasers, a X <return> signifies to repetitively fire at the same target. X X Scout ships do not possess torpedoes. X X Mines: X X Intersteller mines are extremely dangerous. They are difficult to X spot and impossible to trace, and they will explode if they take any X damage at all (ie: if you shoot it). Clusters of mines will X chain-detonate; this will produce a very spectacular explosion (not X to mention killing nearly any ship nearby). Mines are not detected X by one's "collision avoidance" system, and as a result you can X easily run into one or more without warning. X X Note that once in a while a mine will be in your "kit" that has much X more explosive power than normal. These are termed "nuclear" mines; X you cannot detect a difference until they are detonated. X X Mines are first available to Frigates. X X Ramming objects: X X Your computer will not allow you to run into solid objects unless X you specifically override this safety feature. To turn on the X override, and permit ramming, press <R>. You may press this key X again to disable the override when you are done with it. X X This is intended to permit intentional ramming operations, but X prevent accidental death due to collisions with solid objects. X X Note that the override on your movement expends some energy stopping X your ship before it impacts with the object you would otherwise ram. X X Special weaponry: X X There may be special functions only available to the largest class X ships. The use of these functions is not documented, but there are X rumors that one of them is a planet-destroying weapon. X X Hints will be given to you if you are fortunate when completing a base. X X XExplosions: X X Expect to take *HEAVY* damage from things that explode near you. If X you are unfortunate enough to be next to an object that is destroyed, X you will suffer the equivalent damage of several large laser (or X multiple) torpedo hits. Many ships will be destroyed by these X occurances. Bases, planets, stars, and large ships will do damage X beyond the immediate neighbor sectors when they detonate. X X Be especially careful if you are near multiple sources of explosion X -- it is possible to have a chain-reaction established and suffer X multiple hits in this case. Such occurrances are nearly always fatal. X X Your shields are effective against explosion forces up to a point. X X Combat: X X You will be informed via a "beep" and a message on the bottom line X of your screen, as well as your token "flashing", whenever you X suffer an attack. The source of the attack is not necessarially X known to you, although you can probably take a good guess from the X magnitude of the hit. X X The first time you fire on a base it will send a distress message. X Bases will also use their very last dying gasps to tell the universe X you have blown them to smithereens, so you can expect a message when X this occurs as well. X X Weapons fire is "sticky"; that is, once you enter a coordinate to X shoot at you may just press <return> at the coordinate prompt to X fire at the same relative location. This "sticky" power is retained X even if you move the vessel. NOTE THAT COORDINATES ENTERED FOR X WEAPONS MUST - MUST - MUST BE RELATIVE TO YOUR CURRENT LOCATION. X X Any item which explodes will be detected by your ships' sensor, and X the coordinates of the explosion will be displayed on the message X screen. Novas and planetary destruction are so spectacular as to be X unmistakable for other explosions, and are so noted. X X Black Holes: X X Occasionally you may see an "empty" space on the game grid. These X are "black holes". There are a few found at random locations X throughout the galaxy, and exploding stars will also create these X anomolies. X X Moving into a sector containing a black hole will cause your ship to X be instantly transported to another location on the game grid. The X "white hole" on the other side is always consistantly placed once X the black hole has been created. X X General Weaponry & Player Notes: X X When you shoot something, or it explodes, you will see the area X affected by the act light up in reverse video (providing your X terminal supports this option). X X Note that the computer may be playing and number of ships while you X are in the game. These are indistinguishable from human players, X and they play be the same rules you do. Pay particular attention X to a ships' size, as these ships come in all sizes and dispositions. X The admininistrator can set the maximum number of computer players X which can be in the game as well as their rate of replenishment. X It is completely possible for the computer ships to gang up on the X human player(s). (Hint: Computer ships operate on energy just as you X do, and must dock as well). X X The message area (the 4 lines on the bottom right side of the screen) X is a "windowed radio" of sorts. Operating on sub-light frequencies, X it is a limited-bandwidth device, that is to say, rapid events may X overload it's reception and display capacity. If this occurs the X message(s) which overload the capacity of the internal buffering are X lost without a trace. X X All other things being equal, a small ship is faster than a large X one due to inertia. The game enforces this by parceling out movement X windows differently for the different classes of ships. X X X Combat Hints: X To Survive Combat (victoriously, of course): X X1) Use the power of items near you, yet be wary of it. Be aware that a ship X or other object which detonates near you will likely damage you heavily. X Large ships', planets, and stars' detonations will be _fatal_ if you are X too close to the object when it explodes. X2) Put up your shields when hostilities are imminent. They only help you if X they are raised. However, do not leave them up unnecessarially, as X shields are a heavy drain on your energy resources. Computer ships will X _always_ raise their shields when in your company if they are operational. X Note that if your shields get to below 30% efficiency, your control X circuits may malfunction, making it impossible to lower _or_ raise shields. X To avoid this drop your shields before you go below 30% shield efficiency. X3) Make use of the explosive potential in starbases if you surprise a enemy X ship and it is docked with one. Undock and move away IMMEDIATELY if you X are attacked while docked, or if the base you are docked with is attacked X by hostile fire. X4) Be aware that different class ships have different scanner sensitivities, X and that you may be seen before you can see your opponent and vice-versa. X As a correlary of this, if you can't see what's firing on you, it's X almost certainly larger than you are. X5) Keep an eye on your secondary resources (percentage damage display), as X well as energy. Abort your combat if any of your critical parameters is X near the failing level. Shields are especially important, as they absorb X hits that would otherwise damage your ship's other components. X6) Learn to fire bursts of weapons. This is done by moving to position, X keying the initial fire command with appropriate parameters, then X re-keying only the command portion to fire again at the same location. X Use EXTREME caution when doing this with lasers to prevent running out X of energy! X7) Use the scanners to determine whether a ship you are attacking is weaker X than you are, comparable, or much stronger. Don't be afraid to run from X attacks from ships of unknown strength! X8) Be wary of allowing your "operability percentages" to drop below 30 X percent. Your controls may malfunction in this circumstance; you may be X unable to raise (or lower!) your shields, fire weapons, or even move! X Note that you only get points for what you actively damage. Forcing someone into a planet will not gain you any Captains' points, while causing their ship to explode from laser or torpedo fire certainly will. X Most damage which does not disable a resource (percent < 0) will be repaired with time, even if you do not dock at a starbase. Damage which results in an item going below "0" will not be repaired until you dock, and the item affected cannot be used. Nearly all items which sustain damage leaving less than 30 percent operability will have serious problems. The following X"secondary" items are *ESSENTIAL* to operation of the ship; loss of any of these (below 0) will cost you your vessel. X X Life support - This one should be obvious (oxygen anyone?) X Crew - Also obvious. You're one of them :-) X Hull - If it's zero, there isn't one. In other words, X your vessel is blown into a few thousand pieces. X X<Return> to continue END_OF_FILE if test 13308 -ne `wc -c <'Help'`; then echo shar: \"'Help'\" unpacked with wrong size! fi # end of 'Help' fi if test -f 'cosmos.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'cosmos.h'\" else echo shar: Extracting \"'cosmos.h'\" \(7901 characters\) sed "s/^X//" >'cosmos.h' <<'END_OF_FILE' X/* Cosmos - 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 <values.h> /* Gots to have this */ X X#undef NO_RDCHK /* Define if not Xenix or if X you have problems with input X disappearing when typed ahead */ X X#define MAXSHIPS 20 /* Max players */ X#define HOMEDIR home /* Home directory */ X#define HOME "/etc/cosmos/" /* Home pointer file */ X#define SIZE 200 /* Grid size (each) */ X#define MAXNAME 20 /* Ship name max length */ X#define MAXFTORPS 10 /* Max free torps per ship */ X#define TIME_PER_EUNIT 20 /* Time per energy in turns at rest */ X#define TIME_PER_MSG 100 /* Time for message expiration */ X#define MINE_ENERGY 5L /* Energy for a mine */ X#define EPERSHIELD 100 /* Energy per shield point */ X#undef ACCOUNTING /* Accounting features enabled? */ X X#undef RETIRE_MSGS /* Don't kill msgs */ X#undef FASTMATH /* We have a fast sqrt routine */ X X/* All of these constants are per ship type, which means they get multiplied X when used. This is especially important with energy adjustments; be fair! */ X X#define E_PER_MOVE 30 /* Energy per move square */ X#define E_RAND_PER_MOVE 5 /* Random influence per move */ X#define EADD 75 /* Number always added w/docked */ X#define RANDADD 80 /* Random number added w/docked */ X#define NUKECHANCE 200 /* One in 200 mines is a nuke */ X X/* Having a thing explode counts as EXPLOSION * HIT TYPE points of X explosive energy which must be dissipated. Some, of course, by X the person impacted.... :-) X*/ X X#define EXPLOSION 10000 /* Base explosion energy dissipated */ X#define TORP_EREL 800 /* Base torpedo energy released */ X X#define SHIP_DEATH 1 /* Ship explosion ( X type) */ X#define MINE_BOOM 2 /* Mine explosion */ X#define BASE_DEATH 4 /* This is not good :-) */ X#define NUKE_MINE 12 /* Nuclear mine blast */ X#define BIG_BOOM 18 /* A planet blowing up! */ X#define NOVA 40 /* Uh, don't ask */ X X#define NAP /* System has short sleep if defined */ X#define NAPTIME 250 /* Time in ms for sleep ifdef NAP */ X#define SLEEPTIME 1 /* Time in sec for sleep ifndef NAP */ X X/* Some constants below, tune these for personal preference */ X X#define SHIELD_COST 4 /* Cost per turn per ship/shield type */ X#define BUILDCOST 500 /* Cost of a BUILD command */ X#define BUILDTIME 2 /* Time in Seconds to execute a build */ X X/* For inter-ship messages */ X X#define MAXMSG 6 /* Maximum messages in queue at once */ X#define MSGLEN 40 /* Maximum length of each msg */ X X/* The following are the definitions for the inanimate objects */ X X#define EMPTY '.' /* Empty place */ X#define PLANET '@' /* Planetary body */ X#define STAR '*' /* A star */ X#define BASE '+' /* A Starbase planet */ X#define NEGBASE '-' /* A negbase planet */ X#define MINE ',' /* A Mine */ X#define TORPEDO '^' /* A Torpedo */ X X#define VOID ' ' /* A void */ X#define ASTEROID '`' /* Asteroid :-) */ X X/* END OF CONFIGURABLE SECTION -- DO NOT CHANGE BELOW HERE */ X X static char *shiptypes[20] = { /* Names of ships */ X "", "Scout", "Courier", "Frigate", "Miner", "Destroyer", X "Cruiser", "Battlestar", "Death Star", "Dreadnought", X "Marauder", "Flagship" X }; X static int e_require[20] = { /* Energy requirements/capacity */ X 0, 20000, 30000, 40000, 55000, 70000, 85000, 100000, X 120000, 135000, 150000, 200000 X }; X static int pts[20] = { /* Pts for Advancement */ X 0, 20000, 40000, 80000, 160000, 320000, 640000, 1280000, X 2560000, 5120000, 10240000, MAXINT X }; X static int num_torps[20] = { /* Number of torpedoes */ X 0, 0, 2, 5, 2, 5, 10, 15, 17, 20, 30, 35 X }; X static int num_ftorps[20] = { /* Guidance control capacity */ X 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5 X }; X static int num_mines[20] = { /* Number of mines */ X 0, 0, 0, 2, 15, 5, 5, 15, 20, 25, 30, 40 X }; X static int window_size[20] = { /* Screen window sizes */ X 10, 10, 12, 12, 14, 14, 16, 16, 18, 18, 20, 20 X }; X X /* Bit mask values for weapons */ X /* THESE SHOULD NOT BE CHANGED */ X#define SHIELD_UP 1 X#define SHIELD_DEAD 2 /* NOTE: Requires, due to entries, */ X#define LASERS_LOCK 4 /* 32-bit integers to run */ X#define LASERS_DEAD 8 X#define TORPEDO_LOCK 16 X#define TORPEDO_DEAD 32 X#define MINE_LOCK 64 X#define MINE_DEAD 128 X#define PLANET_KILLER 256 /* You have a planet killer */ X#define CREATE_WORLDS 512 /* You can create planets */ X static int weapons[20] = { /* Weapons mask; must be here */ X 0, X MINE_DEAD, X MINE_DEAD, X 0, X 0, X MINE_DEAD, X MINE_DEAD, X 0, /* All normal weapons here */ X 0, X 0, X PLANET_KILLER, X PLANET_KILLER|CREATE_WORLDS X }; X X X/* Standard include files */ X X#include <stdio.h> X#include <fcntl.h> X#include <errno.h> X#include <sys/types.h> X#include <sys/file.h> X#include <sys/ipc.h> X#include <sys/shm.h> X#include <curses.h> X#include <signal.h> X#include <string.h> X#include <math.h> X#include <ctype.h> X#include <pwd.h> X extern struct passwd *getpwuid(); extern char *memcpy(); X X#define MAXGRID SIZE * SIZE /* DO NOT CHANGE */ X struct torps { X char inuse; /* Torpedo in "use" */ X int level; /* Torpedo 'level' for explosion */ X int x; /* Torpedo 'x' coordinate */ X int y; /* Torpedo 'y' coordinate */ X int destx; /* Destination 'x' */ X int desty; /* Destination 'y' */ X int homeship; /* Home in on ship indicated if NZ */ X int travelled; /* Sectors travelled */ X int life; /* Life (in sectors) of torpedo w/o impact */ X int lastkey; /* Last homing beacon direction */ X}; X struct grid { /* The play grid */ X char type; /* Thing 'living' there */ X short shield; /* Shield percentage at location */ X int energy; /* Energy at location */ X char align; /* Alignment */ X char hit; /* Hit by fire flag */ X}; X X/* Additional attributes X Ship type (1 char) X Weapon status (each weapon - bit mask inoperable/locked/standby) X Shields X Lasers X Torpedoes X Mines X Life support status (percentage) X Crew status (percentage) X Engines (percentage) X Hull (percentage) X Shields X*/ struct nameblock { X char name[MAXNAME]; /* Ships' christened name */ X char token; /* Game token */ X int type; /* Ship type */ X int wstatus; /* Bit mask -- be careful! */ X int lasers; /* Laser status */ X int torps; /* Torpedo launchers */ X int mines; /* Mine launchers */ X int life; /* Life support */ X int crew; /* Crew status */ X int engines; /* Engine status */ X int hull; /* Hull status */ X int shield; /* Shield status */ X long energy; /* Energy amount */ X long points; /* Points awarded to date */ X char align; /* Current alignment */ X int locked; /* What you have locked on */ X int lockx; /* 'X' coordinate of lock */ X int locky; /* "Y" coordinate of lock */ X int numtorps; /* Number of torpedoes */ X int nummines; /* Number of mines */ X int scanned; /* Have we been scanned? */ X int human; /* Non-zero if a human player */ X int gods; /* The gods have intervened */ X int uid; /* The users' UID */ X}; X struct msgblock { X int curmsg; /* Current message number */ X char msgtext[MSGLEN*MAXMSG]; /* Message texts */ X}; X X struct gameseg { X int ccount; /* # of computers */ X struct nameblock names[MAXSHIPS]; /* Name/ship blocks */ X struct grid play[MAXGRID]; /* Play grid */ X struct msgblock messages[MAXMSG]; /* Messages */ X}; X X struct shiprecord { X char shipname[20]; X int type; X long points; /* Points */ X int uid; /* User's UID entry */ X int x; /* X & Y Coordinates Last time */ X int y; X long energy; /* Energy last saved */ X int notused1; /* We will save 2 ints for later */ X int notused2; X int notused3; X int notused4; X}; X struct nameblock onename; struct grid onegrid; struct msgblock onemsg; X int ccount; X END_OF_FILE if test 7901 -ne `wc -c <'cosmos.h'`; then echo shar: \"'cosmos.h'\" unpacked with wrong size! fi # end of 'cosmos.h' fi if test -f 'drone.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'drone.c'\" else echo shar: Extracting \"'drone.c'\" \(13370 characters\) sed "s/^X//" >'drone.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 X/* This is the drone module -- it's a computer "player" */ X X X X#include "cosmos.h" X X int extx, exty; char *buffer; /* Buffer pointer */ int *intbfr; int numcomp; 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; int quit; /* Halt variable */ X int squares[SIZE]; X int drone = -1; /* This is a drone ship */ X main(argc, argv) int argc; char *argv[]; X{ X X static long points; /* Points accumulated */ X static int type; /* Class of ship */ X char shipname[40]; X X int shipcount = 0; X int bypass; X int slept = 0; /* Was I sleeping a minute ago? */ X int humans = 0; /* Number of human players */ X int humancount = 0; /* Human count (turns) */ X int ntfree = 0; /* Number of torpedoes free */ X int docked = 0; X int tmpint; /* Temp integer */ 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 x, y; /* X & Y coordinates of ship */ X int oldx, oldy; X int key; X int tempint = 0; X double dist; /* Distance between two points */ 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 lastkey = 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 X printf("Cosmos DRONE V%s\n", VERSION); X printf("Copyright 1988 MCS Inc. & Karl Denninger\n"); X fflush(stdout); X for (x = 0; x < SIZE; x++) X squares[x] = (x * x); X sprintf(tmp, "%s", HOME); X if ((fid = fopen(tmp, "r")) != NULL) { X fscanf(fid, "%s %d %d %d", home, &superuser, &su2, &numcomp); X fclose(fid); X } X if ((seg = shmget(122L, size, 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)) == -1) { X perror("semaphone create"); X exit(1); X } X } else { X acquire(semid); X } X signal(SIGINT, SIG_IGN); /* Ignore ^C */ X readgrid(0, 0, &onegrid); X if (onegrid.type == 0) { X puts("No grid, exiting....\n"); X release(semid); X exit(1); X } X intbfr = (int *) buffer; X srand((unsigned) time ((long *) 0L)); X if (((int) *intbfr ) >= numcomp) { X puts("All computer players in, exiting"); X release(semid); X exit(1); X } X *intbfr += 1; /* Increment one */ X ship = (struct nameblock *) getcship(semid, &x, &y);/* Get token */ X if ((x == 0) && (y == 0)) { X x = roll(SIZE); X y = 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 computer's ship in the game. */ X X quit = 0; X tempint = 0; X while (quit == 0) { X readgrid(x, y, &onegrid); X if (onegrid.type == EMPTY) X quit++; X else { X x = roll(SIZE); y = roll(SIZE); X tempint++; X if (tempint >= 200) { 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 = 0; /* Android player */ X storegrid(x, y, onegrid); X quit = 0; X while (quit == 0) { X X/* Move torpedoes */ X movetorps(torparray, &ntfree); X readgrid(x, y, &onegrid); X if (onegrid.type == EMPTY) /* If we got killed */ X quit++; /* Exit at end of pass */ 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 energy_count--; X if (energy_count < 0) { X energy_count = TIME_PER_EUNIT; X onegrid.energy += 500; X ship->energy += 500; 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 <= 30) { X ship->wstatus &= ~(SHIELD_UP); X ship->wstatus |= SHIELD_DEAD; X } else X ship->wstatus &= ~(SHIELD_DEAD); X if (ship->torps <= 30) { X ship->wstatus &= ~(TORPEDO_LOCK); X ship->wstatus |= TORPEDO_DEAD; X if (ship->torps < 0) X ship->numtorps = 0; /* Blown off */ X } else X if (num_torps[ship->type] > 0) X ship->wstatus &= ~(TORPEDO_DEAD); X if (ship->mines <= 30) { X ship->wstatus &= ~(MINE_LOCK); X ship->wstatus |= MINE_DEAD; X if (ship->mines < 0) 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 printf("Computer hit %d times\n", onegrid.hit); X onegrid.hit = 0; X } X storegrid(x, y, onegrid); X if ((ship->energy < 0) || (ship->life < 0) || (ship->hull < 0) || (ship->crew < 0)) { X sprintf(tmp, "The %s (%c) explodes!", ship->name, ship->token); X putmsg(tmp); X explode(x, y, (ship->type * EXPLOSION), ship->type); 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(x, y, onegrid); X release(semid); /* Release locks */ X puts("Computer ship disintegrated!"); X *intbfr -= 1; X exit(0); X } X status = calcstatus(x, y, window, docked); X release(semid); /* Release lock */ X oldx = x; X oldy = y; 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. In addition, if a drone, we only move with any real speed if X there are humans in the game (to reduce CPU load). X*/ X humans = 0; /* No humans */ X for (key = 0; key < MAXSHIPS; key++) { X readname(key, &onename); X if (onename.type) { X if (onename.human) /* A human! */ X humans++; X } X } X if (!humans) { /* If there are no humans */ X if (humancount < 100) /* Do we sleep? */ X humancount++; /* Increase human check */ X else { X slept++; X sleep(60); /* sleep 60 seconds */ X } X } else { X humancount = 0; /* Clear count iff humans */ X if (slept) { X slept = 0; /* Clear it */ X sprintf(tmp, "%s awakens", ship->name); X putmsg(tmp); X } X } X key = 0; X nap(NAPTIME + 350); X#ifdef SLOWDOWN X if ((ship->type >= 10) && (shipcount < 5))/* Marauder... */ X shipcount = 5; /* Nearly always can move... */ X if (shipcount++ <= (ship->type / 3)) {/* If delay not expired */ X key = 0; /* No input allowed */ X bypass++; /* Bypass check */ X } else { /* Otherwise... */ X#endif X shipcount = 0; /* Reset counter to zero */ X key = makechoice(x, y, window, &lastkey); X bypass = 0; /* Evaluate keypress */ X#ifdef SLOWDOWN X } X#endif X acquire(semid); /* Regain lock on segment */ X if (status == 0) /* If green */ X qcount = 0; /* Then reset exit marker */ X if (!bypass) { X if ((key == 0) || ((key >= '0') && (key <= '9'))) X key = checkchoice(x, y, key, &lastkey); X } X switch (key) { X case 0: X break; X case '8': X y = y + 1; X break; X case '7': X y = y + 1; X x = x - 1; X break; X case '1': X y = y - 1; X x = x - 1; X break; X case '9': X x = x + 1; X y = y + 1; X break; X case '3': X y = y - 1; X x = x + 1; X break; X case '2': X y = y - 1; X break; X case '4': X x = x - 1; X break; X case '6': X x = x + 1; X break; X case 'D': X docked = cdock(x, y, &window); X break; X case 'B': X cbuildbase(semid, x, y, window); X break; X case 'l': X if (cphasers(x, y, 'A', 'Z') == 0) X lastkey = 0; X break; X case 'L': X if (cphasers(x, y, BASE, BASE) == 0) X lastkey = 0; X break; X/* X case 'm': X cmines(semid, x, y); X break; X*/ X case 't': X if (!cftorps(x, y, torparray, &ntfree, window)) X lastkey = 0; X break; X case 's': X case 'S': X if ((ship->wstatus & SHIELD_DEAD) == 0) X ship->wstatus = ship->wstatus ^ SHIELD_UP; X break; X } X if (x < 0) X x = 0; X if (y < 0) X y = 0; X if (x >= SIZE) X x = SIZE - 1; X if (y >= SIZE) X y = 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 x = oldx; /* If not, no movement! */ X y = oldy; X } X } X X/* End Engine check */ X X if ((x != oldx) || (y != oldy)) { X printf("Position %d %d\n", x, y); X docked = 0; /* Undock craft */ X readgrid(x, y, &oldgrid); X if (oldgrid.type == VOID) { X x = oldgrid.energy; X y = oldgrid.shield; X readgrid(x, y, &oldgrid); X } X if (oldgrid.type != EMPTY) { /* 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 } X if (oldgrid.type == MINE) { X explode(x, y, (MINE_BOOM * EXPLOSION), MINE_BOOM); X } X oldgrid.type = EMPTY; X } X storegrid(x, y, oldgrid); X x = oldx; /* Go backwards */ X y = oldy; X if (tempenergy < 0) X tempenergy = 0 - tempenergy; X onegrid.energy -= ((tempenergy / 2) + 1000); X storegrid(x, y, onegrid); X } else { X readgrid(oldx, oldy, &onegrid); X X onegrid.energy -= sqr(((x - oldx) * (x - oldx)) + ((y - oldy) * (y - oldy))) * (roll(E_RAND_PER_MOVE) + E_PER_MOVE); X storegrid(x, y, 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 readgrid(x, y, &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; X ship->energy += tmpint; 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) { X ship->shield++; X onegrid.shield++; X } X if (ship->engines < 100) X ship->engines += 1; X if (ship->life < 100) X ship->life += 1; X if (ship->crew < 100) X ship->crew += 1; X if (ship->hull < 100) X ship->hull += 1; X if (ship->lasers < 100) X ship->lasers += 1; X if (ship->mines < 100) X ship->mines += 1; X if (ship->torps < 100) X ship->torps += 1; X ship->numtorps++; X ship->nummines++; 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 storegrid(x, y, onegrid); X } X readgrid(x, y, &onegrid); /* Delete ship */ X onegrid.type = EMPTY; X storegrid(x, y, 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 *intbfr -= 1; X shmdt(buffer); /* Detach shared segment */ X exit(0); X} END_OF_FILE if test 13370 -ne `wc -c <'drone.c'`; then echo shar: \"'drone.c'\" unpacked with wrong size! fi # end of 'drone.c' fi if test -f 'torpedoes.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'torpedoes.c'\" else echo shar: Extracting \"'torpedoes.c'\" \(7558 characters\) sed "s/^X//" >'torpedoes.c' <<'END_OF_FILE' X/* Part of the COSMOS package X Copyright 1988 Karl Denninger & MCS, Inc. X All Rights Reserved X*/ X X X#include "cosmos.h" X extern struct nameblock *ship; X movetorps(ta, ntfree) struct torps ta[]; int *ntfree; X{ X int tcount; X struct grid ourgrid; X int key; X int xx, yy; X int dist; X int x1, y1, xv, yv, count; X X if (! *ntfree) X return(0); /* Exit -- no torpedoes to move */ X for (tcount = 0; tcount < MAXFTORPS; tcount++) { X if (ta[tcount].inuse) { /* Process this entry */ X readgrid(ta[tcount].x, ta[tcount].y, &ourgrid); X if (ourgrid.type != TORPEDO) { X ta[tcount].inuse = 0; /* Free slot */ X (*ntfree)--; /* Free torpedo in flight */ X } else { X ourgrid.type = EMPTY; X ourgrid.energy = 0; X ourgrid.shield = 0; X storegrid(ta[tcount].x, ta[tcount].y, ourgrid); X if ((ta[tcount].destx == -1) && (ta[tcount].desty == -1)) { X if (ta[tcount].homeship) { X xx = ta[tcount].x; X yy = ta[tcount].y; X key = findobj(&xx, &yy, &dist, X ta[tcount].homeship, X ta[tcount].homeship, X window_size[ship->type]); X if (!key) X key = ta[tcount].lastkey; X else X ta[tcount].lastkey = key; X } X } else X key = give_dir(ta[tcount].x, X ta[tcount].y, X ta[tcount].destx, X ta[tcount].desty); X xx = ta[tcount].x; X yy = ta[tcount].y; X switch(key) { X case 0: X break; X case '8': X yy = yy + 1; X break; X case '7': X yy= yy + 1; X xx = xx - 1; X break; X case '1': X yy = yy - 1; X xx = xx - 1; X break; X case '9': X xx = xx + 1; X yy = yy + 1; X break; X case '3': X yy = yy - 1; X xx = xx + 1; X break; X case '2': X yy = yy - 1; X break; X case '4': X xx = xx - 1; X break; X case '6': X xx = xx + 1; X break; X } X if ((xx < 0) || (yy < 0) || (xx >= SIZE) || (yy >= SIZE)) { X (*ntfree)--; X ta[tcount].inuse = 0; /* Delete */ X } else { X readgrid(xx, yy, &ourgrid); X if (ourgrid.type == VOID) { /* Warp */ X xx = ourgrid.energy; /* Get x */ X yy = ourgrid.shield; /* And Y */ X readgrid(xx, yy, &ourgrid); X } X if (ourgrid.type != EMPTY) { X ta[tcount].inuse = 0; /* Boom! */ X if ((ourgrid.type >= 'A') && (ourgrid.type <= 'Z')) X ship->points += 100; X givedamage(xx, yy, ta[tcount].level * TORP_EREL, ship, 0); X (*ntfree)--; X } else { X ourgrid.type = TORPEDO; X ourgrid.energy = 5; X ourgrid.shield = 0; X storegrid(xx, yy, ourgrid); X ta[tcount].x = xx; X ta[tcount].y = yy; X if (ta[tcount].life-- <= 0) { X givedamage(xx, yy, X (ta[tcount].level * TORP_EREL), ship, 0); X (*ntfree)--; X ta[tcount].inuse = 0; X } X } X } X } X } X } X} X X firetorps(x, y, torparray, semid, ntfree, window) int x, y; struct torps torparray[]; int semid; int *ntfree; int window; X{ X static int key; X static int destx; X static int desty; X static int zz; X int xx, yy; X int x1, y1; X int z = 0; X int dist; X struct grid ourgrid; X char tmp[80]; X X release(semid); X mvaddstr(22,20,"Torpedo -> "); X refresh(); X get_str(tmp); X acquire(semid); X if (ship->wstatus & SHIELD_UP) { X mvaddstr(23,20,"Captain! The shields are UP!"); X clrtoeol(); X return(0); X } X xx = x; X yy = y; X if (tmp[0]) { X if ((!isdigit(tmp[0])) && (tmp[0] != '-')) { X destx = x; X desty = y; X key = findobj(&destx, &desty, &dist, toupper(tmp[0]), toupper(tmp[0]), window); X if (!key) { X mvaddstr(23,20,"Captain, I can't locate that target!"); X clrtoeol(); X return(0); X } X destx = -1; X desty = -1; X zz = toupper(tmp[0]); X } else { X sscanf(tmp, "%d %d", &x1, &y1); X destx = (x1 + x); X desty = (y1 + y); X key = give_dir(xx, yy, destx, desty); X } X } X xx = x; yy = y; X switch(key) { X case '9': X xx++; X yy++; X break; X case '6': X xx++; X break; X case '3': X xx++; X yy--; X break; X case '2': X yy--; X break; X case '1': X xx--; X yy--; X break; X case '4': X xx--; X break; X case '7': X xx--; X yy++; X break; X case '8': X yy++; X break; X } X if ((xx < 0) || (xx >= SIZE) || (yy < 0) || (yy >= SIZE)) X return(0); /* Don't launch, off grid */ X readgrid(xx, yy, &ourgrid); X if (ourgrid.type != EMPTY) { /* Something is there */ X mvaddstr(23,20,"ABORT! Something is in the way of our launch!"); X clrtoeol(); X return(0); X } X if (*ntfree >= num_ftorps[ship->type]) { X mvaddstr(23,20,"Information system overload; unable to launch"); X clrtoeol(); X return(0); X } X if (ship->numtorps <= 0) { X mvaddstr(23,20,"No torpedoes on board Captain!"); X clrtoeol(); X return(0); X } X ship->numtorps--; /* Subtract one torpedo */ X for (z = 0; z < num_ftorps[ship->type]; z++) { X if (!torparray[z].inuse) { /* Found one free! */ X (*ntfree)++; X torparray[z].x = xx; X torparray[z].y = yy; X torparray[z].destx = 0; X torparray[z].desty = 0; X if ((destx == -1) && (desty == -1)) { X torparray[z].homeship = zz; X torparray[z].destx = -1; X torparray[z].desty = -1; X } else { X torparray[z].homeship = 0; X torparray[z].destx = destx; X torparray[z].desty = desty; X } X torparray[z].travelled = 0; X torparray[z].life = (ship->type * 2); /* Max dist */ X torparray[z].level = (ship->type); /* Blast size */ X if (!torparray[z].level) X torparray[z].level++; X torparray[z].inuse++; /* Entry used */ X mvaddstr(23,20,"Torpedo fired!"); X clrtoeol(); X ourgrid.type = TORPEDO; X storegrid(xx, yy, ourgrid); X return(1); X } X } X /* If you get here, you're in trouble -- something went wrong */ X mvaddstr(23,20,"Captain! The torpedo tubes are jammed!"); X clrtoeol(); X refresh(); X return(0); X} X X cftorps(x, y, torparray, ntfree, window) int x, y; struct torps torparray[]; int *ntfree; int window; X{ X static int key; X static int destx; X static int desty; X static int zz; X int xx, yy; X int x1, y1; X int z = 0; X int dist; X struct grid ourgrid; X char tmp[80]; X X if (ship->torps < 30) { X if (roll(200) > ship->torps) X return(0); X } X destx = x; X desty = y; X key = findobj(&destx, &desty, &dist, 'A', 'Z', window); X if (!key) { X return(0); X } X readgrid(destx, desty, &ourgrid); X zz = ourgrid.type; /* Save character */ X xx = x; yy = y; X switch(key) { X case '9': X xx++; X yy++; X break; X case '6': X xx++; X break; X case '3': X xx++; X yy--; X break; X case '2': X yy--; X break; X case '1': X xx--; X yy--; X break; X case '4': X xx--; X break; X case '7': X xx--; X yy++; X break; X case '8': X yy++; X break; X } X if ((xx < 0) || (xx >= SIZE) || (yy < 0) || (yy >= SIZE)) X return(0); /* Don't launch, off grid */ X readgrid(xx, yy, &ourgrid); X if (ourgrid.type != EMPTY) { /* Something is there */ X return(0); X } X if (*ntfree >= num_ftorps[ship->type]) { X return(0); X } X if (ship->numtorps <= 0) { X return(0); X } X ship->numtorps--; /* Subtract one torpedo */ X for (z = 0; z < num_ftorps[ship->type]; z++) { X if (!torparray[z].inuse) { /* Found one free! */ X (*ntfree)++; X torparray[z].x = xx; X torparray[z].y = yy; X torparray[z].destx = 0; X torparray[z].desty = 0; X torparray[z].homeship = zz; X torparray[z].destx = -1; X torparray[z].desty = -1; X torparray[z].travelled = 0; X torparray[z].life = (ship->type * 2); /* Max dist */ X torparray[z].level = (ship->type); /* Blast size */ X if (!torparray[z].level) X torparray[z].level++; X torparray[z].inuse++; /* Entry used */ X ourgrid.type = TORPEDO; X storegrid(xx, yy, ourgrid); X return(1); X } X } X /* If you get here, you're in trouble -- something went wrong */ X return(0); X} END_OF_FILE if test 7558 -ne `wc -c <'torpedoes.c'`; then echo shar: \"'torpedoes.c'\" unpacked with wrong size! fi # end of 'torpedoes.c' fi echo shar: End of archive 2 \(of 3\). cp /dev/null ark2isdone 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"
karl@ddsw1.MCS.COM (Karl Denninger) (11/18/88)
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 <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 3 (of 3)." # Contents: cosmos.c funcs.c # Wrapped by karl@ddsw1 on Thu Nov 17 23:53:11 1988 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'cosmos.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'cosmos.c'\" else echo shar: Extracting \"'cosmos.c'\" \(23237 characters\) sed "s/^X//" >'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 <Q> 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,"<<<ENTER>>> 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, <Q> 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"