Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!watmath!clyde!cbatt!ucbvax!okamoto From: okamoto@ucbvax.UUCP Newsgroups: net.sources.games Subject: Trek73 (Part 4 of 6) Message-ID: <16577@ucbvax.BERKELEY.EDU> Date: Wed, 10-Dec-86 12:30:27 EST Article-I.D.: ucbvax.16577 Posted: Wed Dec 10 12:30:27 1986 Date-Received: Sun, 14-Dec-86 05:28:19 EST Organization: University of California at Berkeley Lines: 1971 #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # moveships.c # parseopts.c # parsit.c # save.c # ships.c # special.c # strat1.c # subs.c # vers.c # This archive created: Wed Dec 10 09:01:32 1986 # By: Jeff Okamoto () export PATH; PATH=/bin:$PATH if test -f 'moveships.c' then echo shar: will not over-write existing file "'moveships.c'" else cat << \SHAR_EOF > 'moveships.c' /* * TREK73: moveships.c * * Actual command execution * * move_ships, check_targets, misc_timers, disposition * */ #include "externs.h" move_ships() { register int i; register float j; register float k; register struct list *lp; register struct ship *sp; register float fuel_use; struct torpedo *tp; struct ship *fed; struct list *lp1; struct ship *sp1; float iterations; float tmpf; float energy; float course, newcourse; float warp, newwarp; int x, y; struct ship *target; double d0; float Mpersegment; double floor(), fabs(); /* * The value 100 is the number of Megameters per second * per warp-factor */ Mpersegment = segment * 100.0; iterations = (int)floor(timeperturn/segment + 0.5); /* What a crock! */ for (i=0; i<=shipnum; i++) distribute(shiplist[i]); fed = shiplist[0]; for (i=0; ifwd) { if (lp == tail) break; if (lp->type == I_UNDEFINED) continue; sp = NULL; tp = NULL; if (lp->type == I_SHIP) sp = lp->data.sp; else tp = lp->data.tp; if (sp && is_dead(sp, S_DEAD)) continue; if ((sp) && (i % sp->p_firing_delay == 0)) (void) phaser_firing(sp); if ((sp) && (i % sp->t_firing_delay == 0)) (void) torpedo_firing(sp); /* * time fuses */ if (tp) { tp->timedelay -= segment; if (tp->timedelay <= 0.) { torp_detonate(tp, lp); continue; } } else { sp->delay -= segment; if (sp->delay <= 0.) { ship_detonate(sp, lp); continue; } } /* * proximity fuse */ if (tp && tp->prox != 0) { for (lp1 = &head; lp1 != tail; lp1 = lp1->fwd) { if (lp1->type == I_SHIP) { sp1 = lp1->data.sp; if (sp1 == tp->from) continue; if (cantsee(sp1)) continue; j = rangefind(tp->x, sp1->x, tp->y, sp1->y); } else if (lp1->type == I_ENG) { sp1 = lp1->data.sp; if (sp1 == tp->from) continue; if (cantsee(sp1)) continue; j = rangefind(tp->x, sp1->x, tp->y, sp1->y); } else continue; if (j >= tp->prox) continue; torp_detonate(tp, lp); break; } if (lp1 != tail) continue; } /* * movement simulation */ if (sp && is_dead(sp, S_DEAD)) continue; if (sp) { x = sp->x; y = sp->y; warp = sp->warp; if (fabs(sp->newwarp) > sp->max_speed) sp->newwarp = (sp->newwarp > 0) ? sp->max_speed : -sp->max_speed; newwarp = sp->newwarp; course = sp->course; newcourse = sp->newcourse; target = sp->target; energy = sp->energy; /* * fuel consumption */ if (fabs(warp) > 1.0) fuel_use = (fabs(warp) * sp->eff * segment); else fuel_use = 0.; #ifdef TRACE /* if (trace) printf("*** Fuel use = %.2f, energy = %.2f\n", fuel_use, energy); */ #endif if (fuel_use > energy) { if (!shutup[BURNOUT + sp->id] && !(is_dead(sp, S_WARP)) && cansee(sp)) { printf("%s's warp drive burning out.\n", sp->name); shutup[BURNOUT + sp->id]++; } newwarp = (warp < 0.0) ? -0.99 : 0.99; energy = 0; } else energy -= fuel_use; } else { x = tp->x; y = tp->y; warp = tp->speed; newwarp = tp->newspeed; course = tp->course; newcourse = course; target = tp->target; } /* * destroyed warp drive */ if (sp && (is_dead(sp, S_WARP))) if (fabs(warp) > 1.0) newwarp = (warp < 0.0) ? -0.99 : 0.99; /* * automatic pilot */ if (target != NULL) if (sp && (is_dead(target, S_DEAD))) { if ((sp == fed) && !shutup[DISENGAGE] && !is_dead(sp, S_DEAD)) { printf("%s's autopilot disengaging.\n", sp->name); shutup[DISENGAGE]++; } newcourse = course; target = NULL; sp->relbear = 0.0; } else { if (cantsee(target)) j =bearing(x,target->position.x, y, target->position.y); else j = bearing(x, target->x, y, target->y); if (sp) j = rectify(j - sp->relbear); newcourse = j; } /* * turn rate (known to be a ship) */ if (tp) course = newcourse; if (sp && course != newcourse) { j = rectify(newcourse - course); if (j > 180) j -= 360; /* * maximum degrees turned in one turn */ k = ((sp->max_speed + 2.0 - warp) * sp->deg_turn * segment); /* If you have no warp drive, you're less * maneuverable */ if (is_dead(sp, S_WARP)) k /= 2; k = course + (j < 0.0 ? -1.0 : 1.0) * min(fabs(j), k); course = rectify(k); } /* * acceleration */ tmpf = newwarp - warp; d0 = fabs(tmpf); warp += ((tmpf < 0.0) ? -1 : 1) * sqrt(d0) * segment; d0 = toradians(course); x += (int) (warp * cos(d0) * Mpersegment); y += (int) (warp * sin(d0) * Mpersegment); /* * projected position (cloaked) */ if (sp && cantsee(sp)) { d0 = toradians(sp->position.course); sp->position.x += (sp->position.warp * cos(d0) * segment); sp->position.y += (sp->position.warp * sin(d0) * segment); } /* * reset all the vars */ if (sp) { sp->x = x; sp->y = y; sp->warp = warp; sp->newwarp = newwarp; /* XXXXX should these be rectified? */ sp->course = rectify(course); sp->newcourse = rectify(newcourse); sp->energy = energy; sp->target = target; } else { tp->x = x; tp->y = y; tp->speed = warp; tp->course = rectify(course); tp->target = target; } } } } check_targets() { register int i; register int j; struct ship *sp; struct ship *fed; struct ship *target; fed = shiplist[0]; for (i=0; i <= shipnum; i++) { /* Check targets */ sp = shiplist[i]; if (is_dead(sp, S_DEAD)) continue; target = sp->target; if (target && is_dead(target, S_DEAD)) { if ((sp == fed) && !shutup[DISENGAGE]) { puts(" helm lock disengaging"); shutup[DISENGAGE]++; } sp->target = NULL; sp->relbear = 0.0; } for (j=0; jnum_phasers; j++) { target = sp->phasers[j].target; if (target && is_dead(target, S_DEAD)) { if ((sp == fed) && (!shutup[PHASERS+j]) && !(is_dead(sp, S_DEAD))) { printf(" phaser %d disengaging\n",j+1); shutup[PHASERS+j]++; } sp->phasers[j].target = NULL; } else if (target) sp->phasers[j].bearing = rectify(bearing(sp->x, (cantsee(target)) ? target->position.x : target->x, sp->y, (cantsee(target)) ? target->position.y : target->y) - sp->course); } for (j=0; jnum_tubes; j++) { target = sp->tubes[j].target; if (target && is_dead(target, S_DEAD)) { if ((sp == fed) && (!shutup[TUBES+j]) && !(is_dead(sp, S_DEAD))) { printf(" tube %d disengaging\n", j+1); shutup[TUBES+j]++; } sp->tubes[j].target = NULL; } else if (target) sp->tubes[j].bearing = rectify(bearing(sp->x, (cantsee(target)) ? target->position.x : target->x, sp->y, (cantsee(target)) ? target->position.y : target->y) - sp->course); } } if (sp->cloak_delay > 0) sp->cloak_delay--; } misc_timers() { struct ship *fed; /* * self-destruct warning */ fed = shiplist[0]; if ((fed->delay < 1000.) && (fed->delay > 0.)) { if (is_dead(fed, S_COMP)) { printf("%s: Self-destruct has been aborted due to computer damage\n", science); fed->delay = 10000.; } else printf("Computer: %5.2f seconds to self destruct.\n", fed->delay); } fed->probe_status = PR_NORMAL; /* * Ruses, bluffs, surrenders */ if (defenseless) defenseless++; if (corbomite) corbomite++; if (surrender) surrender++; if (surrenderp) surrenderp++; } disposition() { struct ship *sp; struct ship *fed; struct ship *ep; int kills; int others; int fedstatus; register int i; register int j; register int k; /* * Federation dispostion */ fed = shiplist[0]; sp = fed; kills = others = fedstatus = 0; if (sp->complement <= 0 && !is_dead(sp, S_DEAD)) { sp->status[S_DEAD] = 100; sp->newwarp = 0.0; sp->newcourse = sp->course; sp->target = NULL; sp->relbear = 0.0; for (i = 0; i < sp->num_phasers; i++) { sp->phasers[i].target = NULL; sp->phasers[i].drain = MIN_PHASER_DRAIN; sp->phasers[i].status &= ~P_FIRING; } for (i = 0; i < sp->num_tubes; i++) { sp->tubes[i].target = NULL; sp->tubes[i].status &= ~T_FIRING; } for (i = 0; i < SHIELDS; i++) sp->shields[i].attemp_drain = 0.0; sp->regen = 0.0; sp->cloaking = C_NONE; } if (is_dead(sp, S_DEAD)) fedstatus = 1; else { for (i=0; inum_phasers; i++) if (!(sp->phasers[i].status & P_DAMAGED)) break; if (i == sp->num_phasers) { for (i=0; inum_tubes; i++) if (!(sp->tubes[i].status & T_DAMAGED)) break; if (i == sp->num_tubes) fedstatus = 1; } } /* * enemy disposition */ for (k=1; k <= shipnum; k++) { ep = shiplist[k]; if (ep->complement <= 0 && !is_dead(ep, S_DEAD)) { ep->status[S_DEAD] = 100; ep->newwarp = 0.0; ep->newcourse = ep->course; ep->target = NULL; ep->relbear = 0.0; for (i = 0; i < ep->num_phasers; i++) { ep->phasers[i].target = NULL; ep->phasers[i].drain = MIN_PHASER_DRAIN; ep->phasers[i].status &= ~P_FIRING; } for (i = 0; i < ep->num_tubes; i++) { ep->tubes[i].target = NULL; ep->tubes[i].status &= ~T_FIRING; } for (i = 0; i < SHIELDS; i++) ep->shields[i].attemp_drain = 0.0; ep->regen = 0.0; ep->cloaking = C_NONE; } if (is_dead(ep, S_DEAD)) { kills++; continue; } if (fedstatus) continue; j = rangefind(sp->x, ep->x, sp->y, ep->y); if ((j>3500 && is_dead(ep, S_WARP)) || (j>4500 && ep->delay<10.)) { others++; continue; } /* Check if we are within range to turn off the flag */ if ((j <= 3500) && (reengaged)) reengaged = 0; if (ep->energy > 10) continue; for (i=0; inum_phasers; i++) if (!(ep->phasers[i].status & P_DAMAGED)) break; if (i != ep->num_phasers) continue; for (i=0; inum_tubes; i++) if (!(ep->tubes[i].status & T_DAMAGED)) break; if (i != ep->num_tubes) continue; kills++; } if (!fedstatus && (global & E_SURRENDER)) /* enemy surrender */ if (leftovers()) (void) warn(FIN_E_SURRENDER); else (void) final(FIN_E_SURRENDER); if ((is_dead(fed, S_SURRENDER)) && (kills + others < shipnum)) if (leftovers()) /* federation surrender */ (void) warn(FIN_F_SURRENDER); else (void) final(FIN_F_SURRENDER); if (!fedstatus && (kills + others) < shipnum) /* play continues */ return 0; if (fedstatus && kills < shipnum) /* Fed. defeated */ if (leftovers()) (void) warn(FIN_F_LOSE); else (void) final(FIN_F_LOSE); if (!fedstatus && kills == shipnum) /* Fed. victory */ if (leftovers()) (void) warn(FIN_E_LOSE); else (void) final(FIN_E_LOSE); if (!fedstatus && (kills + others) == shipnum) /* outmaneuvered */ if (leftovers()) (void) warn(FIN_TACTICAL); else (void) final(FIN_TACTICAL); if (fedstatus && kills == shipnum) (void) final(FIN_COMPLETE); /* both sides dead */ return 0; } SHAR_EOF chmod +x 'moveships.c' fi # end of overwriting check if test -f 'parseopts.c' then echo shar: will not over-write existing file "'parseopts.c'" else cat << \SHAR_EOF > 'parseopts.c' /* * TREK73: parseopts.c * * Parse the environment variable TREK73OPTS and command line options * * parse_opts, get_comlineopts */ #include #include #include "externs.h" #include "options.h" #define EQSTR(a, b, c) (strncmp(a, b, c) == 0) #define NUM_OPTS (sizeof optlist / sizeof (OPTION)) /* * description of an option and what to do with it */ struct optstruct { char *o_name; /* option name */ int *o_opt; /* pointer to thing to set */ int o_type /* Boolean or string */ }; typedef struct optstruct OPTION; OPTION optlist[] = { {"terse", (int *)&terse, BOOLEAN}, {"name", (int *)captain, STRING}, {"sex", (int *)sex, STRING}, {"science", (int *)science, STRING}, {"engineer", (int *)engineer, STRING}, {"com", (int *)com, STRING}, {"nav", (int *)nav, STRING}, {"helmsman", (int *)helmsman, STRING}, {"shipname", (int *)shipname, STRING}, {"enemy", (int *)racename, STRING}, {"foename", (int *)foename, STRING}, {"silly", (int *)&silly, BOOLEAN}, {"class", (int *)class, STRING}, {"foeclass", (int *)foeclass, STRING}, {"time", (int *)com_delay, STRING}, {"teletype", (int *)&teletype, BOOLEAN}, {"trace", (int *)&trace, BOOLEAN}, {"savefile", (int *)savefile, STRING} }; /* * parse_opts: * Parse options from string, usually taken from the environment. * The string is a series of comma separated values, with booleans * being stated as "name" (true) or "noname" (false), and strings * being "name=....", with the string being defined up to a comma * or the end of the entire option string. */ parse_opts(str) register char *str; { register char *sp; register OPTION *op; register int len; while (*str) { /* * Get option name */ for (sp = str; isascii(*sp) && isalpha(*sp); sp++) continue; len = sp - str; /* * Look it up and deal with it */ for (op = optlist; op < &optlist[NUM_OPTS]; op++) if (EQSTR(str, op->o_name, len)) { if (op->o_type == BOOLEAN) /* if option is a boolean */ *op->o_opt = 1; else /* string option */ { register char *start; /* * Skip to start of string value */ for (str = sp + 1; *str == '='; str++) continue; start = (char *) op->o_opt; /* * Skip to end of string value */ for (sp = str + 1; *sp && *sp != ','; sp++) continue; strucpy(start, str, sp - str); } break; } /* * check for "noname" for booleans */ else if (op->o_type == BOOLEAN && EQSTR(str, "no", 2) && EQSTR(str + 2, op->o_name, len - 2)) { *op->o_opt = 0; break; } /* * skip to start of next option name */ while (*sp && !(isascii(*sp) && isalpha(*sp))) sp++; str = sp; } } /* * strucpy: * Copy string using unctrl for things */ strucpy(s1, s2, len) register char *s1, *s2; register int len; { if (len > 100) len = 100; while (len--) { if (isascii(*s2) && isprint(*s2)) *s1++ = *s2; s2++; } *s1 = '\0'; } get_comlineopts(argc, argv) int argc; char *argv[]; { int c; char *opts = "Rtc:s:S:E:C:N:H:f:r:d:yTn:F:l:v"; int errflg = 0; while ((c = getopt(argc, argv, opts)) != EOF) { switch(c) { case 'R': restart = 1; break; case 't': terse = 1; break; case 'c': (void) strncpy(captain, optarg, sizeof captain); captain[sizeof captain - 1] = '\0'; break; case 's': (void) strncpy(sex, optarg, sizeof sex); sex[sizeof sex - 1] = '\0'; break; case 'S': (void) strncpy(science, optarg, sizeof science); science[sizeof science - 1] = '\0'; break; case 'E': (void) strncpy(engineer, optarg, sizeof engineer); engineer[sizeof engineer - 1] = '\0'; break; case 'C': (void) strncpy(com, optarg, sizeof com); com[sizeof com - 1] = '\0'; break; case 'N': (void) strncpy(nav, optarg, sizeof nav); nav[sizeof nav - 1] = '\0'; break; case 'H': (void) strncpy(helmsman, optarg, sizeof helmsman); helmsman[sizeof helmsman - 1] = '\0'; break; case 'f': (void) strncpy(foename, optarg, sizeof foename); foename[sizeof foename - 1] = '\0'; break; case 'r': (void) strncpy(racename, optarg, sizeof racename); racename[sizeof racename - 1] = '\0'; break; case 'd': (void) strncpy(com_delay, optarg, sizeof com_delay); com_delay[sizeof com_delay - 1] = '\0'; break; case 'y': silly = 1; break; case 'T': teletype = 1; break; case 'n': (void) strncpy(shipname, optarg, sizeof shipname); shipname[sizeof shipname - 1] = '\0'; break; case 'F': (void) strncpy(foeclass, optarg, sizeof foeclass); foeclass[sizeof foeclass - 1] = '\0'; break; case 'l': (void) strncpy(class, optarg, sizeof class); class[sizeof class - 1] = '\0'; break; case 'v': trace = TR_ON; break; case '?': default: errflg++; break; } } if (errflg) { fprintf(stderr, "Usage: trek73 [-t] [-c captain's name] [-s sex] [-S science officer]\n [-E engineer] [-C communications officer] [-N navigator] [-H helmsman]\n"); fprintf(stderr, " [-f enemy captain] [-r enemy race] [-d command delay time] [-y] [-T] \n [-n shipname] [-F enemy ship type] [-l federation ship type] [-v]\n"); fprintf(stderr, " or trek73 -R"); exit(1); } } SHAR_EOF chmod +x 'parseopts.c' fi # end of overwriting check if test -f 'parsit.c' then echo shar: will not over-write existing file "'parsit.c'" else cat << \SHAR_EOF > 'parsit.c' /* * TREK73: parsit.c * * Parse and get input * * Gets, parsit (courtesy, P. Lapsley) * */ #include extern void free(); extern char *gets(), *malloc(), *strcpy(), *index(); static int gindex; static char **argv; char * Gets(buf, len) char *buf; int len; { register char *tmp; if (argv[gindex] == NULL) { (void) fgets(buf, len, stdin); if (tmp = index(buf, '\n')) *tmp = '\0'; return(buf); } ++gindex; if (argv[gindex] == NULL) { (void) fgets(buf, len, stdin); if (tmp = index(buf, '\n')) *tmp = '\0'; return (buf); } (void) strcpy (buf, argv[gindex]); puts (buf); return (buf); } /* ** parsit.c 23 September 1984 P. Lapsley (phil@Berkeley.ARPA) ** ** Parse a string of words separated by spaces into an ** array of pointers to characters, just like good ol' argv[] ** and argc. ** ** Usage: ** ** char line[132]; ** char **argv; ** int argc; ** ** argv = (char **) NULL; ** argc = parsit(line, &argv); ** ** returns the number of words parsed in argc. argv[argc] will ** be (char *) NULL to indicate end of list, if you're not ** happy with just knowing how many words you have. ** ** Note that setting argv = (char **) NULL is only done the first ** time the routine is called with a new "argv" -- it tells ** parsit that "argv" is a new array, and parsit shouldn't free ** up the elements (as it would do if it were an old array). */ parsit(line, array) char *line; char ***array; { char *malloc(); char word[132]; char *linecp; int i, j, num_words; gindex = 0; argv = *array; if (argv != (char **) NULL) { /* Check to see if we should */ i = 0; /* free up the old array */ do { free(argv[i]); /* If so, free each member */ } while (argv[i++] != (char *) NULL); free((char *)argv); /* and then free the ptr itself */ } linecp = line; num_words = 0; while (1) { /* count words in input */ for (; *linecp == ' ' || *linecp == '\t'; ++linecp) ; if (*linecp == '\0') break; for (; *linecp != ' ' && *linecp != '\t' && *linecp != '\0'; ++linecp) ; ++num_words; if (*linecp == '\0') break; } /* Then malloc enough for that many words plus 1 (for null) */ if ((argv = (char **) malloc((unsigned)((num_words + 1) * sizeof(char *)))) == (char **) NULL) { fprintf(stderr, "parsit: malloc out of space!\n"); return(0); } j = i = 0; while (1) { /* Now build the list of words */ for (; *line == ' ' || *line == '\t'; ++line) ; if (*line == '\0') break; i = 0; for (; *line != ' ' && *line != '\t' && *line != '\0'; ++line) word[i++] = *line; word[i] = '\0'; argv[j] = malloc(strlen(word) + 1); if (argv[j] == (char *) NULL) { fprintf(stderr, "parsit: malloc out of space!\n"); return(0); } (void) strcpy(argv[j], word); ++j; if (*line == '\0') break; } argv[j] = (char *) NULL; /* remember null at end of list */ *array = argv; return(j); } SHAR_EOF chmod +x 'parsit.c' fi # end of overwriting check if test -f 'save.c' then echo shar: will not over-write existing file "'save.c'" else cat << \SHAR_EOF > 'save.c' /* * TREK73: save.c * * save and restore routines * * @(#)save.c 4.15 (Berkeley) 5/10/82 */ #include #include #include #include #include #include #define MAXSTR 256 typedef struct stat STAT; extern char *sys_errlist[], version[], encstr[]; extern int errno; char *sbrk(); STAT sbuf; set_save() { register char *env; register struct passwd *pw; char *getpass(); extern char home[]; extern char savefile[]; char *getenv(); if ((env = getenv("HOME")) != NULL) strcpy(home, env); else if ((pw = getpwuid(getuid())) != NULL) strcpy(home, pw->pw_dir); else home[0] = '\0'; strcat(home, "/"); strcpy(savefile, home); strcat(savefile, "trek73.save"); } /* * save_game: * Implement the "save game" command */ save_game() { register FILE *savef; register int c; char buf[MAXSTR]; extern char savefile[]; /* * get file name */ over: if (savefile[0] != '\0') { for (;;) { printf("Save file (%s)? ", savefile); c = getchar(); if (c == 'n' || c == 'N' || c == 'y' || c == 'Y') break; else printf("\nPlease answer Yes or No"); } if (c == 'y' || c == 'Y') { strcpy(buf, savefile); goto gotfile; } } do { stdin->_cnt = 0; printf("File name: "); buf[0] = '\0'; gets(buf); gotfile: /* * test to see if the file exists */ if (stat(buf, &sbuf) >= 0) { for (;;) { stdin->_cnt = 0; printf("\nFile exists. Do you wish to overwrite it?"); if (c == 'y' || c == 'Y') break; else if (c == 'n' || c == 'N') goto over; else printf("\nPlease answer Y or N"); } } strcpy(savefile, buf); if ((savef = fopen(savefile, "w")) == NULL) perror("Trek73: Save problems"); } while (savef == NULL); /* * write out encrpyted file (after a stat) * The fwrite is to force allocation of the buffer before the write */ save_file(savef); exit(0); } /* * save_file: * Write the saved game on the file */ save_file(savef) register FILE *savef; { /* * close any open score file */ fstat(fileno(savef), &sbuf); /* * DO NOT DELETE. This forces stdio to allocate the output buffer * so that malloc doesn't get confused on restart */ fwrite("junk", 1, 5, savef); fseek(savef, 0L, 0); encwrite(version, sbrk(0) - version, savef); fclose(savef); exit(0); } /* * restore: * Restore a saved game from a file with elaborate checks for file * integrity from cheaters */ restore(file, envp) register char *file; char **envp; { register int inf, (*func)(); register char syml; extern char **environ; char buf[MAXSTR]; STAT sbuf2; func = signal(SIGTSTP, SIG_IGN); if ((inf = open(file, 0)) < 0) { perror(file); return 0; } fstat(inf, &sbuf2); syml = symlink(file); if ( unlink(file) < 0) { printf("Cannot unlink file\n"); return 0; } fflush(stdout); encread(buf, (unsigned int) (strlen(version) + 1), inf); if (strcmp(buf, version) != 0) { printf("Sorry, saved game is out of date.\n"); return 0; } fflush(stdout); brk(version + sbuf2.st_size); lseek(inf, 0L, 0); encread(version, (unsigned int) sbuf2.st_size, inf); /* * we do not close the file so that we will have a hold of the * inode for as long as possible */ if (sbuf2.st_ino != sbuf.st_ino || sbuf2.st_dev != sbuf.st_dev) { printf("Sorry, saved game is not in the same file.\n"); return 0; } #ifdef NOTDEF /* * defeat multiple restarting from the same place */ if (sbuf2.st_nlink != 1 || syml) { printf("Cannot restore from a linked file %d %d\n", sbuf2.st_nlink, syml); return 0; } #endif signal(SIGTSTP, SIG_DFL); environ = envp; stdin->_cnt = 0; playit(); /*NOTREACHED*/ } /* * encwrite: * Perform an encrypted write */ encwrite(start, size, outf) register char *start; unsigned int size; register FILE *outf; { register char *ep; ep = encstr; while (size--) { putc(*start++ ^ *ep++, outf); if (*ep == '\0') ep = encstr; } } /* * encread: * Perform an encrypted read */ encread(start, size, inf) register char *start; unsigned int size; register int inf; { register char *ep; register int read_size; if ((read_size = read(inf, start, size)) == -1 || read_size == 0) return read_size; ep = encstr; while (size--) { *start++ ^= *ep++; if (*ep == '\0') ep = encstr; } return read_size; } SHAR_EOF chmod +x 'save.c' fi # end of overwriting check if test -f 'ships.c' then echo shar: will not over-write existing file "'ships.c'" else cat << \SHAR_EOF > 'ships.c' /* * TREK73: ships.c * * Global Ship Defs for TREK73 * */ #include "externs.h" /* * starting stats for the ships depending on the type */ struct ship_stat stats[] = { { "DN", 0, 6, 8, 8, 10, 2., 1.5, 15., 200, 300, 600, 450, 5., 4., 2, 4, 135, 225, 125, 235, 4, 4}, { "CA", 1, 4, 6, 9, 11, 1., 0.75, 10., 150, 200, 450, 350, 3., 2., 5, 2, 135, 225, 125, 235, 4, 4}, { "CL", 2, 4, 4, 9, 11, 0.75, 0.5, 10., 125, 175, 350, 250, 3., 2., 6, 2, 150, 210, 140, 220, 4, 4}, { "DD", 3, 2, 4, 10, 12, 0.5, 0.5, 8., 100, 150, 200, 150, 2., 1.5, 7, 1, 160, 200, 150, 210, 4, 4} }; SHAR_EOF chmod +x 'ships.c' fi # end of overwriting check if test -f 'special.c' then echo shar: will not over-write existing file "'special.c'" else cat << \SHAR_EOF > 'special.c' /* * TREK73: special.c * * special: Take care of special commands like defenseless ruses, * corbomite bluffs, surrenders (both sides) * */ #include "externs.h" special(sp, range, fed) struct ship *sp; int range; struct ship *fed; { int loop, loop2, loop3; /* * Play dead effects */ switch (defenseless) { case 1: /* Monty Pythons? */ if (aliens[enemynum].defenseless == -1) aliens[enemynum].defenseless = randm(100); if (randm(100) > aliens[enemynum].defenseless) { /* Didn't work. Too bad. */ if (cansee(sp)) { printf("%s: No apparent change in the enemy's actions.\n", helmsman); } defenseless = 6; break; } defenseless = 2; case 2: case 3: /* Okay, he's fallen for it. Choose his action */ if (randm(2) == 1) { sp->target = NULL; sp->newwarp = 0.0; } else { sp->newwarp = 1.0; } if (cansee(sp)) { printf("%s: The %s is ", helmsman, sp->name); if (sp->target != NULL) { puts("cautiously advancing."); } else { puts("turning away."); } } case 4: case 5: /* * Now he might get suspicious. If he's moving too * fast or if we're close enough, or if his shields * are up, we'll spot him. */ if ((fabs(sp->target->warp) > 1.0) || (range < 200)) defenseless = 6; else for (loop = 0; loop < SHIELDS; loop++) if (sp->target->shields[loop].drain) defenseless = 6; } /* * Corbomite bluff effects. */ switch (corbomite) { case 1: /* Monty Pythons? */ if (aliens[enemynum].corbomite == -1) aliens[enemynum].corbomite = randm(100); if (randm(100) > aliens[enemynum].corbomite) { /* He didn't fall for it */ printf("%s: Message coming in from the %ss.\n", com, foerace); printf("%s: Put it on audio.\n", captain); if (randm(2) == 1) printf ("%s: Ha, ha, ha, %s. You lose.\n", foename, captain); else printf("%s: I fell for that the last time we met, idiot!\n", foename); corbomite = 6; break; } if (cansee(sp)) { printf("%s: %ss giving ground, Captain. Obviously they\n", science, foerace); puts(" tapped in as you expected them to."); printf("%s: A logical assumption, Mr. %s. Are they still\n", captain, science); puts(" retreating?"); printf("%s: Yes, %s\n", science, title); printf("%s: Good. All hands, stand by.\n", captain); } corbomite = 2; case 2: /* He fell for it, retrograde out of here! */ sp->target = NULL; sp->newwarp = -(3.0 + randm(7)); break; case 3: case 4: case 5: /* Begin to get suspicious */ if (fabs(sp->target->warp) > 2.0) corbomite = 6; break; } /* * Will the enemy accept your surrender? */ switch (surrender) { case 1: /* Monty Python */ if (aliens[enemynum].surrender == -1) aliens[enemynum].surrender = randm(100); /* Just a little reminder */ if (aliens[enemynum].surrender <= 10) printf("%s: The %ss do not take prisoners.\n", nav, foerace); if (randm(100) > aliens[enemynum].surrender) { /* Tough luck */ if (randm(2) == 1) { printf("%s: Message coming in from the %ss.\n", com, foerace); printf("%s: Put it on audio.\n", captain); printf("%s: Prepare to die, Chicken %s!\n", foename, captain); } else printf("%s: No reply from the %ss", com, foerace); surrender = 6; break; } /* He took it! */ printf("%s: Message coming in from the %ss.\n", com, foerace); printf("%s: Put it on audio.\n", captain); printf("%s: On behalf of the %s %s, I accept your surrender.\n", foename, foerace, empire); puts(" You have five seconds to drop your shields, cut"); puts(" warp, and prepare to be boarded."); global |= F_SURRENDER; case 2: case 3: if (surrender == 1) surrender = 2; else (void) warn(FIN_F_SURRENDER); sp->target = fed; sp->newwarp = sp->max_speed; (void) e_cloak_off(sp, fed); break; case 4: case 5: /* Begin checking surrender conditions */ for (loop = 0; loop < SHIELDS; loop++) if (sp->target->shields[loop].drain) break; if (loop < SHIELDS) break; if (range <= 1400) sp->newwarp = 1.0; if ((range <= 1000) && (fabs(sp->target->warp) <= 1.0)) { fed->status[S_SURRENDER] = 100; final(FIN_F_SURRENDER); } if (surrender == 4) break; if (!shutup[SURRENDER]) printf("%s: Captain %s, you have not fulfilled our terms.\n", foename, captain); printf(" We are resuming our attack.\n"); surrender = 6; shutup[SURRENDER]++; default: global &= ~F_SURRENDER; break; } /* * Enemy surrenders? */ switch (surrenderp) { case 1: for (loop = 1; loop <= shipnum; loop++) if (!is_dead(shiplist[loop], S_ENG) && (sp->complement > 100)) { printf("%s: Message coming in from the %ss.\n", com, foerace); printf("%s: Put it on audio.\n", captain); printf("%s: You must be joking, Captain %s.\n", foename, captain); puts(" Why don't you surrender?"); surrenderp = 6; break; } if (loop <= shipnum) break; /* Monty Python */ if (aliens[enemynum].surrenderp == -1) aliens[enemynum].surrenderp = randm(100); if (randm(100) > aliens[enemynum].surrenderp) { printf("%s: I'll never surrender to you, %s\n", foename, captain); surrenderp = 6; break; } printf("%s: As much as I hate to, Captain %s, we will surrender.\n", foename, captain); puts(" We are dropping shields. You may board us."); case 2: case 3: if (surrenderp == 1) surrenderp = 2; else (void) warn(FIN_E_SURRENDER); for (loop = 0; loop < SHIELDS; loop++) sp->shields[loop].attemp_drain = 0.0; sp->newwarp = 0.0; for (loop = 1; loop <= shipnum; loop++) shiplist[loop]->status[S_SURRENDER] = 100; global |= E_SURRENDER; break; } /* * Unsportsmanlike firing */ if (betw(defenseless, 0, 6) || betw(corbomite, 0, 6) || betw(surrender, 0, 6) || betw(surrenderp, 0, 6)) { for (loop = 0; loop < fed->num_phasers; loop++) if (fed->phasers[loop].status & P_FIRING) break; for (loop2 = 0; loop2 < fed->num_tubes; loop2++) if (fed->tubes[loop].status & T_FIRING) break; loop3 = (fed->probe_status != PR_NORMAL); /* Has he fired? */ if ((loop != fed->num_phasers) || (loop2 != fed->num_tubes) || (loop3 == 1)) { /* Yes, be angry and disbelieve everything from now on */ printf("%s: How dare you fire on us! We are resuming our attack!\n", foename); global = NORMAL; if (betw(defenseless,0,6)) defenseless = 6; if (betw(corbomite,0,6)) corbomite = 6; if (betw(surrender,0,6)) surrender = 6; if (betw(surrenderp,0,6)) surrenderp = 6; for (loop = 0; loop <= shipnum; loop++) shiplist[loop]->status[S_SURRENDER] = 0; } } } SHAR_EOF chmod +x 'special.c' fi # end of overwriting check if test -f 'strat1.c' then echo shar: will not over-write existing file "'strat1.c'" else cat << \SHAR_EOF > 'strat1.c' /* * TREK73: strat1.c * * Standard Enemy Strategy * * standard_strategy * */ #include "externs.h" standard_strategy(sp) struct ship *sp; { register struct ship *fed; float bear; int range; float tmpf; fed = shiplist[0]; if (is_dead(sp, S_DEAD)) return; range = rangefind(sp->x, fed->x, sp->y, fed->y); bear = bearing(sp->x, fed->x, sp->y, fed->y); bear = rectify(bear - sp->course); /* * Handle special requests */ special(sp, range, fed); /* * Now check for surrendering flags */ if ((global & F_SURRENDER) || (global & E_SURRENDER)) return; /* * Always turn on cloaking device if we have it and if we * can afford it */ if ((sp->cloaking == C_OFF) && (sp->energy >= 20) && e_cloak_on(sp, fed)) return; /* * Check for hostile antimatter devices */ if ((sp->cloaking == C_OFF) && e_closetorps(sp, fed)) return; if ((sp->cloaking == C_OFF) && e_checkprobe(sp)) return; /* * If cloaking is on, and we're running low on energy, * drop the cloak */ /* XXXX May want to change number */ if ((sp->cloaking == C_ON) && (sp->energy < 30) && e_cloak_off(sp, fed)) return; /* * Short range? */ if (range < 1050) { if (e_checkarms(sp) < randm((int)(sp->num_phasers+ sp->num_tubes)/3)) { if (!e_cloak_on(sp, fed)) (void) e_runaway(sp, fed); return; } if (e_lockphasers(sp, fed)) return; if (e_phasers(sp, fed)) return; if (betw(bear, 90.0, 270.0)) { (void) e_pursue(sp, fed, 1.0); return; } if (e_launchprobe(sp, fed)) return; if (sp->pods< 20 && sp->regen < 4.0 && e_destruct(sp, fed)) return; /* * set course? */ tmpf = fabs(fed->warp); if (sp->target != fed || fabs(sp->warp) + tmpf > 2.0) { (void) e_pursue(sp, fed, tmpf); return; } if (e_cloak_on(sp, fed)) return; } if (range < 3800) { /* * Either medium range, or we can't figure out what * to do at short range */ if (e_locktubes(sp, fed)) return; if (sp->energy > 30 && sp->pods > 40 && e_loadtubes(sp)) return; if (e_torpedo(sp)) return; /* * should we run away; can we? */ if (e_checkarms(sp) < randm((int)(sp->num_phasers+ sp->num_tubes)/3)) { if (!e_cloak_on(sp, fed)) (void) e_runaway(sp, fed); return; } /* * Pursued from behind, low power: jettison engineering! */ if (betw(bear, 90.0, 270.0) && sp->energy < 10 && sp->regen < 4.0 && e_jettison(sp, fed)) return; /* * put in other junk later */ if (e_cloak_on(sp, fed)) return; } /* * Either distant range, or we can't figure out * what to do at medium range */ /* Warp drive dead and Federation destructing, run away! */ if (fed->delay < 15. && (is_dead(sp, S_WARP))) { (void) e_runaway(sp, fed); return; } /* * enemy in our blind area? make a quick turn. */ /* XXXX Should we check for blind spots? * or should we check for forward/aft */ if (betw(bear, sp->t_blind_left, sp->t_blind_right)) { (void) e_pursue(sp, fed, 1.0); return; } if (e_locktubes(sp, fed)) return; if (e_lockphasers(sp, fed)) return; /* * attack? */ /* tmpf = fabs(fed->warp); if (sp->target != fed || sp->warp + tmpf > 2.0) { (void) e_pursue(sp, fed, (int)tmpf + 2.0 + randm(2)); return; } */ if (e_attack(sp, fed)) return; if (sp->energy > 30 && sp->pods > 40 && e_loadtubes(sp)) return; if (e_cloak_on(sp, fed)) return; /* * gee, there's nothing that we want to do! */ if (cansee(sp)) printf("%s: We're being scanned by the %s\n", science, sp->name); } SHAR_EOF chmod +x 'strat1.c' fi # end of overwriting check if test -f 'subs.c' then echo shar: will not over-write existing file "'subs.c'" else cat << \SHAR_EOF > 'subs.c' /* * TREK73: subs.c * * Miscellaneous Subroutines * * ship_name, newitem, delitem, rangefind, bearing, phaser_hit, * torpedo_hit, antimatter_hit, round, rectify */ #include "externs.h" #include #include struct ship *ship_name(name) char *name; { register int i; register int j; register int len; if (isascii(*name) && islower(*name)) *name = toupper(*name); j = shipnum; len = strlen(name); for (i=1; i<=j; i++) { if (shiplist[i]->complement < 0) continue; if (!strncmp(name, shiplist[i]->name, len)) return shiplist[i]; } printf("%s: I am unable to find the %s\n", science, name); return NULL; } struct list *newitem(item) int item; { register struct list *new; register struct list *newtail; /* * if there's no "tail" node, make one (only happens at init) */ if (tail == NULL) { new = MKNODE(struct list, *, 1); if (new == (struct list *)NULL) { fprintf(stderr, "newitem: malloc failed\n"); exit(2); } new->back = &head; new->fwd = NULL; new->data.tp = NULL; head.fwd = new; tail = new; } new = tail; /* * now make the new tail node */ newtail = MKNODE(struct list, *, 1); if (newtail == (struct list *)NULL) { fprintf(stderr, "newitem: malloc failed\n"); exit(2); } newtail->back = new; newtail->fwd = NULL; newtail->data.tp = NULL; newtail->type = 0; tail = newtail; /* * link the old tail node to the new one */ new->type = item; new->fwd = newtail; return new; } int delitem(item) struct list *item; { register struct list *bp; register struct list *fp; bp = item->back; fp = item->fwd; if (item->data.tp != NULL) free((char *) item->data.tp); /* * re-arrange pointers on both the next and the previous * nodes; if no forward pointer, we were the tail so make * the bp the new tail node. */ if (fp != NULL) { bp->fwd = fp; fp->back = bp; } else { tail = bp; bp->fwd = NULL; } free((char *) item); } int rangefind(xfrom, xto, yfrom, yto) int xfrom; int xto; int yfrom; int yto; { register double x, y; x = xto - xfrom; y = yto - yfrom; if (x == 0.0 && y == 0.0) return 0; else return (int) hypot(x, y); } /* * This routine finds the bearing of (xto,yto) from (xfrom,yfrom) */ float bearing(xfrom, xto, yfrom, yto) int xfrom; int xto; int yfrom; int yto; { register double x, y; register float bear; x = xto - xfrom; y = yto - yfrom; if (x == 0.0 && y == 0.0) bear = 0.0; else bear = todegrees(atan2(y, x)); bear = rectify(bear); return bear; } int phaser_hit(sp, x, y, bank, true_bear) struct ship *sp; int x; int y; struct phaser *bank; float true_bear; { register int hit; int i; float spread; float bear; double d1; double d2; hit = 0; i = rangefind(sp->x, x, sp->y, y); if (i < MAX_PHASER_RANGE) { bear = bearing(sp->x, x, sp->y, y); spread = rectify(true_bear - bear); /* * Check if a target is within the phaser spread */ if (betw(spread, sp->p_spread, 360-spread)) return 0; d1 = 1.0 - (float)i/MAX_PHASER_RANGE; d2 = (float)bank->load * sqrt(d1) * sp->p_percent / 100; /* XXXX */ /* * This may have to be changed if phaser spread or maximum * phaser load is changed */ d2 = (float)bank->load * d2 * 45.0/(float)sp->p_spread * sp->p_percent / 100; hit = d2/10.0; } return hit; } int torpedo_hit(fuel, x, y, tx, ty) int fuel; int x; int y; int tx; int ty; { register int hit; int i; double d1; double d2; float f1; float f2; hit = 0; i = rangefind(x, tx, y, ty); f1 = fuel * HIT_PER_POD; f2 = fuel * PROX_PER_POD; if (i < f2) { d1 = 1.0 - (float)i/f2; d2 = (float)f1 * sqrt(d1); hit = d2; } return hit; } antimatter_hit(ptr, x, y, fuel) char *ptr; int x; int y; int fuel; { register struct list *lp; register int hit; int tarx, tary; int s; float bear; struct torpedo *tp; struct ship *sp; for (lp = &head; lp != tail; lp = lp->fwd) { if (lp->type == 0) continue; sp = NULL; tp = NULL; if (lp->type == I_SHIP) { sp = lp->data.sp; tarx = sp->x; tary = sp->y; } else { tp = lp->data.tp; tarx = tp->x; tary = tp->y; } if (sp == (struct ship *) ptr || tp == (struct torpedo *) ptr) continue; hit = torpedo_hit(fuel, x, y, tarx, tary); if (hit <= 0) continue; if (sp) { /* * Determine which shield is hit */ bear = rectify(bearing(tarx, x, tary, y) - sp->course); if (bear <= 45.0 || bear >= 315.0) s = 1; else if (bear <= 135.0) s = 2; else if (bear < 225.0) s = 3; else s = 4; (void) damage(hit, sp, s, &a_damage, D_ANTIMATTER); } else { if (tp->timedelay <= segment) continue; tp->timedelay = segment; switch (lp->type) { case I_TORPEDO: printf("hit on torpedo %d\n", tp->id); break; case I_PROBE: printf("hit on probe %d\n", tp->id); break; case I_ENG: printf("hit on %s engineering\n", tp->from->name); break; default: printf("hit on unknown item %d\n", tp->id); } } } } float round(x) float x; { return(floor(x + 0.5)); } float rectify(x) float x; { while (x < 0.0) { x += 360.0; } while (x >= 360.0){ x -= 360.0; } return x; } SHAR_EOF chmod +x 'subs.c' fi # end of overwriting check if test -f 'vers.c' then echo shar: will not over-write existing file "'vers.c'" else cat << \SHAR_EOF > 'vers.c' /* * TREK73: vers.c * * version */ vers() { extern char version[]; printf("%s\n", version); printf("Jeff Okamoto, Peter Yee, and Roger Noe\n"); return 1; } SHAR_EOF chmod +x 'vers.c' fi # end of overwriting check # End of shell archive exit 0