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: main(argc,argv) 136: int argc; 137: char *argv[]; 138: { 139: char tmp, *s, *tcbuf; 140: 141: int i; 142: 143: FILE *savfil; 144: 145: #if RANDBITS > 16 146: for (i=100; i; i--) 147: if (rand() >= 65536) 148: goto rand_ok; 149: printf("Recompile with RANDBITS = 15 or 16.\n"); 150: exit(1); 151: #else 152: #if RANDBITS > 15 153: for (i=100; i; i--) { 154: if (rand() >= 32768) 155: goto rand_ok; 156: } 157: printf("Recompile with RANDBITS = 15.\n"); 158: exit(1); 159: #endif 160: #endif 161: rand_ok: 162: 163: #ifdef lint /* to suppress "defined but never used" */ 164: # ifdef SIGTSTP 165: (void)stop_catcher(); 166: # endif 167: # ifdef SIGCONT 168: (void)cont_catcher(); 169: # endif 170: #endif 171: 172: while (--argc > 0 && (*++argv)[0] == '-') 173: for (s = argv[0]+1; *s != '\0'; s++) 174: switch (*s) { 175: case '&': 176: amoebaspec = TRUE; 177: beginner = TRUE; 178: break; 179: case 'A': 180: apolspec = TRUE; 181: beginner = TRUE; 182: break; 183: case 'b': 184: beginner = TRUE; 185: break; 186: case 'C': 187: crushspec = TRUE; 188: beginner = TRUE; 189: break; 190: case 'D': 191: debugging = TRUE; 192: #ifdef DEBUGGING 193: debug = atoi(++s); 194: #endif 195: s += strlen(s)-1; 196: break; 197: case 'd': 198: s++; 199: if (*s == '=') s++; 200: ismarts = atoi(s); 201: if (ismarts <= 0) 202: ismarts = 1; 203: if (ismarts > 99) 204: ismarts = 99; 205: if (ismarts > 40) 206: beginner = TRUE; 207: s += strlen(s)-1; 208: break; 209: case 'E': 210: klingspec = TRUE; 211: beginner = TRUE; 212: s++; 213: if (*s == '=') s++; 214: inumenemies = atoi(s); 215: s += strlen(s)-1; 216: break; 217: case 'F': 218: friendspec = TRUE; 219: beginner = TRUE; 220: s++; 221: if (*s == '=') s++; 222: inumfriends = atoi(s); 223: s += strlen(s)-1; 224: break; 225: case 'G': 226: gornspec = TRUE; 227: beginner = TRUE; 228: break; 229: case 'l': 230: lowspeed = TRUE; 231: break; 232: case 'm': 233: metakey = TRUE; 234: break; 235: case 'M': 236: massacre = TRUE; 237: break; 238: case 'P': 239: piratespec = TRUE; 240: beginner = TRUE; 241: s++; 242: if (*s == '=') s++; 243: inumpirates = atoi(s); 244: s += strlen(s)-1; 245: break; 246: case 'S': 247: prespec = TRUE; 248: beginner = TRUE; 249: s++; 250: if (*s == '=') s++; 251: if (*s) 252: prescene = atoi(s); 253: else 254: prescene = -1; 255: s += strlen(s)-1; 256: break; 257: case 'R': 258: romspec = TRUE; 259: beginner = TRUE; 260: break; 261: case '*': 262: starspec = TRUE; 263: beginner = TRUE; 264: s++; 265: if (*s == '=') s++; 266: inumstars = atoi(s); 267: s += strlen(s)-1; 268: break; 269: case 's': 270: scorespec = TRUE; 271: break; 272: case 'T': 273: tholspec = TRUE; 274: beginner = TRUE; 275: break; 276: case 'x': 277: experimenting = TRUE; 278: break; 279: case 'v': 280: version(); 281: exit(0); 282: break; 283: default: 284: fprintf(stderr,"warp: illegal option %c\n", *s); 285: fprintf(stderr, "Usage: warp -dn -b -x -v -s\n"); 286: exit(1); 287: } 288: if (argc != 0) { 289: fprintf(stderr, "Usage: warp -dn -b -x -v -s\n"); 290: exit(1); 291: } 292: bang_init(); 293: move_init(); 294: object_init(); 295: play_init(); 296: them_init(); 297: us_init(); 298: util_init(); 299: weapon_init(); 300: 301: tcbuf = malloc(1024); 302: intrp_init(tcbuf); 303: 304: if (chdir(warplib) < 0) 305: fprintf(stderr,nocd,warplib); 306: 307: term_init(); 308: 309: term_set(tcbuf); 310: free(tcbuf); 311: 312: umask(022); /* mustn't rely on incoming umask--could be 033 which */ 313: /* would disable people from running wscore */ 314: 315: score_init(); 316: 317: sig_init(); 318: 319: if (totalscore) { 320: clear(); 321: mvaddstr(12,25,"*** restoring saved game ***"); 322: roundsleep(1); 323: } 324: 325: srand(getpid()); 326: 327: do { 328: for (keepgoing = TRUE;;) { 329: if (!experimenting) { 330: if ((savfil = fopen(savefilename,"w")) == NULL) { 331: resetty(); 332: printf("Can't open savefile\r\n"); 333: finalize(1); 334: } 335: fprintf(savfil, 336: "%-8s %10ld, %2d,%5d,%2d,%2d,%3d %c%c%c%c%c%c%c%c%c\n", 337: logname, totalscore, smarts, cumsmarts, 338: numents, numbases, wave, 339: apolspec ? 'a' : ' ', 340: beginner ? 'b' : ' ', 341: crushspec ? 'c' : ' ', 342: gornspec ? 'g' : ' ', 343: massacre ? 'm' : ' ', 344: romspec ? 'r' : ' ', 345: tholspec ? 't' : ' ', 346: lowspeed ? 'l' : ' ', 347: amoebaspec ? '&' : ' ' 348: ); 349: fprintf(savfil," running on %s, process #%d\n", 350: term+5,getpid()); 351: Fclose(savfil); 352: } 353: 354: lastscore = totalscore; 355: initialize(); 356: play(); 357: cumsmarts += smarts; 358: wavescore(); 359: if (numents<=0 && numbases<=0) 360: keepgoing = FALSE; 361: if (!keepgoing) break; 362: do { 363: if (experimenting) { 364: mvaddstr(23,15, 365: " [Hit space to continue, 'q' to quit] "); 366: } 367: else { 368: mvaddstr(23,15, 369: "[Hit space to continue, 's' to save, 'q' to quit]"); 370: } 371: sleep(1); 372: Fflush(stdout); 373: eat_typeahead(); 374: getcmd(&tmp); 375: if (tmp == BREAKCH || tmp == INTRCH) { 376: mvaddstr(23,15, 377: " "); 378: mvaddstr(23,33, 379: "Really quit? "); 380: getcmd(&tmp); 381: if (tmp == 'y' || tmp == 'Y') 382: tmp = 'q'; 383: else 384: tmp = 1; 385: } 386: } while (tmp != INTRCH && tmp != BREAKCH && !index(" qQs",tmp)); 387: if (tmp != ' ' && tmp != 's') break; 388: if (!beginner && smarts < 20) 389: smarts += 4; 390: else if (!beginner && smarts < 35) 391: smarts += 2; 392: else if (smarts < 99) 393: smarts++; 394: if (tmp == 's') save_game(); 395: } 396: score(); 397: 398: } while (justonemoretime); 399: 400: if (!experimenting) 401: unlink(savefilename); 402: 403: clear(); 404: resetty(); 405: exit(0); 406: }