NetBSD/games/warp/warp.c

402 lines
10 KiB
C

char rcsid[] = "@(#)Header: warp.c,v 7.0.1.3 86/12/12 17:07:44 lwall Exp";
/* warp -- a real-time space war program
* author: Larry Wall
* helpers: Jonathan and Mark Biggar, and Dan Faigin
* special thanks to my sweetie Gloria who suggested the Planet Crusher
*
* Copyright (c) 2020 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Larry Wall.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* version 5.0 04/20/83
* 5.1 05/05/83 various tidbits
* 5.2 05/12/83 VAX -> vax, ifdef'ed a SIGCONT
* 5.3 05/24/83 RCS
*
* Log: warp.c,v
* Revision 7.0.1.3 86/12/12 17:07:44 lwall
* Baseline for net release.
*
* Revision 7.0.1.2 86/10/20 12:08:00 lwall
* Made all exits reset tty.
*
* Revision 7.0.1.1 86/10/16 10:54:13 lwall
* Added Damage. Fixed random bugs.
*
* Revision 7.0 86/10/08 15:14:47 lwall
* Split into separate files. Added amoebas and pirates.
*
* Revision 6.4 83/12/16 13:11:45 lwall
* Handled 15 bit random number generators.
*
* Fixed array overflow bug on multiple zaps.
*
* Multiple zaps now consolidated to minimize output.
*
* Tholian jackpot games outlawed under difficulty 15.
*
* Revision 6.3 83/08/24 11:17:49 lwall
* Fixed array overflow bug on multiple zap.
*
* Revision 6.2 83/08/23 18:06:37 lwall
* Added zap command.
* Warp -s should now work on dumb terminals
* Specifying difficulty >= 40 now just makes it a special game.
* SIGTTOU #ifdef'ed.
* No-delay read provided as alternative to FIONREAD.
* Warp won't report "-1 obsolete" when there are no Enterprises left.
* Some high-difficulty tuning.
*
* Revision 6.1 83/08/17 08:49:03 lwall
* Fixed obscure bug in storing UP that caused a %. in CM to occasionally
* foist garbage onto the screen.
*
* Revision 6.0 83/08/08 17:09:26 lwall
* New baseline version for net release.
*
* Revision 5.5 83/08/01 10:59:56 lwall
* Cloaking for the Enterprise.
* Difficulty now goes to 99, and many activities depending on difficulty
* have been adjusted in frequency.
* Simplified exit sequence, and reduced dependencies on control
* characters. You needn't see the scoreboard if you don't want to.
* Hitting i,w,c, or v switches to Enterprise. Hitting p switches to Base.
* Excessive use of q is not allowed.
* Excessive use of D is not allowed.
* Scoreboard may depend on either full name or login name.
* Integrated scoreboard lister. Login name now shows up on scoreboard.
* "Hidden" startup options are now upper case.
* Checks upon startup for no cursor movement, or screen too small.
* Checks upon startup that WARPDIR is correctly protected, and that warp
* is running setuid. As an additional bonus this prevents root from
* running warp, which mucks things up, UN*X be blessed.
* All gets's turned into fgets's for safety.
* Bonus Enterprises and Bases.
* Escalating bonuses for saving Base and Enterprise.
* Escalating Enterprise energy.
* Turbolasers decrease with distance.
* Really smart enemies can see through stars occasionally.
* Occasional Tholian jackpot waves. Tholians are a trifle nastier.
* Choleric Gorns.
* An O or o can miss seeing you. Enemies can avoid a stationary O, o, or X.
* Warp 3 enemies and other nastinesses are possible in massacre mode.
* Enemies that decide to navigate when they see you can do other things than
* just come toward you.
* Gorns occasionally launch a salvo for the fun of it.
* Only star and enemy explosions can keep the round going now.
* Bounces don't always go back to starting spot now.
* Better full name processing. USG quirks handled. & substitution also
* handled now (whoever dreamed up that one must have been in the middle
* of the night before the morning after).
* Catch ^D on fgets.
* Version number printer.
* Less signal catching during debugging.
*
* Revision 5.4 83/06/24 09:28:38 lwall
* 16 bit random number generators are now supported.
* Made warp not blow up on a null save file.
* Warp now prints E and B before the stars.
* Fixed bug which caused torp count to get decremented even when no torp
* was launched because of an obstacle.
* Put %<n>ld formats where appropriate.
* Fixed E: 0 0 bug on refresh.
*
* Revision 5.3 83/05/24 14:03:10 lwall
* Starting RCS
*
*/
#include "INTERN.h"
#include "warp.h"
#include "EXTERN.h"
#include "bang.h"
#include "init.h"
#include "intrp.h"
#include "object.h"
#include "move.h"
#include "play.h"
#include "score.h"
#include "sig.h"
#include "term.h"
#include "them.h"
#include "us.h"
#include "util.h"
#include "version.h"
#include "weapon.h"
int
main(int argc, char *argv[])
{
char tmp, *s, *tcbuf;
FILE *savfil;
#ifdef lint /* to suppress "defined but never used" */
# ifdef SIGTSTP
(void)stop_catcher();
# endif
# ifdef SIGCONT
(void)cont_catcher();
# endif
#endif
while (--argc > 0 && (*++argv)[0] == '-')
for (s = argv[0]+1; *s != '\0'; s++)
switch (*s) {
case '&':
amoebaspec = true;
beginner = true;
break;
case 'A':
apolspec = true;
beginner = true;
break;
case 'b':
beginner = true;
break;
case 'C':
crushspec = true;
beginner = true;
break;
case 'D':
debugging = true;
#ifdef DEBUGGING
debug = atoi(++s);
#endif
s += strlen(s)-1;
break;
case 'd':
s++;
if (*s == '=') s++;
ismarts = atoi(s);
if (ismarts <= 0)
ismarts = 1;
if (ismarts > 99)
ismarts = 99;
if (ismarts > 40)
beginner = true;
s += strlen(s)-1;
break;
case 'E':
klingspec = true;
beginner = true;
s++;
if (*s == '=') s++;
inumenemies = atoi(s);
s += strlen(s)-1;
break;
case 'F':
friendspec = true;
beginner = true;
s++;
if (*s == '=') s++;
inumfriends = atoi(s);
s += strlen(s)-1;
break;
case 'G':
gornspec = true;
beginner = true;
break;
case 'l':
lowspeed = true;
break;
case 'm':
metakey = true;
break;
case 'M':
massacre = true;
break;
case 'P':
piratespec = true;
beginner = true;
s++;
if (*s == '=') s++;
inumpirates = atoi(s);
s += strlen(s)-1;
break;
case 'S':
prespec = true;
beginner = true;
s++;
if (*s == '=') s++;
if (*s)
prescene = atoi(s);
else
prescene = -1;
s += strlen(s)-1;
break;
case 'R':
romspec = true;
beginner = true;
break;
case '*':
starspec = true;
beginner = true;
s++;
if (*s == '=') s++;
inumstars = atoi(s);
s += strlen(s)-1;
break;
case 's':
scorespec = true;
break;
case 'T':
tholspec = true;
beginner = true;
break;
case 'x':
experimenting = true;
break;
case 'v':
version();
exit(0);
break;
default:
fprintf(stderr,"warp: illegal option %c\n", *s);
fprintf(stderr, "Usage: warp -dn -b -x -v -s\n");
exit(1);
}
if (argc != 0) {
fprintf(stderr, "Usage: warp -dn -b -x -v -s\n");
exit(1);
}
bang_init();
move_init();
object_init();
play_init();
them_init();
us_init();
util_init();
weapon_init();
tcbuf = malloc(1024);
intrp_init(tcbuf);
if (chdir(warplib) < 0)
fprintf(stderr,NOCD,warplib);
term_init();
term_set(tcbuf);
free(tcbuf);
umask(022); /* mustn't rely on incoming umask--could be 033 which */
/* would disable people from running wscore */
score_init();
sig_init();
if (totalscore) {
clear();
mvaddstr(12,25,"*** restoring saved game ***");
roundsleep(1);
}
srandom(getpid());
do {
for (keepgoing = true;;) {
if (!experimenting) {
if ((savfil = fopen(savefilename,"w")) == NULL) {
resetty();
printf("Can't open savefile `%s'\r\n", savefilename);
finalize(1);
}
fprintf(savfil,
"%-8s %10ld, %2d,%5d,%2d,%2d,%3d %c%c%c%c%c%c%c%c%c\n",
logname, totalscore, smarts, cumsmarts,
numents, numbases, wave,
apolspec ? 'a' : ' ',
beginner ? 'b' : ' ',
crushspec ? 'c' : ' ',
gornspec ? 'g' : ' ',
massacre ? 'm' : ' ',
romspec ? 'r' : ' ',
tholspec ? 't' : ' ',
lowspeed ? 'l' : ' ',
amoebaspec ? '&' : ' '
);
fprintf(savfil," running on %s, process #%d\n",
term+5,getpid());
fclose(savfil);
}
lastscore = totalscore;
initialize();
play();
cumsmarts += smarts;
wavescore();
if (numents<=0 && numbases<=0)
keepgoing = false;
if (!keepgoing) break;
do {
if (experimenting) {
mvaddstr(23,15,
" [Hit space to continue, 'q' to quit] ");
}
else {
mvaddstr(23,15,
"[Hit space to continue, 's' to save, 'q' to quit]");
}
sleep(1);
fflush(stdout);
eat_typeahead();
getcmd(&tmp);
if (tmp == BREAKCH || tmp == INTRCH) {
mvaddstr(23,15,
" ");
mvaddstr(23,33,
"Really quit? ");
getcmd(&tmp);
if (tmp == 'y' || tmp == 'Y')
tmp = 'q';
else
tmp = 1;
}
} while (tmp != INTRCH && tmp != BREAKCH && !strchr(" qQs",tmp));
if (tmp != ' ' && tmp != 's') break;
if (!beginner && smarts < 20)
smarts += 4;
else if (!beginner && smarts < 35)
smarts += 2;
else if (smarts < 99)
smarts++;
if (tmp == 's') save_game();
}
score();
} while (justonemoretime);
if (!experimenting)
unlink(savefilename);
clear();
resetty();
exit(0);
}