Doug@ecn-aa.UUCP (09/07/85)
# # Here's a simple visual Star Trek game that I recently wrote. # It's pretty much the same as other Star Trek games, but the # visual aspect makes it a bit more entertaining. # # This version seems to work OK here at purdue-ecn (4.2,4.3bsd). It # should work on other Unix OS's with little or no changes. # It will work on CP/M if you have the Aztec C compiler and # 64K of ram. It will work on the IBM PC & compatibles with # minor changes. # # Send flames to /dev/null. Please mail be a copy of any major # enhancements/modifications that you make. # # You are free to distribute copies to anyone who wants the game, # as long as you don't sell it. # # dug patrick # ihnp4!pur-ee!dug # #------------------------------------------------------------------------ echo x - main.c cat >main.c << '!EOF!' /* * main.c * * visual star trek * * BASIC version written by Tom Goerz and debugged by Dug Patrick * 22-Dec-79, 13-Nov-80 * C version written by Dug Patrick * 05-Aug-84, 11-Mar-85 * */ #include "vtrek.h" char playership[] = " ? "; int rolines = 0; main() { int cmd, ch; char str[44]; #ifdef AZTEC int errortrap(); Sysvec[FLT_FAULT] = errortrap; #endif instructions(); initvars(); terminit(); replot(); sprintf(str, "You have %.1f stardates to save the", lastdate - stardate); readout(ADDLINE, str); readout(ADDLINE, "Federation from the Klingon invasion."); setcondition(); while (numkling > 0) { switch (cmd = getcmd()) { case 'H' : /* hyper-space */ hyperspace(); break; case 'S' : /* short range scan */ srs(); break; case 'L' : /* long range scan */ lrs(); break; case 'P' : /* fire phasers */ phasers(); break; case 'T' : /* fire photon torpedo */ torpedo(); break; case 'U' : /* change shield level */ defense(); break; case 'R' : /* replot screen */ replot(); continue; case 'Q' : /* move using impulse engines */ case 'W' : case 'E' : case 'A' : case 'D' : case 'Z' : case 'X' : case 'C' : impulse(cmd); break; case 'K' : /* kill - commit suicide */ prompt("Quit ? "); ch = getch(); if (Toupper(ch) == 'Y') die(); break; case 'F' : /* fix devices */ repdevices(); break; case 03 : /* exit without warning */ case 04 : die(); break; case '?' : /* help */ help(); break; default : /* illegal command */ readout(ADDLINE, "Type '?' for help."); break; } fixdev(REL, RND, 5); setcondition(); klingmove(); if ((stardate += 0.1) > lastdate) timeout(); plt_stat(ELEMENT, STARDATE); plt_num(INFO); if (energy <= 0 && shields <= 0) dead(); } win(); } #ifdef AZTEC errortrap(errcode, addr) int errcode, addr; { } #endif !EOF! echo x - makefile cat >makefile << '!EOF!' OBJS=main.o plot.o sub1.o sub2.o termio.o a.out: $(OBJS) $(CC) $(OBJS) -lm -ltermlib .c.o: cc -O -c $*.c $(OBJS): vtrek.h !EOF! echo x - plot.c cat >plot.c << '!EOF!' /* plot.c -- plot routines for visual star trek */ #include "vtrek.h" /* replot screen */ replot() { cls(); plt_stat(ALL); plt_srs(ALL); plt_dam(ALL); plt_gal(ALL); moveyx(12, 18); printf("READOUT"); moveyx(13, 18); printf("-------"); plt_num(ALL); } /* plot status (upper left) */ plt_stat(op, item) int op, item; { static char *text[9] = { " Status", " ------", "Stardate :", "Condition :", "Quadrant :", "Sector :", "Energy :", "Photon torps :", "Shields :" }; static char *ctext[4] = { "Green", "Yellow", "Red", "Docked" }; int i, high, low; if (op & TEXT) for (i = 0; i < 9; i++) { moveyx(i + 2, 1); printf("%s", text[i]); } if (op & (INFO | ELEMENT)) { if (op & INFO) { low = STARDATE; high = SHIELDS; } else { low = item; high = item; } for (i = low; i <= high; i++) { switch (i) { case STARDATE : moveyx(4, 16); printf("%-.1f", stardate); break; case CONDITION : moveyx(5, 16); printf("%-6s", ctext[condition]); break; case QUADRANT : moveyx(6, 16); printf("[%d,%d]", xquad + 1, yquad + 1); break; case SECTOR : moveyx(7, 16); printf("[%d,%d]", xsect + 1, ysect + 1); break; case ENERGY : moveyx(8, 16); printf("%-4d", energy); break; case TORPS : moveyx(9, 16); printf("%-2d", torps); break; case SHIELDS : moveyx(10, 16); printf("%-4d", shields); break; } } } } /* plot short range scan */ plt_srs(op, xs, ys) int op, xs, ys; { static char *htext = "-1--2--3--4--5--6--7--8-"; static char *stext[6] = { " ", "<K>", "<S>", " * ", "???", " + " }; int i, j; if (op & TEXT) { moveyx(1, 28); printf("%s", htext); for (i = 1; i < 9; i++) { moveyx(i + 1, 27); printf("%d", i); moveyx(i + 1, 52); printf("%d", i); } moveyx(10, 28); printf("%s", htext); } strcpy(stext[PLAYER], playership); if (op & INFO) { for (i = 0; i < 8; i++) { moveyx(i + 2, 28); for (j = 0; j < 8; j++) printf("%s", stext[(damage[SRS] <= 0) ? EMPTY : quadrant[j][i]]); } } else if (op & ELEMENT) { moveyx(ys + 2, 28 + 3 * xs); printf("%s", stext[(damage[SRS] <= 0) ? EMPTY : quadrant[xs][ys]]); } } /* plot damage info */ plt_dam(op, item) int op, item; { static char *text[10] = { " Damage Report", " -------------", "Warp engines :", "S.R. sensors :", "L.R. sensors :", "Phaser control :", "Damage control :", "Defense control :", "Computer :", "Photon tubes :" }; int i; if (op & TEXT) for (i = 0; i < 10; i++) { moveyx(i + 1, 56); printf("%s", text[i]); } if (op & INFO) for (i = 0; i < 8; i++) { moveyx(i + 3, 74); if (damage[DAMAGE] <= 0) printf(" "); else printf("%4d", damage[i]); } else if (op & ELEMENT) { moveyx(item + 3, 74); if (damage[DAMAGE] <= 0) printf(" "); else printf("%4d", damage[item]); } } /* plot galaxy map */ plt_gal(op, xq, yq) int op, xq, yq; { static char *htext = "-1- -2- -3- -4- -5- -6- -7- -8-"; int i, j, fedquad; if (op & TEXT) { moveyx(13, 47); printf("%s", htext); for (i = 1; i < 9; i++) { moveyx(i + 13, 45); printf("%d:", i); for (j = 0; j < 7; j++) { moveyx(i + 13, 50 + (j << 2)); putch(':'); } moveyx(i + 13, 78); printf(":%d", i); } moveyx(22, 47); printf("%s", htext); } if (op & INFO) { for (i = 0; i < 8; i++) for (j = 0; j < 8; j++) { moveyx(i + 14, 47 + (j << 2)); if (damage[COMPUTER] <= 0 || !galaxy[j][i].known) printf(" "); else printf("%01d%01d%01d", galaxy[j][i].nkling, galaxy[j][i].nbase, galaxy[j][i].nstar); } moveyx(yquad + 14, 46 + (xquad << 2)); putch('['); moveyx(yquad + 14, 50 + (xquad << 2)); putch(']'); } else if (op & ELEMENT) { moveyx(yq + 14, 46 + (xq << 2)); fedquad = (xq == xquad && yq == yquad); putch(fedquad ? '[' : ':'); if (damage[COMPUTER] <= 0) printf(" "); else printf("%01d%01d%01d", galaxy[xq][yq].nkling, galaxy[xq][yq].nbase, galaxy[xq][yq].nstar); putch(fedquad ? ']' : ':'); } } /* plot number of star bases & klingons */ plt_num(op) int op; { float kf; if (op & TEXT) { moveyx(23, 47); printf("Base stars = "); moveyx(23, 63); printf("Klingons = "); moveyx(24, 54); printf("Kill Factor = "); } if (op & INFO) { moveyx(23, 59); printf(" %d", numbases); moveyx(23, 73); printf(" %d/%d ", numkling, begkling); moveyx(24, 68); if (begdate != stardate) kf = (begkling - numkling) / (stardate - begdate); else kf = 0.0; printf("%5.3f ", kf); } } /* change readout */ readout(op, str) int op; char *str; { int i, j; switch (op) { case CLEAR : /* clear readout */ for (i = 14; i <= 13 + rolines; i++) { moveyx(i, 1); for (j = 0; j < 44; j++) putch(' '); } rolines = 0; break; case ADDLINE : /* add line to readout */ if (rolines >= 10) readout(CLEAR, NULL); moveyx(14 + rolines, 1); printf("%-.44s", str); rolines++; break; } } !EOF! echo x - sub1.c cat >sub1.c << '!EOF!' /* sub1.c -- subroutines for visual star trek */ #include "vtrek.h" /* print short help information */ help() { if (rolines > 5) readout(CLEAR, NULL); readout(ADDLINE, "Directions = Q,W,E,A,D,Z,X,C"); readout(ADDLINE, "H = Hyper-space S = Short range scan"); readout(ADDLINE, "L = Long range scan P = Fire phasers"); readout(ADDLINE, "T = Fire torpedo U = Defense control"); readout(ADDLINE, "R = Redraw screen F = Fix devices"); } /* get command character */ getcmd() { int ch, i; char str[40]; sprintf(str, "Command %s ? ", captain); prompt(str); ch = getch(); return Toupper(ch); } /* give option to see instructions */ instructions() { FILE *fp; char line[80]; int n, ch; printf("Instructions ? "); /* This would seem to be a silly place to randomize, but this */ /* location made things a bit easier for the CPM version. */ #ifdef AZTEC /* if randomize is available then use it instead of this: */ while (!chready()) rnd(1); #else randomize(); #endif if (fgets(line, 80, stdin) == NULL) vexit(0); ch = Toupper(line[0]); if (ch == 'Y') { if ((fp = fopen(VTREKINS, "r")) == NULL) printf("Error: Missing instruction file\n"); else { terminit(); for (;;) { for (n = 0; n < 22; n++) { if (fgets(line, 80, fp) == NULL) break; printf("%s", line); #ifdef UNIX putchar('\r'); #endif } if (n < 22) break; printf("--More--"); getch(); printf("\r \r"); } fclose(fp); termreset(); } } } /* get captain's name and ship's name */ getnames() { int ch, tmp; printf("Your name captain ? "); if (fgets(captain, 11, stdin) == NULL) vexit(1); if (captain[tmp = strlen(captain) - 1] == '\n') captain[tmp] = '\0'; else while (getchar() != '\n'); if (*captain == '\0') strcpy(captain, "Duncel"); printf("Your ship's name captain ? "); if (fgets(shipname, 11, stdin) == NULL) vexit(1); if (shipname[tmp = strlen(shipname) - 1] == '\n') shipname[tmp] = '\0'; else while (getchar() != '\n'); if (*shipname == '\0') strcpy(shipname, "Fruit"); } /* get skill level */ getskill() { char level[10]; printf("Skill level (0-5, 0=easy, 5=hard) ? "); if (fgets(level, 10, stdin) == NULL) vexit(1); if (isdigit(level[0])) skill = level[0] - '0'; else skill = 3; } /* initialize galaxy */ initgal() { int i, j, k, r, n; numkling = 0; for (i = 0; i < 8; i++) { for (j = 0; j < 8; j++) { if ((r = rnd(100)) < 10) k = 3; else if (r < 20) k = 2; else if (r < 30) k = 1; else k = 0; numkling += k; galaxy[i][j].nkling = k; galaxy[i][j].nstar = rnd(8) + 1; galaxy[i][j].nbase = 0; galaxy[i][j].known = 0; } } numbases = rnd(3) + 2; for (n = 0; n < numbases; n++) { for (;;) { if (galaxy[i = rnd(7)][j = rnd(7)].nbase == 0) { galaxy[i][j].nbase = 1; break; } } } } /* initialize variables */ initvars() { int i; getnames(); getskill(); initgal(); numkmove = skill; begkling = numkling; xquad = rnd(7); yquad = rnd(7); old_xsect = (xsect = rnd(7)); old_ysect = (ysect = rnd(7)); shields = 0; energy = 3000; stardate = 2000.0; begdate = stardate; lastdate = stardate + (float)numkling; torps = 10; playership[1] = *shipname; condition = YELLOW; for (i = 0; i < 8; i++) damage[i] = 100; old_xquad = -1; old_yquad = -1; setpos(); } /* set new position -- check for outside galaxy, set up new quadrant */ setpos() { int dam = 0, i, j, n, dev, status = 0; static int notfirstcall = 0; if (xsect > 7) { xsect = 0; xquad++; } else if (xsect < 0) { xsect = 7; xquad--; } if (ysect > 7) { ysect = 0; yquad++; } else if (ysect < 0) { ysect = 7; yquad--; } if (xquad > 7) { dam = 1; xquad = 7; xsect = 7; } else if (xquad < 0) { dam = 1; xquad = 0; xsect = 0; } if (yquad > 7) { dam = 1; yquad = 7; ysect = 7; } else if (yquad < 0) { dam = 1; yquad = 0; ysect = 0; } if (dam) { readout(ADDLINE, "You encounter a force field."); shields -= rnd(20) + 90; plt_stat(ELEMENT, SHIELDS); status = DAMAGE; if (shields < 0) die(); } if (xquad != old_xquad || yquad != old_yquad) { galaxy[xquad][yquad].known = 1; if (notfirstcall) { plt_gal(ELEMENT, old_xquad, old_yquad); plt_gal(ELEMENT, xquad, yquad); } for (i = 0; i < 8; i++) for (j = 0; j < 8; j++) quadrant[i][j] = EMPTY; quadrant[xsect][ysect] = PLAYER; for (n = 0; n < galaxy[xquad][yquad].nkling; n++) { for (;;) { if (quadrant[i = rnd(7)][j = rnd(7)] == EMPTY) { quadrant[i][j] = KLINGON; break; } } klingon[n].xs = i; klingon[n].ys = j; klingon[n].sh = 200; } for (; n < 3; n++) klingon[n].xs = klingon[n].ys = klingon[n].sh = -1; for (n = 0; n < galaxy[xquad][yquad].nbase; n++) for (;;) { if (quadrant[i = rnd(7)][j = rnd(7)] == EMPTY) { quadrant[i][j] = STARBASE; base_xsect = i; base_ysect = j; break; } } for (n = 0; n < galaxy[xquad][yquad].nstar; n++) for (;;) { if (quadrant[i = rnd(7)][j = rnd(7)] == EMPTY) { quadrant[i][j] = STAR; break; } } old_xquad = xquad; old_yquad = yquad; if (notfirstcall) { plt_srs(INFO); plt_stat(ELEMENT, CONDITION); plt_stat(ELEMENT, QUADRANT); plt_gal(ELEMENT, xquad, yquad); } } else { switch (quadrant[xsect][ysect]) { case KLINGON: dam = rnd(20) + 90; if (damkling(xsect, ysect, dam) != DEAD) { xsect = old_xsect; ysect = old_ysect; } dam >>= 1; if ((shields -= dam) < 0) die(); fixdev(REL, RND, -dam); plt_stat(ELEMENT, SHIELDS); break; case STAR: readout(ADDLINE, "There's a star in the way, Duncel!"); if (damage[SRS] > 0) strcpy(captain, "Duncel"); xsect = old_xsect; ysect = old_ysect; break; case STARBASE: xsect = old_xsect; ysect = old_ysect; readout(ADDLINE, "There's a star base in the way!"); break; } status = quadrant[xsect][ysect]; quadrant[old_xsect][old_ysect] = EMPTY; quadrant[xsect][ysect] = PLAYER; plt_srs(ELEMENT, old_xsect, old_ysect); plt_srs(ELEMENT, xsect, ysect); } old_xsect = xsect; old_ysect = ysect; if (notfirstcall) plt_stat(ELEMENT, SECTOR); notfirstcall = 1; return status; } /* "So this is it. We're going to die." -- Arthur Dent */ die() { char str[10]; plt_stat(ELEMENT, SHIELDS); prompt("(Press RETURN)"); while (getch() != '\r') ; cls(); moveyx(11, 21); printf("Your ship the %s has been destroyed.", shipname); moveyx(12, 21); printf("The Federation will be conquered.\n\n\n\r"); vexit(0); } win() { char str[10]; readout(ADDLINE, "Congratulations!"); prompt("(Press RETURN)"); while (getch() != '\r') ; cls(); moveyx(11, 16); printf("The last of the Klingon battle cruisers have been\n"); printf("%15sdestroyed. You alone have saved the Federation. You\n", ""); printf("%15sare promoted to Admiral %s !!!\n\n\n\r", "", captain); vexit(0); } /* random (?) number generator */ rnd(max) int max; { #ifdef AZTEC static long iy = 0x86A186A1; iy *= 125; iy &= 0x7FFFFFFF; iy %= 0xAAAAAAAd; return (int)((iy >> 8) % max); #else return (int)(rand() % max); #endif } #ifdef UNIX /* randomize */ randomize() { srand(time(0)); } #endif /* impulse drive -- move one sector */ impulse(dir) int dir; { int dx, dy, status; if (energy <= 0) { readout(ADDLINE, "Insufficient energy for command."); return ERROR; } if (checkdir(dir, &dx, &dy) != ERROR) { xsect += dx; ysect += dy; } energy--; status = setpos(); plt_stat(ELEMENT, ENERGY); return status; } /* defense -- set shield level */ defense() { int i; if (damage[DEFENSE] <= 0) readout(ADDLINE, "Defense control is damaged."); else { energy += shields; for (;;) { prompt("Shield level ? "); if ((shields = getnum()) >= 0 && shields <= energy) { energy -= shields; break; } } if (shields > 0) { playership[0] = '('; playership[2] = ')'; } else { playership[0] = ' '; playership[2] = ' '; } plt_srs(ELEMENT, xsect, ysect); plt_stat(ELEMENT, SHIELDS); plt_stat(ELEMENT, ENERGY); } } /* get a number */ getnum() { int num = 0, ch; while ((ch = getch()) != '\r') { putch(ch); if (isdigit(ch)) num = num * 10 + ch - '0'; else if (ch == '\b') { num = num / 10; putch(' '); putch('\b'); } else break; } return num; } /* damage a klingon */ damkling(xs, ys, dam) int xs, ys, dam; { char str[40]; int k; if ((k = findkling(xs, ys)) == ERROR) readout(ADDLINE, "damkling: error"); else { if (dam != AUTOKILL) { sprintf(str, "You did %d to the Klingon.", dam); readout(ADDLINE, str); } if ((klingon[k].sh -= dam) < 0) { readout(ADDLINE, "Klingon destroyed."); klingon[k].xs = klingon[k].ys = -1; quadrant[xs][ys] = EMPTY; plt_srs(ELEMENT, xs, ys); numkling--; plt_num(INFO); galaxy[xquad][yquad].nkling--; plt_gal(ELEMENT, xquad, yquad); return DEAD; } } return ALIVE; } /* fix/damage a device */ fixdev(type, dev, value) int type; /* ABSolution fix or RELative fix */ int dev; /* device (if RND then pick a damaged device) */ int value; /* new device value for ABS, amount to add for REL */ { int i, old_dam; if (dev == RND) { dev = rnd(8); if (value > 0 && damage[dev] >= 100) { for (i = 0; i < 8; i++) { if (++dev > 7) dev = 0; if (damage[dev] < 100) break; } } } old_dam = damage[dev]; if (type == ABS) damage[dev] = value; else damage[dev] += value; if (damage[dev] > 100) damage[dev] = 100; plt_dam(ELEMENT, dev); /* see if device changed from fixed <==> broken */ if ((old_dam <= 0 && damage[dev] > 0) || (old_dam > 0 && damage[dev] <= 0)) { switch (dev) { case SRS : plt_srs(INFO); break; case DAMAGE : plt_dam(INFO); break; case COMPUTER : plt_gal(INFO); break; } } } /* print a prompt in the upper left hand corner */ prompt(str) char *str; { int i; moveyx(1, 1); for (i = 0; i < 26; i++) putch(' '); moveyx(1, 1); printf("%-.26s", str); } /* check a direction for validity and return delta-x and delta-y */ checkdir(dir, dx, dy) int dir, *dx, *dy; { static struct { int d, x, y; } dirs[8] = { {'Q', -1, -1}, {'W', 0, -1}, {'E', 1, -1}, {'D', 1, 0}, {'C', 1, 1}, {'X', 0, 1}, {'Z', -1, 1}, {'A', -1, 0} }; int i; for (i = 0; i < 8; i++) if (dirs[i].d == dir) { *dx = dirs[i].x; *dy = dirs[i].y; return 0; } return ERROR; } /* hyperspace drive */ hyperspace() { int i, dir, dx, dy, w, tmp, savex, savey; if (damage[WARP] <= 0) readout(ADDLINE, "Warp engines are damaged."); else { prompt("Direction ? "); if (islower(dir = getch())) dir = toupper(dir); if (checkdir(dir, &dx, &dy) == ERROR) { readout(ADDLINE, "Illegal direction."); return; } prompt("Warp ? "); putch(w = getch()); if (isdigit(w)) { w -= '0'; if (w <= 0) return; savex = xsect; savey = ysect; while ((tmp = xsect + dx) >= 0 && tmp <= 7 && (tmp = ysect + dy) >= 0 && tmp <= 7) { if (impulse(dir)) return; } if (energy < 20 * w) readout(ADDLINE, "Insufficient energy for command."); else { xquad += w * dx; yquad += w * dy; energy -= 20 * w; stardate += (double)(w) / 5.0; xsect = savex; ysect = savey; setpos(); plt_stat(ELEMENT, ENERGY); } } else if (w == '.' && isdigit(w = getch())) { putch(w); w -= '0'; stardate += (double)(w) / 50.0; for (; w > 0; w--) if (impulse(dir)) break; } else readout(ADDLINE, "Illegal warp factor."); } } /* long range scan */ lrs() { int x, y; char str[20]; if (damage[LRS] <= 0) readout(ADDLINE, "Long range sensors are damaged."); else { if (rolines > 3) readout(CLEAR, NULL); for (y = yquad - 1; y <= yquad + 1; y++) { readout(ADDLINE, "+---+---+---+"); strcpy(str, "|"); for (x = xquad - 1; x <= xquad + 1; x++) { if (x < 0 || x > 7 || y < 0 || y > 7) strcat(str, "XXX"); else { if (damage[COMPUTER] > 0) galaxy[x][y].known = 1; sprintf(str + strlen(str), "%d%d%d", galaxy[x][y].nkling, galaxy[x][y].nbase, galaxy[x][y].nstar); plt_gal(ELEMENT, x, y); } strcat(str, "|"); } str[13] = '\0'; readout(ADDLINE, str); } readout(ADDLINE, "+---+---+---+"); plt_gal(ELEMENT, xquad, yquad); } } /* short range scan */ srs() { int k, dx, dy; double dir, dist; char str[40]; if (damage[SRS] <= 0) readout(ADDLINE, "Short range sensors are damaged."); else { if (rolines > 6) readout(CLEAR, NULL); readout(ADDLINE, "Sector Direction Distance"); for (k = 0; k < 3; k++) { if (klingon[k].sh >= 0) { if (damage[COMPUTER] <= 0) sprintf(str, "[%d,%d]", klingon[k].xs+1, klingon[k].ys+1); else { dx = klingon[k].xs - xsect; dy = klingon[k].ys - ysect; dist = sqrt((double)(dx*dx) + (double)(dy*dy)); if (dx) { dir = atan2(-(double)dy, (double)dx) * 180.0 / PI; if (dir < 0.0) dir += 360.0; } else if (dy > 0) dir = 270.0; else dir = 90.0; sprintf(str, "[%d,%d] %5.1f %4.1f", klingon[k].xs+1, klingon[k].ys+1, dir, dist); } readout(ADDLINE, str); } } } } findkling(x, y) int x, y; { int i; for (i = 0; i < 3; i++) if (x == klingon[i].xs && y == klingon[i].ys) return i; return ERROR; } !EOF! echo x - sub2.c cat >sub2.c << '!EOF!' /* sub2.c -- subroutines for visual star trek */ #include "vtrek.h" /* klingon movement and firing */ klingmove() { int k, dx, dy, dam, kx, ky, nx, ny, i, j; int minj, mind, d, sk; static int dirx[9] = {1, 1, 0, -1, -1, -1, 0, 1, 0}; static int diry[9] = {0, 1, 1, 1, 0, -1, -1, -1, 0}; double dist; char str[40]; for (k = 0; k < 3; k++) { if (klingon[k].sh < 0) continue; kx = klingon[k].xs; ky = klingon[k].ys; /* movement */ if (rnd(100) < 30 + skill * 5) { for (i = 0; i < numkmove; i++) { mind = 999; minj = -1; for (j = 0; j < 9; j++) { nx = kx + dirx[j]; ny = ky + diry[j]; if (nx < 0 || nx > 7 || ny < 0 || ny > 7) continue; if (quadrant[nx][ny] != EMPTY) continue; dx = xsect - nx; dy = ysect - ny; d = dx * dx + dy * dy; if (d < mind) { mind = d; minj = j; } } if (minj < 0) break; nx = kx + dirx[minj]; ny = ky + diry[minj]; quadrant[kx][ky] = EMPTY; quadrant[nx][ny] = KLINGON; plt_srs(ELEMENT, nx, ny); plt_srs(ELEMENT, kx, ky); kx = nx; ky = ny; } klingon[k].xs = kx; klingon[k].ys = ky; } /* fire disrupters */ dx = kx - xsect; dy = ky - ysect; dist = sqrt((double)(dx * dx) + (double)(dy * dy)); dam = (rnd(100) + 100 + skill * 20) / dist; if (damage[SRS] > 0) sprintf(str, "Klingon at [%d,%d] hits with %d units.", kx+1, ky+1, dam); else sprintf(str, "Klingon hits with %d units.", dam); readout(ADDLINE, str); if (condition == DOCKED) readout(ADDLINE, "Starbase shields protect you!"); else { if ((shields -= dam) < 0) die(); sk = skill * 250; if (shields <= 500 + sk) fixdev(REL, RND, -dam / 2); else if (shields < 1500 + sk) fixdev(REL, RND, -(1500 + sk - shields) * dam / 2000); } } plt_stat(ELEMENT, SHIELDS); } /* fire phasers */ phasers() { int dam, k, dx, dy, e, kx, ky; char str[40]; double dist; if (damage[PHASER] < 0) readout(ADDLINE, "Phasers are damaged."); else { for (k = 0; k < 3; k++) { if (klingon[k].sh < 0) continue; kx = klingon[k].xs; ky = klingon[k].ys; if (damage[SRS] > 0) { sprintf(str, "Units aimed at [%d,%d] : ", kx + 1, ky + 1); prompt(str); } else prompt("Units aimed at [?,?] : "); e = getnum(); dx = kx - xsect; dy = ky - ysect; dist = sqrt((double)(dx * dx) + (double)(dy * dy)); dam = e / dist; if (energy < e) readout(ADDLINE, "Insufficient energy for command."); else { energy -= e; damkling(kx, ky, dam); plt_stat(ELEMENT, ENERGY); } } } } /* set condition */ setcondition() { int dx, dy, i, oldcond; int plotgal, plotsrs; oldcond = condition; if (galaxy[xquad][yquad].nkling) condition = RED; else if (shields < 100) { condition = YELLOW; if (oldcond != DOCKED) readout(ADDLINE, "Captain, shields are dangerously low."); } else condition = GREEN; if (galaxy[xquad][yquad].nbase) { dx = xsect - base_xsect; dy = ysect - base_ysect; if (abs(dx) <= 1 && abs(dy) <= 1) { condition = DOCKED; if (oldcond != DOCKED) { energy = 3000; torps = 10; shields = 0; plotsrs = damage[SRS] <= 0; plotgal = damage[COMPUTER] <= 0; for (i = 0; i < 8; i++) damage[i] = 100; readout(ADDLINE, "Shields lowered for docking."); playership[0] = playership[2] = ' '; plt_srs(ELEMENT, xsect, ysect); plt_stat(INFO); plt_dam(INFO); if (plotsrs) plt_srs(INFO); if (plotgal) plt_gal(INFO); oldcond = DOCKED; } } } if (oldcond != condition) plt_stat(ELEMENT, CONDITION); } /* move torp to a sector and see if it hit */ mvtorp(x, y) int x, y; { int ch, status = ALIVE; char str[40]; ch = quadrant[x][y]; quadrant[x][y] = TBLAST; plt_srs(ELEMENT, x, y); switch (ch) { case EMPTY : break; case KLINGON : damkling(x, y, AUTOKILL); status = DEAD; break; case STARBASE : readout(ADDLINE, "Starbase destroyed."); galaxy[xquad][yquad].nbase--; numbases--; plt_num(INFO); status = DEAD; break; case STAR : sprintf(str, "Star at [%d,%d] has gone supernova.", x + 1, y + 1); readout(ADDLINE, str); galaxy[xquad][yquad].nstar--; status = DEAD; break; } if (status == DEAD) ch = EMPTY; quadrant[x][y] = ch; plt_srs(ELEMENT, x, y); return status; } /* fire a torpedo */ torpedo() { int dir, i, ch, x, y; int dx, dy; double th; static char dirstr[] = "DEWQAZXC"; if (damage[TUBES] < 0) readout(ADDLINE, "Photon torpedo tubes are damaged."); else if (torps < 1) readout(ADDLINE, "You're out of photon torpedos!"); else { torps--; plt_stat(ELEMENT, TORPS); prompt("Direction ? "); dir = getch(); if (isdigit(dir)) { putch(dir); dir -= '0'; while ((ch = getch()) != '\r') { putch(ch); if (isdigit(ch)) dir = dir * 10 + ch - '0'; else break; } } else { ch = Toupper(dir); dir = 0; for (i = 0; i < 8; i++) { if (ch == dirstr[i]) break; dir += 45; } if (i >= 8) { readout(ADDLINE, "Illegal direction."); return; } } th = dir / 180.0 * PI; if (dir >= 315 || dir <= 45 || (dir >= 135 && dir <= 225)) { dx = (dir >= 315 || dir <= 45) ? 1 : -1; for (x = xsect + dx; x >= 0 && x <= 7; x += dx) { y = ysect - (x - xsect) * tan(th) + 0.5; if (y < 0 || y > 7) break; if (mvtorp(x, y) == DEAD) { break; } } } else { th -= PI / 2.0; dy = (dir >= 45 && dir <= 135) ? -1 : 1; for (y = ysect + dy; y >= 0 && y <= 7; y += dy) { x = xsect + (y - ysect) * tan(th) + 0.5; if (x < 0 || x > 7) break; if (mvtorp(x, y) == DEAD) break; } } } } /* repair devices somewhat */ repdevices() { int i; for (i = 0; i < 8; i++) fixdev(REL, i, 5); } /* out of star dates */ timeout() { char str[44]; readout(CLEAR); readout(ADDLINE, "You have run out of stardates an there"); sprintf(str, "are still %d Klingons left. Some captain you", numkling); readout(ADDLINE, str); readout(ADDLINE, "are."); die(); } /* out of energy */ dead() { readout(CLEAR); readout(ADDLINE, "Your ship is dead in space. Eventually,"); readout(ADDLINE, "Klingons show up and relieve you of your"); readout(ADDLINE, "task . . ."); die(); } /* reset terminal and exit program */ vexit(status) { termreset(); exit(status); } !EOF! echo x - termio.c cat >termio.c << '!EOF!' /* terminal I/O */ #include "vtrek.h" #ifdef AZTEC /* These constants are at the beginning so they will be easy to find with */ /* DDT. They will be a 0103 and 0107 if this file is loaded first. */ char cm[4] = "\033="; /* cursor movement string */ char cl[4] = "\032"; /* clear screen string */ #else /* UNIX */ #include <sgtty.h> static int saveflags; static char cl[5], cm[20], bp[1024], name[20]; char PC, BC[5], UP[5]; #endif /* initialize the termimal mode */ terminit() { #ifdef UNIX struct sgttyb tty; char *p, *getenv(); if (p = getenv("TERM")) strcpy(name, p); else { fprintf(stderr, "TERM not set\n"); exit(1); } if (tgetent(bp, name) != 1) { fprintf(stderr, "Can't get termcap entry\n"); exit(1); } p = cm; tgetstr("cm", &p); p = cl; tgetstr("cl", &p); p = UP; tgetstr("up", &p); p = BC; tgetstr("bc", &p); gtty(0, &tty); saveflags = tty.sg_flags; tty.sg_flags |= RAW; tty.sg_flags &= ~(ECHO | XTABS); stty(0, &tty); #endif } /* reset the terminal mode */ termreset() { #ifdef UNIX struct sgttyb tty; gtty(0, &tty); tty.sg_flags = saveflags; stty(0, &tty); #endif } /* get a character from the terminal */ getch() { #ifdef AZTEC int ch; while ((ch = CPM(6, 0xff)) == 0) ; return ch; #else /* UNIX */ return getchar() & 0177; #endif } /* write a character */ putch(ch) int ch; { #ifdef AZTEC CPM(6, ch); #else /* UNIX */ putchar(ch); #endif } #ifdef AZTEC /* see if a character is ready to be read */ chready() { return CPM(11, 0); } #endif /* move cursor */ moveyx(ypos,xpos) int ypos,xpos; { #ifdef AZTEC printf("%s%c%c", cm, ypos+31, xpos+31); #else /* UNIX */ fputs(tgoto(cm, xpos - 1, ypos - 1), stdout); #endif } /* clear screen */ cls() { fputs(cl, stdout); } !EOF! echo x - vtrek.doc cat >vtrek.doc << '!EOF!' <<< Instructions for Star Trek >>> The galaxy is divided into a 8 X 8 quadrant grid, and each quadrant is further divided into a 8 X 8 sector grid. You will be assigned a starting point somewhere in the galaxy. Your mission : To seek out and destroy the fleet of Klingon warships which are menacing the Federation of Planets. You will have the following commands available to you as captain : 'D','E','W','Q','A','Z','X','C' , the keys around the 'S' on the keyboard control your direction. When you are asked for the direction, type one of these. Q W E \ | / \|/ A --S-- D /|\ / | \ Z X C 'H' , Hyper-space , used when you want to travel a large distance. The direction is set by typing one of the keys around the 'S'. The warp factor can be a number from 0-8. 'S' , Short range scan , tells you the direction and the distance that the Klingons are from you. Anytime that your Short range sensors are working, you will have a display of your quadrant on the screen. The following symbols are used on the display : <K> - Klingon <S> - Star Base (refuel/repair/re-arm here) * - star ? or (?) - you (? is the 1st letter of your ship name.) 'L' Long range scan. Shows conditions in space for one quadrant on each side of you (your in the middle of the scan). The scan prints out up to three digits for each quadrant. The one's digit is the number of stars, then tens digit is the number of star bases, and the hundred's digit is the number of Kilngons. EXAMPLE : 207 , 2 Klingons, 0 star bases, 7 stars 'P' Fire phasers. Allows you to destroy the Klingon warships by zapping them with suitable amounts of energy. 'T' Fire photon torpedo's. Torpedo course is selected by typing one of the keys around the 'S'. If the torpedo hits the Klingon, he will be destroyed. 'U' Defense control. Allows you to raise or lower your shields. The power to your shields drops as you are hit. If you are hit with your shields all the way down (0), you WILL be destroyed. When your shields up you will have paretheses around your ship. 'F' Fix devices. This allows you to repair damaged devices at a faster pace than normally. 'R' Redraw the screen. Impulse power can be used by typing one of the direction keys around the 'S'. This moves you the same distance as Hyper-space with a warp of 0.1. In the upper right of the screen is a damage report. If something is damaged it will have a negative number beside it. If an item is damaged, you won't be able to use it. !EOF! echo x - vtrek.h cat >vtrek.h << '!EOF!' /* vtrek.h -- header file for visual star trek */ #undef AZTEC /* Aztec C */ #define UNIX /* Unix */ #ifdef AZTEC #include "libc.h" #include "math.h" #endif #ifdef UNIX #include <stdio.h> #include <math.h> #include <ctype.h> #endif #define VTREKINS "vtrek.doc" /* instructions */ #define ERROR -1 #define PI 3.1415926 #define Toupper(x) (islower(x) ? toupper(x) : x) #define abs(x) (x < 0 ? -x : x) /* used for damaging klingon */ #define AUTOKILL 9999 /* used for fixing/damaging devices */ #define ABS 0 /* absolute fix */ #define REL 1 /* relative fix */ #define RND -1 /* pick a random device */ /* status of a ship */ #define ALIVE 0 /* ship is still here */ #define DEAD 1 /* ship has been destroyed */ /* used for replot calls */ #define TEXT 1 /* replot text portion */ #define INFO 2 /* replot information portion */ #define ELEMENT 4 /* replot individual element */ #define ALL (TEXT | INFO) /* replot all */ /* legal condition values */ #define GREEN 0 /* everything OK */ #define YELLOW 1 /* reason to be cautious */ #define RED 2 /* eminent danger */ #define DOCKED 3 /* docked at base (no danger) */ /* legal quadrant values (used in s.r.s) */ #define EMPTY 0 /* sector is empty */ #define KLINGON 1 /* sector contains klingon */ #define STARBASE 2 /* sector contains star base */ #define STAR 3 /* sector contains star */ #define PLAYER 4 /* sector contains player */ #define TBLAST 5 /* torpedo */ /* legal damage control indices */ #define WARP 0 /* warp drive */ #define SRS 1 /* short range sensors */ #define LRS 2 /* long range sensors */ #define PHASER 3 /* phaser control */ #define DAMAGE 4 /* damage control */ #define DEFENSE 5 /* defense control (shields) */ #define COMPUTER 6 /* computer (galaxy map, calculations) */ #define TUBES 7 /* torpedo tubes */ /* legal status items */ #define STARDATE 0 #define CONDITION 1 #define QUADRANT 2 #define SECTOR 3 #define ENERGY 4 #define TORPS 5 #define SHIELDS 6 /* used for readout calls */ #define CLEAR 0 /* clear readout */ #define ADDLINE 1 /* add line to readout */ /* sructure used to store quandrant information */ typedef struct { char nkling; /* number of klingons in quadrant */ char nbase; /* number of bases in quadrant */ char nstar; /* number of stars in quadrant */ char known; /* tells if info is known to player */ } QUADINFO; /* structure used to store klingon information */ struct { int xs, ys; /* sector coordinates */ int sh; /* shield level */ } klingon[3]; QUADINFO galaxy[8][8]; /* galaxy */ int numbases; /* number of bases in galaxy */ int numkling; /* number of klingons in galaxy */ int begkling; /* beginning number of klingons */ int condition; /* current condition (GREEN,YELLOW,RED,DOCKED) */ int xquad, yquad; /* current quadrant */ int xsect, ysect; /* current sector */ int old_xquad, old_yquad; /* quadrant before last movement */ int old_xsect, old_ysect; /* sector before last movement */ int energy; /* energy level */ int shields; /* shield level */ int torps; /* number of torps left */ int quadrant[8][8]; /* current quadrant picture (EMPTY,KLINGON,STARBASE,STAR,PLAYER) */ extern int rolines; /* number of lines used in current readout */ int damage[8]; /* % effectiveness of devices, normal range is 0-100 */ /* if < 0 then device is damaged beyond use */ extern char playership[]; /* image of player's ship for s.r.s */ char captain[11]; /* captain's name */ char shipname[11]; /* ship's name */ float stardate; /* current star date */ float lastdate; /* last star date before federation is conquered */ float begdate; /* beginning star date */ int base_xsect, base_ysect; /* starbase sector, if one is present */ int numkmove; /* number of klingon moves allowed */ int skill; /* skill level */ !EOF! exit 0