xref: /netbsd/games/warp/warp.c (revision abca1099)
137c3bdbeSkamil char rcsid[] = "@(#)Header: warp.c,v 7.0.1.3 86/12/12 17:07:44 lwall Exp";
2c503d12fSkamil 
3c503d12fSkamil /*	warp -- a real-time space war program
4c503d12fSkamil  *	author: Larry Wall
5c503d12fSkamil  *	helpers: Jonathan and Mark Biggar, and Dan Faigin
6c503d12fSkamil  *	special thanks to my sweetie Gloria who suggested the Planet Crusher
7c503d12fSkamil  *
8286a3ee2Skamil  * Copyright (c) 2020 The NetBSD Foundation, Inc.
9286a3ee2Skamil  * All rights reserved.
10c503d12fSkamil  *
11286a3ee2Skamil  * This code is derived from software contributed to The NetBSD Foundation
12286a3ee2Skamil  * by Larry Wall.
13286a3ee2Skamil  *
14286a3ee2Skamil  * Redistribution and use in source and binary forms, with or without
15286a3ee2Skamil  * modification, are permitted provided that the following conditions
16286a3ee2Skamil  * are met:
17286a3ee2Skamil  * 1. Redistributions of source code must retain the above copyright
18286a3ee2Skamil  *    notice, this list of conditions and the following disclaimer.
19286a3ee2Skamil  * 2. Redistributions in binary form must reproduce the above copyright
20286a3ee2Skamil  *    notice, this list of conditions and the following disclaimer in the
21286a3ee2Skamil  *    documentation and/or other materials provided with the distribution.
22286a3ee2Skamil  *
23286a3ee2Skamil  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
24286a3ee2Skamil  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25286a3ee2Skamil  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26286a3ee2Skamil  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
27286a3ee2Skamil  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28286a3ee2Skamil  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29286a3ee2Skamil  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30286a3ee2Skamil  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31286a3ee2Skamil  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32286a3ee2Skamil  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33286a3ee2Skamil  * POSSIBILITY OF SUCH DAMAGE.
34c503d12fSkamil  *
35c503d12fSkamil  * version 5.0  04/20/83
36c503d12fSkamil  *         5.1  05/05/83	various tidbits
37c503d12fSkamil  *	   5.2  05/12/83	VAX -> vax, ifdef'ed a SIGCONT
38c503d12fSkamil  *	   5.3  05/24/83	RCS
39c503d12fSkamil  *
4037c3bdbeSkamil  * Log:	warp.c,v
41c503d12fSkamil  * Revision 7.0.1.3  86/12/12  17:07:44  lwall
42c503d12fSkamil  * Baseline for net release.
43c503d12fSkamil  *
44c503d12fSkamil  * Revision 7.0.1.2  86/10/20  12:08:00  lwall
45c503d12fSkamil  * Made all exits reset tty.
46c503d12fSkamil  *
47c503d12fSkamil  * Revision 7.0.1.1  86/10/16  10:54:13  lwall
48c503d12fSkamil  * Added Damage.  Fixed random bugs.
49c503d12fSkamil  *
50c503d12fSkamil  * Revision 7.0  86/10/08  15:14:47  lwall
51c503d12fSkamil  * Split into separate files.  Added amoebas and pirates.
52c503d12fSkamil  *
53c503d12fSkamil  * Revision 6.4  83/12/16  13:11:45  lwall
54c503d12fSkamil  * Handled 15 bit random number generators.
55c503d12fSkamil  *
56c503d12fSkamil  * Fixed array overflow bug on multiple zaps.
57c503d12fSkamil  *
58c503d12fSkamil  * Multiple zaps now consolidated to minimize output.
59c503d12fSkamil  *
60c503d12fSkamil  * Tholian jackpot games outlawed under difficulty 15.
61c503d12fSkamil  *
62c503d12fSkamil  * Revision 6.3  83/08/24  11:17:49  lwall
63c503d12fSkamil  * Fixed array overflow bug on multiple zap.
64c503d12fSkamil  *
65c503d12fSkamil  * Revision 6.2  83/08/23  18:06:37  lwall
66c503d12fSkamil  * Added zap command.
67c503d12fSkamil  * Warp -s should now work on dumb terminals
68c503d12fSkamil  * Specifying difficulty >= 40 now just makes it a special game.
69c503d12fSkamil  * SIGTTOU #ifdef'ed.
70c503d12fSkamil  * No-delay read provided as alternative to FIONREAD.
71c503d12fSkamil  * Warp won't report "-1 obsolete" when there are no Enterprises left.
72c503d12fSkamil  * Some high-difficulty tuning.
73c503d12fSkamil  *
74c503d12fSkamil  * Revision 6.1  83/08/17  08:49:03  lwall
75c503d12fSkamil  * Fixed obscure bug in storing UP that caused a %. in CM to occasionally
76c503d12fSkamil  * foist garbage onto the screen.
77c503d12fSkamil  *
78c503d12fSkamil  * Revision 6.0  83/08/08  17:09:26  lwall
79c503d12fSkamil  * New baseline version for net release.
80c503d12fSkamil  *
81c503d12fSkamil  * Revision 5.5  83/08/01  10:59:56  lwall
82c503d12fSkamil  * Cloaking for the Enterprise.
83c503d12fSkamil  * Difficulty now goes to 99, and many activities depending on difficulty
84c503d12fSkamil  *     have been adjusted in frequency.
85c503d12fSkamil  * Simplified exit sequence, and reduced dependencies on control
86c503d12fSkamil  *     characters.  You needn't see the scoreboard if you don't want to.
87c503d12fSkamil  * Hitting i,w,c, or v switches to Enterprise.  Hitting p switches to Base.
88c503d12fSkamil  * Excessive use of q is not allowed.
89c503d12fSkamil  * Excessive use of D is not allowed.
90c503d12fSkamil  * Scoreboard may depend on either full name or login name.
91c503d12fSkamil  * Integrated scoreboard lister.  Login name now shows up on scoreboard.
92c503d12fSkamil  * "Hidden" startup options are now upper case.
93c503d12fSkamil  * Checks upon startup for no cursor movement, or screen too small.
94c503d12fSkamil  * Checks upon startup that WARPDIR is correctly protected, and that warp
95c503d12fSkamil  *     is running setuid.  As an additional bonus this prevents root from
96c503d12fSkamil  *     running warp, which mucks things up, UN*X be blessed.
97c503d12fSkamil  * All gets's turned into fgets's for safety.
98c503d12fSkamil  * Bonus Enterprises and Bases.
99c503d12fSkamil  * Escalating bonuses for saving Base and Enterprise.
100c503d12fSkamil  * Escalating Enterprise energy.
101c503d12fSkamil  * Turbolasers decrease with distance.
102c503d12fSkamil  * Really smart enemies can see through stars occasionally.
103c503d12fSkamil  * Occasional Tholian jackpot waves.  Tholians are a trifle nastier.
104c503d12fSkamil  * Choleric Gorns.
105c503d12fSkamil  * An O or o can miss seeing you.  Enemies can avoid a stationary O, o, or X.
106c503d12fSkamil  * Warp 3 enemies and other nastinesses are possible in massacre mode.
107c503d12fSkamil  * Enemies that decide to navigate when they see you can do other things than
108c503d12fSkamil  *     just come toward you.
109c503d12fSkamil  * Gorns occasionally launch a salvo for the fun of it.
110c503d12fSkamil  * Only star and enemy explosions can keep the round going now.
111c503d12fSkamil  * Bounces don't always go back to starting spot now.
112c503d12fSkamil  * Better full name processing.  USG quirks handled.  & substitution also
113c503d12fSkamil  *     handled now (whoever dreamed up that one must have been in the middle
114c503d12fSkamil  *     of the night before the morning after).
115c503d12fSkamil  * Catch ^D on fgets.
116c503d12fSkamil  * Version number printer.
117c503d12fSkamil  * Less signal catching during debugging.
118c503d12fSkamil  *
119c503d12fSkamil  * Revision 5.4  83/06/24  09:28:38  lwall
120c503d12fSkamil  * 16 bit random number generators are now supported.
121c503d12fSkamil  * Made warp not blow up on a null save file.
122c503d12fSkamil  * Warp now prints E and B before the stars.
123c503d12fSkamil  * Fixed bug which caused torp count to get decremented even when no torp
124c503d12fSkamil  *     was launched because of an obstacle.
125c503d12fSkamil  * Put %<n>ld formats where appropriate.
126c503d12fSkamil  * Fixed E: 0  0 bug on refresh.
127c503d12fSkamil  *
128c503d12fSkamil  * Revision 5.3  83/05/24  14:03:10  lwall
129c503d12fSkamil  * Starting RCS
130c503d12fSkamil  *
131c503d12fSkamil  */
132c503d12fSkamil 
133c503d12fSkamil #include "INTERN.h"
134c503d12fSkamil #include "warp.h"
135c503d12fSkamil #include "EXTERN.h"
136c503d12fSkamil #include "bang.h"
137c503d12fSkamil #include "init.h"
138c503d12fSkamil #include "intrp.h"
139c503d12fSkamil #include "object.h"
140c503d12fSkamil #include "move.h"
141c503d12fSkamil #include "play.h"
142c503d12fSkamil #include "score.h"
143c503d12fSkamil #include "sig.h"
144c503d12fSkamil #include "term.h"
145c503d12fSkamil #include "them.h"
146c503d12fSkamil #include "us.h"
147c503d12fSkamil #include "util.h"
148c503d12fSkamil #include "version.h"
149c503d12fSkamil #include "weapon.h"
150c503d12fSkamil 
1518a5cd4c8Skamil int
main(int argc,char * argv[])152c8c17207Schristos main(int argc, char *argv[])
153c503d12fSkamil {
154c503d12fSkamil     char tmp, *s, *tcbuf;
155c503d12fSkamil 
156c503d12fSkamil     FILE *savfil;
157c503d12fSkamil 
158c503d12fSkamil #ifdef lint  /* to suppress "defined but never used" */
159c503d12fSkamil # ifdef SIGTSTP
160c503d12fSkamil     (void)stop_catcher();
161c503d12fSkamil # endif
162c503d12fSkamil # ifdef SIGCONT
163c503d12fSkamil     (void)cont_catcher();
164c503d12fSkamil # endif
165c503d12fSkamil #endif
166c503d12fSkamil 
167c503d12fSkamil     while (--argc > 0 && (*++argv)[0] == '-')
168c503d12fSkamil 	for (s = argv[0]+1; *s != '\0'; s++)
169c503d12fSkamil 	    switch (*s) {
170c503d12fSkamil 	    case '&':
171c8c17207Schristos 		amoebaspec = true;
172c8c17207Schristos 		beginner = true;
173c503d12fSkamil 		break;
174c503d12fSkamil 	    case 'A':
175c8c17207Schristos 		apolspec = true;
176c8c17207Schristos 		beginner = true;
177c503d12fSkamil 		break;
178c503d12fSkamil 	    case 'b':
179c8c17207Schristos 		beginner = true;
180c503d12fSkamil 		break;
181c503d12fSkamil 	    case 'C':
182c8c17207Schristos 		crushspec = true;
183c8c17207Schristos 		beginner = true;
184c503d12fSkamil 		break;
185c503d12fSkamil 	    case 'D':
186c8c17207Schristos 		debugging = true;
187c503d12fSkamil #ifdef DEBUGGING
188c503d12fSkamil 		debug = atoi(++s);
189c503d12fSkamil #endif
190c503d12fSkamil 		s += strlen(s)-1;
191c503d12fSkamil 		break;
192c503d12fSkamil 	    case 'd':
193c503d12fSkamil 		s++;
194c503d12fSkamil 		if (*s == '=') s++;
195c503d12fSkamil 		ismarts = atoi(s);
196c503d12fSkamil 		if (ismarts <= 0)
197c503d12fSkamil 		    ismarts = 1;
198c503d12fSkamil 		if (ismarts > 99)
199c503d12fSkamil 		    ismarts = 99;
200c503d12fSkamil 		if (ismarts > 40)
201c8c17207Schristos 		    beginner = true;
202c503d12fSkamil 		s += strlen(s)-1;
203c503d12fSkamil 		break;
204c503d12fSkamil 	    case 'E':
205c8c17207Schristos 		klingspec = true;
206c8c17207Schristos 		beginner = true;
207c503d12fSkamil 		s++;
208c503d12fSkamil 		if (*s == '=') s++;
209c503d12fSkamil 		inumenemies = atoi(s);
210c503d12fSkamil 		s += strlen(s)-1;
211c503d12fSkamil 		break;
212c503d12fSkamil 	    case 'F':
213c8c17207Schristos 		friendspec = true;
214c8c17207Schristos 		beginner = true;
215c503d12fSkamil 		s++;
216c503d12fSkamil 		if (*s == '=') s++;
217c503d12fSkamil 		inumfriends = atoi(s);
218c503d12fSkamil 		s += strlen(s)-1;
219c503d12fSkamil 		break;
220c503d12fSkamil 	    case 'G':
221c8c17207Schristos 		gornspec = true;
222c8c17207Schristos 		beginner = true;
223c503d12fSkamil 		break;
224c503d12fSkamil 	    case 'l':
225c8c17207Schristos 		lowspeed = true;
226c503d12fSkamil 		break;
227c503d12fSkamil 	    case 'm':
228c8c17207Schristos 		metakey = true;
229c503d12fSkamil 		break;
230c503d12fSkamil 	    case 'M':
231c8c17207Schristos 		massacre = true;
232c503d12fSkamil 		break;
233c503d12fSkamil 	    case 'P':
234c8c17207Schristos 		piratespec = true;
235c8c17207Schristos 		beginner = true;
236c503d12fSkamil 		s++;
237c503d12fSkamil 		if (*s == '=') s++;
238c503d12fSkamil 		inumpirates = atoi(s);
239c503d12fSkamil 		s += strlen(s)-1;
240c503d12fSkamil 		break;
241c503d12fSkamil 	    case 'S':
242c8c17207Schristos 		prespec = true;
243c8c17207Schristos 		beginner = true;
244c503d12fSkamil 		s++;
245c503d12fSkamil 		if (*s == '=') s++;
246c503d12fSkamil 		if (*s)
247c503d12fSkamil 		    prescene = atoi(s);
248c503d12fSkamil 		else
249c503d12fSkamil 		    prescene = -1;
250c503d12fSkamil 		s += strlen(s)-1;
251c503d12fSkamil 		break;
252c503d12fSkamil 	    case 'R':
253c8c17207Schristos 		romspec = true;
254c8c17207Schristos 		beginner = true;
255c503d12fSkamil 		break;
256c503d12fSkamil 	    case '*':
257c8c17207Schristos 		starspec = true;
258c8c17207Schristos 		beginner = true;
259c503d12fSkamil 		s++;
260c503d12fSkamil 		if (*s == '=') s++;
261c503d12fSkamil 		inumstars = atoi(s);
262c503d12fSkamil 		s += strlen(s)-1;
263c503d12fSkamil 		break;
264c503d12fSkamil 	    case 's':
265c8c17207Schristos 		scorespec = true;
266c503d12fSkamil 		break;
267c503d12fSkamil 	    case 'T':
268c8c17207Schristos 		tholspec = true;
269c8c17207Schristos 		beginner = true;
270c503d12fSkamil 		break;
271c503d12fSkamil 	    case 'x':
272c8c17207Schristos 		experimenting = true;
273c503d12fSkamil 		break;
274c503d12fSkamil 	    case 'v':
275c503d12fSkamil 		version();
276c503d12fSkamil 		exit(0);
277c503d12fSkamil 		break;
278c503d12fSkamil 	    default:
279c503d12fSkamil 		fprintf(stderr,"warp: illegal option %c\n", *s);
280c503d12fSkamil 		fprintf(stderr, "Usage: warp -dn -b -x -v -s\n");
281c503d12fSkamil 		exit(1);
282c503d12fSkamil 	    }
283c503d12fSkamil     if (argc != 0) {
284c503d12fSkamil 	fprintf(stderr, "Usage: warp -dn -b -x -v -s\n");
285c503d12fSkamil 	exit(1);
286c503d12fSkamil     }
287c503d12fSkamil     bang_init();
288c503d12fSkamil     move_init();
289c503d12fSkamil     object_init();
290c503d12fSkamil     play_init();
291c503d12fSkamil     them_init();
292c503d12fSkamil     us_init();
293c503d12fSkamil     util_init();
294c503d12fSkamil     weapon_init();
295c503d12fSkamil 
296c503d12fSkamil     tcbuf = malloc(1024);
297c503d12fSkamil     intrp_init(tcbuf);
298c503d12fSkamil 
299c503d12fSkamil     if (chdir(warplib) < 0)
300c8c17207Schristos 	fprintf(stderr,NOCD,warplib);
301c503d12fSkamil 
302c503d12fSkamil     term_init();
303c503d12fSkamil 
304c503d12fSkamil     term_set(tcbuf);
305c503d12fSkamil     free(tcbuf);
306c503d12fSkamil 
307c503d12fSkamil     umask(022);     /* mustn't rely on incoming umask--could be 033 which */
308c503d12fSkamil 		    /* would disable people from running wscore */
309c503d12fSkamil 
310c503d12fSkamil     score_init();
311c503d12fSkamil 
312c503d12fSkamil     sig_init();
313c503d12fSkamil 
314c503d12fSkamil     if (totalscore) {
315c503d12fSkamil 	clear();
316c503d12fSkamil 	mvaddstr(12,25,"*** restoring saved game ***");
317c503d12fSkamil 	roundsleep(1);
318c503d12fSkamil     }
319c503d12fSkamil 
320*7839ca65Schristos     srandom(getpid());
321c503d12fSkamil 
322c503d12fSkamil     do {
323c8c17207Schristos 	for (keepgoing = true;;) {
324c503d12fSkamil 	    if (!experimenting) {
325c503d12fSkamil 		if ((savfil = fopen(savefilename,"w")) == NULL) {
326c503d12fSkamil 		    resetty();
3276256b041Schristos 		    printf("Can't open savefile `%s'\r\n", savefilename);
328c503d12fSkamil 		    finalize(1);
329c503d12fSkamil 		}
330c503d12fSkamil 		fprintf(savfil,
331c503d12fSkamil 		    "%-8s %10ld, %2d,%5d,%2d,%2d,%3d %c%c%c%c%c%c%c%c%c\n",
332c503d12fSkamil 		    logname, totalscore, smarts, cumsmarts,
333c503d12fSkamil 		    numents, numbases, wave,
334c503d12fSkamil 		    apolspec ? 'a' : ' ',
335c503d12fSkamil 		    beginner   ? 'b' : ' ',
336c503d12fSkamil 		    crushspec  ? 'c' : ' ',
337c503d12fSkamil 		    gornspec   ? 'g' : ' ',
338c503d12fSkamil 		    massacre   ? 'm' : ' ',
339c503d12fSkamil 		    romspec    ? 'r' : ' ',
340c503d12fSkamil 		    tholspec   ? 't' : ' ',
341c503d12fSkamil 		    lowspeed   ? 'l' : ' ',
342c503d12fSkamil 		    amoebaspec ? '&' : ' '
343c503d12fSkamil 		);
344c503d12fSkamil 		fprintf(savfil,"         running on %s, process #%d\n",
345c503d12fSkamil 		    term+5,getpid());
346c8c17207Schristos 		fclose(savfil);
347c503d12fSkamil 	    }
348c503d12fSkamil 
349c503d12fSkamil 	    lastscore = totalscore;
350c503d12fSkamil 	    initialize();
351c503d12fSkamil 	    play();
352c503d12fSkamil 	    cumsmarts += smarts;
353c503d12fSkamil 	    wavescore();
354c503d12fSkamil 	    if (numents<=0 && numbases<=0)
355c8c17207Schristos 		keepgoing = false;
356c503d12fSkamil 	  if (!keepgoing) break;
357c503d12fSkamil 	    do {
358c503d12fSkamil 		if (experimenting) {
359c503d12fSkamil 		    mvaddstr(23,15,
360c503d12fSkamil 		      "      [Hit space to continue, 'q' to quit]       ");
361c503d12fSkamil 		}
362c503d12fSkamil 		else {
363c503d12fSkamil 		    mvaddstr(23,15,
364c503d12fSkamil 		      "[Hit space to continue, 's' to save, 'q' to quit]");
365c503d12fSkamil 		}
366c503d12fSkamil 		sleep(1);
367c8c17207Schristos 		fflush(stdout);
368c503d12fSkamil 		eat_typeahead();
369c503d12fSkamil 		getcmd(&tmp);
370c503d12fSkamil 		if (tmp == BREAKCH || tmp == INTRCH) {
371c503d12fSkamil 		    mvaddstr(23,15,
372c503d12fSkamil 		      "                                                 ");
373c503d12fSkamil 		    mvaddstr(23,33,
374c503d12fSkamil 		      "Really quit? ");
375c503d12fSkamil 		    getcmd(&tmp);
376c503d12fSkamil 		    if (tmp == 'y' || tmp == 'Y')
377c503d12fSkamil 			tmp = 'q';
378c503d12fSkamil 		    else
379c503d12fSkamil 			tmp = 1;
380c503d12fSkamil 		}
381*7839ca65Schristos 	    } while (tmp != INTRCH && tmp != BREAKCH && !strchr(" qQs",tmp));
382c503d12fSkamil 	  if (tmp != ' ' && tmp != 's') break;
383c503d12fSkamil 	    if (!beginner && smarts < 20)
384c503d12fSkamil 		smarts += 4;
385c503d12fSkamil 	    else if (!beginner && smarts < 35)
386c503d12fSkamil 		smarts += 2;
387c503d12fSkamil 	    else if (smarts < 99)
388c503d12fSkamil 		smarts++;
389c503d12fSkamil 	  if (tmp == 's') save_game();
390c503d12fSkamil 	}
391c503d12fSkamil 	score();
392c503d12fSkamil 
393c503d12fSkamil     } while (justonemoretime);
394c503d12fSkamil 
395c503d12fSkamil     if (!experimenting)
396c503d12fSkamil 	unlink(savefilename);
397c503d12fSkamil 
398c503d12fSkamil     clear();
399c503d12fSkamil     resetty();
400c503d12fSkamil     exit(0);
401c503d12fSkamil }
402