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