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