knutson@ut-ngp.UUCP (Jim Knutson) (10/04/84)
There have been several requests for ve so here is an updated version of ve done here at the UT. This version will process ship, radar and coastwatch reports as well as the previous map, census, commodity and spy reports. Surveys have been fixed so they don't overflow. Checkpointed sectors are reported. Large maps no longer cause segment violations and other problems. You no longer are able to run into the edge of the world. The world map will wrap back on itself. This version also uses much less memory making forking the editor much faster. The editor commands now use the VISUAL and EDITOR environment variables. You may now fork a shell with the ! command (uses the SHELL environment variable). More commodity, census, etc. files may be read in without having to enter them on the command line. A Naval mode has been added to display navies and ship information. Tracing of routes for mov and nav commands may be shown on the screen using ^P. Be sure to strip the trailer. ------------------ Cut here ------------------- : Run this shell script with "sh" not "csh" PATH=:/bin:/usr/bin:/usr/ucb export PATH all=FALSE if [ $1x = -ax ]; then all=TRUE fi /bin/echo 'Extracting ve.6' sed 's/^X//' <<'//go.sysin dd *' >ve.6 X.ds v \fIve\fR X.ds V \fIVe\fR X.ds ]W "2nd Release" X.TH VE 6 10/3/84 X.SH NAME ve - visual empire X.SH SYNOPSIS ve [-a|c command_file] census map commodity spy ship radar coastwatch... X.SH DESCRIPTION \*V is a screen oriented empire(6) tool to aid in decision making and command file creation. It has been used by kings, presidents and petty dictators in many different countries and worlds with varying degrees of success. The program runs independently of empire and can thus be used as much and whenever you wish. X.sp \*V takes as input any number of empire commodity, census, map, spy, ship, radar and coastwatch reports, combines the information and displays a map on the screen and the census and commodity information for that sector at the bottom. As you move your cursor from one sector to the next the information at the bottom is updated. You can do surveys of the land, mark sectors and save commands in a separate command file to be executed later in empire. If the \fI\-a\fR option is used the \fIcommand_file\fR is appended to whereas the \fI\-c\fR option will create or truncate the file. X.sp The following are the commands that are understood (if not quite executed) by \*v. X.sp X.IP q Quit \*v. X.sp 2 X.IP "Entering information:" Many commands in \*v will prompt you for more information at the bottom ("last line") of the screen. The following characters have a special meaning when entering information. X.sp X.IP BS The backspace key will erase one character using a backspace-space-backspace sequence. X.IP @ The @ key will erase the entire line. X.IP ESC The ESCape key will move the cursor from the bottom line to its current map position, wait a second and then jump back. X.IP . The period will immediately expand to the x and y coordinates of the current sector. A `.' embedded into macros will get expanded when the macro is. X.IP ^P Proposed movements may be traced on the screen and allow you to verify moves and nav's by using the ^P command. X.IP backslash The backslash, `\\\' will cause the next character to be interpreted literally. This is how `.'s are embedded into macros and how one keeps a macro from expanding. X.IP macros Macros are a single character that will expand to a string as soon as they are entered. The commands to set and delete macros are described below. X.sp 2 X.IP "Movement and display functions:" The following commands control the movement of the cursor on the screen and the printing of the status lines and and display. X.IP "yugjbn" Move one sector in the specified direction. These are the same as in empire (up and left, up and right, left, right, down and left, down and right respectively). X.IP ^Y|^U Move/scroll up. X.IP ^B|^N Move/scroll down. X.IP ^G Move/scroll left. X.IP ^J Move/scroll right. X.IP l Leap to a specified sector. \*V will prompt for the x and y coordinates of the sector. X.IP P Toggle the printing of the status lines at the bottom of the screen (for slow baud rates). Normally \*v will update the status lines every time the cursor is moved, but with printing turned off, the status lines are only printed by the `p' command below. X.IP p Print the status lines for that sector. Only useful if printing has been toggled off. X.IP ^F Flip between the survey map and the designation maps. X.IP ^L Redraw the screen. X.sp X.IP "Marking the map:" The result of a `?' command is to mark sectors of the map. Sectors are marked using the \fIcurrent mark\fR character. This can be changed without affecting the screen allowing for multiple marks on the same screen. A sector is marked by placing the current mark character (default is `>') directly to the left of the sector. As an example of multiple marks, you can set the current mark to `^' and do the command "?civ>100" then set the mark to `v' and do "?civ<5" to get a visual representation of the high and low civilian population sectors. X.IP m Set the current mark character. X.IP M Reset the mark character to the default of `>'. X.IP c Clear the current marks on the screen. X.IP C Clear ALL of the marks on the screen. X.sp 2 X.IP "Command file:" The optional command file can be used to store notes or commands to later be executed by empire. \*V lets you append to the file, change or create it and edit it without exiting the program. X.IP a Append a line to the command file. X.IP O Create or change the current command file. If there is a current command file it is closed before the new file is opened. X.IP V Invoke the default visual editor (normally \fIvi(1)\fR) on the current command file. The shell variable VISUAL will be used if set. X.IP E Invoke the default line editor (normally \fIex(1)\fR) on the current command file. The shell variable EDITOR will be used if set. X.sp 2 X.IP "\*V Commands" X.IP ? This command will prompt you for an expression similar to that in empire (see Command Syntax in the empire manual). The effect of all `?' commands is to "mark" sectors that satisfy the requirements of the command. Unfortunately the command is not as robust as it is in empire. At most two commands (separated by `&') can be combined, not all of the items can be checked and the item name must be on the left while the value is on the right. X.sp Some allowed commands would be X.in +5 X.nf ?civ>100&mil<5 ?country=4 ?des=h&lcm<20 ?del=food&contract=mil X.fi X.in -5 The items that can be accessed are: X.in +5 X.ta 1.5i X.nf civ civilians mil military foo food sh shells gun guns pl planes iro iron dus gold dust bar gold bars oil oil lcm light construction material hcm heavy construction material eff efficiency mob mobility min mineral content gmi gold mineral content fer fertility pet petro content des designation cou country del delivery route X.fi X.in -5 Note that the above are the minimal abbreviations for the different items. X.IP I The I command allows more report files to be read in. This is useful when combined with the ! command to update your empire and look at the results without ever exiting \*V. X.IP ! The ! command forks a shell (honors the SHELL variable). The command file is flushed before forking to allow its use. X.sp 2 X.IP Macros: A macro is a single character that will be expanded immediately as typed it does not need to be space delimited. A `.' may be embedded into a macro and will be expanded at the time the macro is typed. For example, a C could be defined as "mov civ \\\.". Then whenever a C is typed it would expand to "mov civ x, y " where x,y are the coordinates of the current sector. X.IP s Set up a macro. Note that you must use a `\\\' to embed a `.' into a macro. X.IP d Delete a macro. X.sp 2 X.IP "Surveys of the land" It is possible to survey any appropriate item on the commodity or census list. A survey has a \fIrange\fR associated with it which describes the maximum value for the item being surveyed. When the survey is done each sector is replaced by a single digit from 0 to 9 which indicates which tenth of the range the value of that item occurred in. For values greater than the range capital letters are used up to `Z'. After that only a `$' is printed. The survey map is distinct from the designation map. You can flip between the two at any time by typing `^F'. For example, if the range is 100, the item being surveyed is civilians and the number of civilians in the sector is 25, a 2 will be displayed. X.IP S Perform a survey X.IP R Set up the range for surveys. X.sp 2 X.IP "Naval reports" Normally, your opponents navies as well as your own will not be displayed. The ship display may be turned on using the 'N' command. At this point, the flagship of each sector which contains a ship will be displayed in the sector in which they reside. Information about each ship in a sector may be obtained by moving your cursor over the top of the sector and paging through each ship with the '+', '-', and '/' keys. X.IP N Toggles the ship display mode. X.IP G Go to the sector of the specified ship. \*V will prompt for the ship number. X.IP + Display information on the next ship in the sector. Ships are ordered by their ship number. X.IP - Display information on the previous ship in the sector. X.IP / Display information on the flagship in that sector (ship with the lowest number). X.sp 2 X.IP "Moving along routes" You can walk along delivery routes by setting up the desired route with the `r' command and then typing the `w' command. The cursor will then move along the chosen delivery route. X.IP r Designate a current route. X.IP w Walk along the current route. X.SH AUTHORS Matthew Diaz and Michael Baldwin Modifications by Bill Jones, Jim Knutson, Ken Montgomery, Dan Reynolds X.SH "SEE ALSO" empire(6) X.SH BUGS Probably lots X.sp 1 The `?' command should be identical to that in empire. X.sp 1 Some contortions of radar scans may not work. X.sp 1 Surveys with ships may leave survey values on the designation map. X.sp 1 New ship reports don't replace the old values (read using the I command). X.sp 1 Command files that are removed in a forked shell will reappear. X.sp 1 The erase and line kill characters should be taken from the environment. //go.sysin dd * made=TRUE if [ $made = TRUE ]; then /bin/chmod 644 ve.6 /bin/echo -n ' '; /bin/ls -ld ve.6 fi /bin/echo 'Extracting ve.c' sed 's/^X//' <<'//go.sysin dd *' >ve.c X/* * ve - visual empire (with due respect to Peter Langston). * * Written by Matthew Diaz and Michael Baldwin * Modified by Bill Jones, Jim Knutson, Ken Montgomery and Dan Reynolds * * Usage: ve [-a|c] census commodity map ship spy radar coastwatch.... * * Compile using: cc -o ve ve.c -O -lcurses -ltermcap */ #include <ctype.h> #include <stdio.h> #include <curses.h> #include <signal.h> X/* Things you may want to change */ #define VIPATH "/usr/ucb/vi" #define EXPATH "/usr/ucb/ex" #define SHPATH "/bin/sh" #define TEMPFILE "/tmp/vetemp" #define MAPSIZE 128 /* Empire world size */ #define RADARSIZE 40 /* Radar scan size */ #define MAXSHIPS 1024 /* Maximum number of ships */ #define VALUESIZE 30 /* Number of values in sector */ #define DELSIZE 12 /* Number of deliveries per sector */ #define CNTSIZE 12 /* Number of contracts per sector */ #define NODISK -1 /* No disk address flag */ #define NOSHIPS -1 /* No ships present */ #define UNKNOWN -1 /* Unknown ship index flag */ #define MCOLS 79 /* Width of the map window */ #define MLINES 17 /* Height of the map window */ #define NOX 0 /* Expansion flags for getline */ #define EX 1 #define NOSU 0 /* Survey or no survey for mapdr */ #define SURV 1 #define ESC '\033' #define ODD(x) ((x)&01) #define EVEN(x) (!((x)&01)) #define MAX(A,B) ((A) > (B) ? (A) : (B)) #define MIN(A,B) ((A) < (B) ? (A) : (B)) #define VALID(x,y) (EVEN(x)&&EVEN(y)||ODD(x)&&ODD(y)) #define CTRL(c) (('c')-0100) X/* Offsets into sector arrays for various items */ #define CIV 0 #define MIL 1 #define FOOD 2 #define SH 3 #define GUN 4 #define PL 5 #define IRON 6 #define DUST 7 #define BAR 8 #define OIL 9 #define LCM 10 #define HCM 11 #define EFF 12 #define MOB 13 #define MIN 14 #define GMIN 15 #define FERT 16 #define PET 17 #define DES 18 #define COU 19 #define CONT 20 #define DEL 21 #define CHKPT 22 char usage[] = "Usage: ve [-c|a out] files..."; X/* * If you want accounting, change the filename below (make sure * it is 622 at least). Everytime someone plays that version * a line will be entered showing login name, elapsed time and * date. */ #ifdef ACCTNG char acct[] = "/u2/empire/veacct"; #endif X/* * Temporary file related variables */ char tfile[30]; /* temporary file name */ int temp = -1; /* temporary file descriptor */ X/* * Map sector data structures */ struct sector { char surv; /* Survey value */ char mark; /* Mark character */ char own; /* Do you own or know that sector? */ char des; /* Sector designation */ int shp; /* Index of current ship at x,y */ long int diskaddr; /* Disk address containing values */ } map[MAPSIZE][MAPSIZE]; struct shipentry { char des; /* Ship designation (type) */ int number; /* Ship number */ int x,y; /* Map coordinates of ship */ char fleet; /* Fleet designation */ long int diskaddr; /* Disk address containing values */ } ships[MAXSHIPS]; struct value { int val[VALUESIZE]; /* Values as described by items */ char del[DELSIZE]; /* Delivery routes */ char cnt[CNTSIZE]; /* Contracts */ } values; struct item { char *nm; /* Item name - prefix */ int len; /* Length of prefix (for strncmp) */ } items[] = { "civ", 3, "mil", 3, "foo", 3, "sh", 2, "gun", 3, "pl", 2, "iro", 3, "dus", 3, "bar", 3, "oil", 3, "lcm", 3, "hcm", 3, "eff", 3, "mob", 3, "min", 3, "gmi", 3, "fer", 3, "pet", 3, "des", 3, "cou", 3, "con", 3, "del", 3, "", 0 }; X/* * Vector of ship names */ char *shipnames[] = { "yacht", "tender", "minesweep", "destroyer", "submarine", "cargo ship", "battleship", "oil derrick", "patrol boat", "fishing boat", "heavy cruiser", "aircraft carr", "aircraft carrier", 0 }; /* shipnames */ X/* * ve input file function processors */ int census(); /* census file processor */ int readmap(); /* map file processor */ int commodities(); /* commodities file processor */ int spy(); /* spy report processor */ int radarscan(); /* naval radar scan processor */ int ship(); /* ship report processor */ int coastwatch(); /* coastwatch report processor */ struct funsw { /* list of prefixes and functions */ char *type; int (*func)(); } fsw[] = { "cen", census, "map", readmap, "com", commodities, "spy", spy, "rad", radarscan, "shi", ship, "coa", coastwatch, 0, 0, }; char macros[127][MCOLS]; /* Macro definitions */ char peekc; /* Lets you poke a character */ int startx = -50000; /* Leftmost x-coordinate of display window */ int starty = -50000; /* Uppermost y-coordinate of display window */ int minx; /* Min and max x (used for map reading) */ int maxx; int miny; int curmark = '>'; /* Current marking character */ int range = 10; /* Range for survey */ int curx, cury; /* Current x and y coordinates in map array */ int shipcount = 0; /* Total number of ships in ships array */ int shipmode = FALSE; /* True if in ship display mode */ int surmap = 0; /* Nonzero if survey map should be displayed */ int noise = TRUE; /* True if production messages to be printed */ FILE *inpf; /* Input file pointer */ char iname[BUFSIZ]; /* Input file name */ FILE *outf; /* Output file pointer */ char oname[BUFSIZ]; /* Output file name */ char buf[BUFSIZ]; /* Line buffer */ main(argc, argv) int argc; char *argv[]; { struct funsw *fp; /* Pointer to input file function processor */ #ifdef ACCTNG FILE *actf; /* Accounting file */ long sclock; long eclock; #endif if (argc == 1) puts(usage), exit(1); #ifdef ACCTNG time(&sclock); #endif opentf(); presetmap(); argv++; while (*argv) { /* Open/create command file */ if (**argv == '-' && (argv[0][1] == 'c'||argv[0][1] == 'a')) { if ((outf = fopen(*++argv, (argv[0][1] == 'c') ? "w" : "a")) == NULL) perror(*argv), exit(1); strcpy(oname, *argv++); continue; } /* if */ /* * Process empire report files. This is done by looking at * the second line of the file which contains a string of * the form: * * cen ... (e.g. cen # >cen.out) * * The first word indicates the type of file it is (census, * map, etc). */ if ((inpf = fopen(*argv, "r")) == NULL) perror(*argv), exit(1); if (fgets(buf, sizeof buf, inpf) == NULL || fgets(buf, sizeof buf, inpf) == NULL) { printf("%s: wrong format\n", *argv); exit(1); } for (fp = fsw; *fp->type; fp++) if (!strncmp(fp->type, buf, strlen(fp->type))) (fp->func)(inpf); fclose(inpf); argv++; } /* while */ if (map[offset(0)][offset(0)].own) center (0,0); else center (minx + MCOLS/2, miny + MLINES/2); startx = 0 - MCOLS/2 ; /* Set at Capitol */ if (ODD(startx)) startx--; starty = 0 - MLINES/2 ; if (ODD(starty)) starty--; signal(SIGINT, SIG_IGN); /* Ignore common signals */ signal(SIGQUIT, SIG_IGN); initscr(); /* Start up curses etc. */ presetty(); commands(); /* Process all commands */ move(LINES-1, 0); /* Done - move to bottom of screen */ clrtoeol(); refresh(); #ifdef ACCTNG /* Save accounting information */ if ((actf = fopen(acct, "a")) != NULL) { time(&eclock); if (!getpw(getuid(), buf) && (bp = index(buf, ':'))) *bp=0; else sprintf(buf, "%d", getuid()); eclock -= sclock; fprintf(actf, "%s\t%2d:%02d\t%s", buf, eclock/60, eclock % 60, ctime(&sclock)); fclose(actf); } #endif endtty(); /* Reset terminal characteristics */ } /* main */ X/* * Input file processing functions * * These routines parse the information from the input files, * many times in a very ugly way. * * Each routine checks to see if there is a comma in the 4th position. * This is to make certain that the line is of the form x,y and not * another message (e.g. Bad weather). */ X/* * census - Read and process census file. */ census(inpf) FILE *inpf; { register int x,y; register char *p; struct sector *mp; while (fgets(buf, sizeof buf, inpf) != NULL) { if (buf[3] != ',') { /* * Look for census lines of the form: * 'xxxxx yyy zzz in x,y' (reports of products produced) */ if (p = (char *)rindex(buf, ',')) { if (*++p == '-') p++; if (noise && *p >= '0' && *p <= '9') { fputs(buf, stderr); fflush(stderr); } /* if */ } /* if */ continue; } /* if */ x = atoi(buf); y = atoi(&buf[4]); mp = &map[offset(x)][offset(y)]; readvalues (offset(x),offset(y)); mp->own = 1; values.del[CIV] = buf[19]; values.del[MIL] = buf[20]; values.del[FOOD] = buf[21]; values.cnt[CIV] = buf[23]; values.cnt[MIL] = buf[24]; values.cnt[FOOD] = buf[25]; values.val[CHKPT] = buf[27]; values.val[COU] = -1; mp->des = (buf[8]=='-') ? '~' : ((buf[8]=='^') ? '&' : buf[8]); values.val[EFF] = atoi(&buf[10]); values.val[MOB] = atoi(&buf[15]); sscanf(&buf[29], "%d%d%d%d%d%d%d", &values.val[CIV], &values.val[MIL], &values.val[FOOD], &values.val[MIN], &values.val[GMIN], &values.val[FERT], &values.val[PET]); writevalues(offset(x),offset(y)); } /* while */ } /* census */ X/* * commodities - Read and process commodities file. */ commodities(inpf) FILE *inpf; { register int x,y; register char *p; struct sector *mp; while (fgets(buf, sizeof buf, inpf) != NULL) { if (buf[3] != ',') { /* * Look for census lines of the form: * 'xxxxx yyy zzz in x,y' (reports of products produced) */ if (p = (char *)rindex(buf, ',')) { if (*++p == '-') p++; if (noise && *p >= '0' && *p <= '9') { fputs(buf, stderr); fflush(stderr); } /* if */ } /* if */ continue; } /* if */ x = atoi(buf); y = atoi(&buf[4]); readvalues (x,y); mp = &map[offset(x)][offset(y)]; mp->own = 1; sscanf(&buf[14], "%c%c%c%c%c%c%c%c%c", &values.del[SH], &values.del[GUN], &values.del[PL], &values.del[IRON], &values.del[DUST], &values.del[BAR], &values.del[OIL], &values.del[LCM], &values.del[HCM]); sscanf(&buf[24], "%c%c%c%c%c%c%c%c%c", &values.cnt[SH], &values.cnt[GUN], &values.cnt[PL], &values.cnt[IRON], &values.cnt[DUST], &values.cnt[BAR], &values.cnt[OIL], &values.cnt[LCM], &values.cnt[HCM]); sscanf(&buf[34], "%d%d%d%d%d%d%d%d%d", &values.val[SH], &values.val[GUN], &values.val[PL], &values.val[IRON], &values.val[DUST], &values.val[BAR], &values.val[OIL], &values.val[LCM], &values.val[HCM]); writevalues(x,y); } /* while */ } /* commodities */ editradarscan(rm, xr, yr, xp, yp, rp) char rm[RADARSIZE][RADARSIZE]; int *yr, *xr; int *xp, *yp; float *rp; { register int x,y; register int xs,ys; register int mx,my; y = 10.0 * (*rp); if (((y%10) == 5) && *yp < 0) ys = (*yr)/2; else ys = (*yr+1)/2; xs = *xr/2; if (rm[xs][ys] == ' ') xs++; for (x = 0; x <= *xr; x++) for (y = 0; y <= *yr; y++) { switch(rm[x][y]) { case 'A': case 'B': case 'C': case 'D': case 'F': case 'H': case 'M': case 'O': case 'P': case 'S': case 'T': case 'Y': rm[x][y] = '$'; break; case '/': rm[x][y] = ' '; } /* switch */ merge(rm[x][y], (*xp-xs+x), (*yp-ys+y)); } /* for */ } /* editradarscan */ findshipname(inpf) FILE *inpf; { register char c, *sp; register int i; nomatch: c = getc(inpf); if (c == EOF) return(0); for (i = 0; sp = shipnames[i]; i++) { while (*sp) { if (c != *sp) { if (sp == shipnames[i]) goto next; if (skipword(inpf)) goto nomatch; return(0); } /* if */ c = getc(inpf); sp++; } /* while */ fscanf(inpf," %*d at "); return(1); next: continue; } /* for */ if (!(c == '-' || (c >= '0' && c <= '9'))) goto nomatch; ungetc (c, inpf); return(2); } /* findshipname */ X/* * getshiptype - Get ship type. */ getshiptype(bp) register char *bp; { register int i; register char *sp; for (i = 0; sp = shipnames[i]; i++) { if (!strncmp (sp, bp, strlen(sp))) return (shipnames[i][0] - 'a' + 'A'); } /* for */ return (FALSE); } /* getshiptype */ X/* * merge - Update sector designation. */ merge(uc, x, y) register char uc; register int x,y; { struct sector *mp; mp = &map[offset(x)][offset(y)]; switch(mp->des) { case '^': if (uc == '&') mp->des = uc; /* fall through */ case '\\': break; case '~': if (uc == '-') break; /* fall through */ case '&': if (uc == '^') break; /* fall through */ default: case '-': case '?': if (uc == ' ' || uc == '$' || uc == '?') break; /* fall through */ case 0: case ' ': if (uc == '$') mp->des = '.'; else mp->des = uc; break; } /* switch */ } /* merge */ presetradarmap(rm) char rm[RADARSIZE][RADARSIZE]; { register int x,y; for (x = 0; x < RADARSIZE; x++) for (y = 0; y < RADARSIZE; y++) rm[x][y] = ' '; } /* presetradarmap */ radarscan(inpf) FILE *inpf; { int xp, yp; float rp; int xr, yr; char radarmap[RADARSIZE][RADARSIZE]; while (findshipname(inpf)) { if (!readradarlines(inpf, &xp, &yp, &rp)) continue; if (rp < 0.6) continue; presetradarmap(radarmap); if (!readradarscan(inpf, radarmap, &xr, &yr)) continue; editradarscan(radarmap, &xr, &yr, &xp, &yp, &rp); } /* while */ } /* radarscan */ X/* * readmap - Read and process the map file. This is a real kludge where you * try to figure out where you are on the map by looking at the * coordinates along the edge of the map. */ readmap(inpf) FILE *inpf; { register int x,y; /* x,y map coordinates */ int sign; /* Sign of number being converted */ char minb[5]; /* Number buffers for min and max x */ char maxb[5]; char *sp = minb; char *lp = maxb; char *bp; fgets(buf, sizeof buf, inpf); /* Now determine the minimum x value */ *sp++ = buf[4]; *lp++ = buf[strlen(buf) - 2]; sign = (index(buf, '-')) ? -1 : 1; fgets(buf, sizeof buf, inpf); *sp++ = buf[4]; *lp++ = buf[strlen(buf) - 2]; *sp = 0; *lp = 0; minx = atoi(minb); maxx = atoi(maxb); if (sign == -1) { if (minx > 0) minx *= -1; } else { if (minx > maxx) { maxx *= -1; minx *= -1; } /* if */ } /* if */ fgets(buf, sizeof buf, inpf); miny = atoi(buf); for (y = miny; buf[2] != ' '; y++) { for (bp = &buf[4], x = minx; x <= maxx; x++, bp++) { merge (*bp, x, y); } /* for */ fgets(buf, sizeof buf, inpf); } /* for */ } /* readmap */ readradarlines(inpf, xp, yp, rp) FILE *inpf; int *xp, *yp; float *rp; { static char format[] = "%d,%d efficiency %*d%%, barometer at %*d, max range %f"; if (fscanf(inpf, format, xp, yp, rp) != 3) return(FALSE); pitchline(inpf); return(TRUE); } /* readradarlines */ readradarscan(inpf, rm, xr, yr) FILE *inpf; char rm[RADARSIZE][RADARSIZE]; int *xr, *yr; { register char c; register int x,y; register int blankline; register int leadingblanks; *xr = x = 0; *yr = y = 0; leadingblanks = TRUE; blankline = FALSE; while ((c = getc(inpf)) != EOF) { switch (c) { case '\n': if (!leadingblanks && blankline) return (*xr > 0 && --(*yr) > 0); if (!leadingblanks) if (++y >= RADARSIZE) return(FALSE); x--; *xr = MAX(*xr, x); *yr = MAX(*yr, y); blankline = TRUE; if (x > 0) { x = 0; continue; } /* if */ /* fall through */ default: if (x <= 0) { ungetc (c, inpf); (*yr)--; return (*xr > 0 && *yr > 0); } /* if */ blankline = FALSE; leadingblanks = FALSE; /* fall through */ case ' ': rm[x][y] = c; if(++x >= RADARSIZE) return(FALSE); } /* switch */ } /* while */ (*yr)--; return (*xr > 0 && *yr > 0); } /* readradarscan */ X/* * ship - Read and process ship reports. */ ship(inpf) FILE *inpf; { char des; register int number; register int i; struct sector *mp; struct shipentry *sp; while (fgets (buf, sizeof buf, inpf) != NULL) { if (buf[22] != ',') continue; if (!(des = getshiptype (&buf[5]))) continue; number = atoi (buf); if ((i = readship (UNKNOWN, number)) == NOSHIPS) { i = shipcount; if (++shipcount >= MAXSHIPS) { fputs ("Ship vector overflow!\n", stderr); fflush (stderr); exit(1); } /* if */ sp = &ships[i]; sp->des = des; sp->number = number; sp->x = atoi (&buf[19]); sp->y = atoi (&buf[23]); sp->fleet = buf[27]; values.val[COU] = -1; values.val[EFF] = atoi (&buf[29]); sscanf (&buf[34], "%d%d%d%d%d%d%d%d%d%d%d", &values.val[CIV], &values.val[MIL], &values.val[SH], &values.val[GUN], &values.val[PL], &values.val[IRON], &values.val[DUST], &values.val[BAR], &values.val[FOOD], &values.val[OIL], &values.val[MOB]); writeship (i, number); mp = &map[offset(sp->x)][offset(sp->y)]; if (mp->shp == NOSHIPS) mp->shp = i; mp->own = 1; } /* if */ } /* while */ } /* ship */ coastwatch(inpf) FILE *inpf; { char des; register int number; register int i; int j,cnum; struct sector *mp; struct shipentry *sp; while (fgets (buf, sizeof buf, inpf) != NULL) { for (i=0; buf[i] != ' '; i++) ; /* find country */ if (buf[++i] != '(' || buf[++i] != '#') continue; cnum = atoi(&buf[++i]); for ( ; buf[i] != ' '; i++) ; /* find ship type */ if (!(des = getshiptype (&buf[++i]))) continue; for ( ; buf[i] != '#'; i++) ; /* find ship number */ number = atoi (&buf[++i]); if ((j = readship (UNKNOWN, number)) == NOSHIPS) { j = shipcount; if (++shipcount >= MAXSHIPS) { fputs ("Ship vector overflow!\n", stderr); fflush (stderr); exit(1); } /* if */ sp = &ships[j]; sp->des = des; sp->number = number; for ( ; buf[i] != '@'; i++) ; /* find coordinates */ sp->x = atoi (&buf[++i]); sp->y = atoi (&buf[i+4]); sp->fleet = ' '; values.val[COU] = cnum; writeship (j, number); mp = &map[offset(sp->x)][offset(sp->y)]; if (mp->shp == NOSHIPS) mp->shp = j; mp->own = 1; } /* if */ } /* while */ } /* coastwatch */ X/* * spy - Read and process spy reports. */ spy(inpf) FILE *inpf; { register int x,y; struct sector *mp; register int i; while (fgets(buf, sizeof buf, inpf) != NULL) { if (buf[3] != ',') continue; x = atoi(buf); y = atoi(&buf[4]); mp = &map[offset(x)][offset(y)]; readvalues (x,y); if (mp->own && values.val[COU] == -1) continue; mp->own = 1; values.val[COU] = atoi(&buf[8]); if (buf[14] == 'N') goto noreport; /* Ignore "No report... */ merge (buf[11], x, y); values.val[DES] = buf[11]; values.val[EFF] = atoi(&buf[13]); sscanf(&buf[18], "%d%d%d%d%d%d%d", &values.val[CIV], &values.val[MIL], &values.val[SH], &values.val[GUN], &values.val[IRON], &values.val[PL], &values.val[FOOD]); noreport: values.val[CHKPT] = ' '; for (i = 0; i < DELSIZE; i++) values.del[i] = '.'; for (i = 0; i < CNTSIZE; i++) values.cnt[i] = '.'; writevalues(x,y); } /* while */ } /* spy */ X/* * censusinfo - Display census and commodities info for sector. */ censusinfo(x,y) register int x,y; { register struct sector *mp = &map[offset(x)][offset(y)]; register struct shipentry *sp; censusheader(shipmode && mp->shp != NOSHIPS); move(LINES-2, 0); clrtoeol(); move(LINES-4, 0); clrtoeol(); readvalues(x,y); printw("%3d,%-3d %c", x, y, mp->des ? mp->des : ' '); if (mp->own) { printw("%6d%%%4d %c%c%c %c%c%c %c %4d%4d%5d%5d%5d%5d%4d", values.val[EFF], values.val[MOB], values.del[CIV], values.del[MIL], values.del[FOOD], values.cnt[CIV], values.cnt[MIL], values.cnt[FOOD], values.val[CHKPT], values.val[CIV], values.val[MIL], values.val[FOOD], values.val[MIN], values.val[GMIN], values.val[FERT], values.val[PET]); move(LINES-2, 0); if (!shipmode || mp->shp == NOSHIPS) { if (values.val[COU] == -1) addstr (" "); else printw("%3d", values.val[COU]); if (values.del[SH]) printw(" %c%c%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c%c", values.del[SH], values.del[GUN], values.del[PL], values.del[IRON], values.del[DUST], values.del[BAR], values.del[OIL], values.del[LCM], values.del[HCM], values.cnt[SH], values.cnt[GUN], values.cnt[PL], values.cnt[IRON], values.cnt[DUST], values.cnt[BAR], values.cnt[OIL], values.cnt[LCM], values.cnt[HCM]); else addstr(" "); printw("%4d%5d%4d%5d%5d%5d%5d%5d%5d", values.val[SH], values.val[GUN], values.val[PL], values.val[IRON], values.val[DUST], values.val[BAR], values.val[OIL], values.val[LCM], values.val[HCM]); } else { sp = &ships[mp->shp]; readship(mp->shp, sp->number); if (values.val[COU] == -1) addstr (" "); else printw("%3d", values.val[COU]); printw(" %4d %c %3d,%-3d %c %3d%%%4d%4d", sp->number, sp->des, x, y, sp->fleet, values.val[EFF], values.val[CIV], values.val[MIL]); printw("%4d%4d%4d%4d%4d%4d%4d%4d%4d", values.val[SH], values.val[GUN], values.val[PL], values.val[IRON], values.val[DUST], values.val[BAR], values.val[FOOD], values.val[OIL], values.val[MOB]); } /* if */ } /* if */ } /* censusinfo */ X/* * censusheader - Display census header. */ censusheader(mode) register int mode; { move(LINES-5, 0); addstr(" sect des eff mob cmf cmf % * "); addstr(" civ mil food min gmin fert oil"); move(LINES-3, 0); clrtoeol(); if (!mode) { addstr("cou sgpidbolh sgpidbolh "); addstr("sh gun pl iron dust bar oil lcm hcm"); } else { addstr("cou # des x,y f "); addstr("eff civ mil sh gun pln irn dst gld food oil mu"); } /* if */ } /* censusheader */ X/* * center - Center display window about (x,y). */ center(x,y) register int x,y; { if (x - 10 < startx || x + 10 > startx + MCOLS || y - 4 < starty || y + 4 > starty + MLINES) { startx = x - MCOLS/2; starty = y - MLINES/2; } /* if */ return; } /* center */ X/* * clearmks - Clear sector marks. If 'all' flag is set, then ALL marks * cleared, otherwise just curmark marks are cleared. */ clearmks(all) int all; { register int x,y; for (y = 0; y < MAPSIZE; y++) for (x = 0; x < MAPSIZE; x++) if (all || map[x][y].mark == curmark) map[x][y].mark = 0; } /* clearmks */ X/* * closetf - close temporary file. */ closetf() { close(temp); } /* closetf */ X/* * commands - Process input commands. */ commands() { register char c; int x,y; /* Indexes into map array */ register int i; register struct item *ip; /* Pointer to current item */ int tx,ty; /* Temporary x,y */ int crou = -1; /* Current route */ int status; /* Fork status return */ int pflg = 1; /* Print census flag */ int update = 0; /* Set if screen update needed */ struct funsw *fp; /* Pointer to input file function process */ char *bp; char prbuf[BUFSIZ]; char *getenv(); if (map[offset(0)][offset(0)].own) center (x = 0, y = 0); else { x = minx + MCOLS/2 - ODD(minx + MCOLS/2); y = miny + MLINES/2 - ODD(miny + MLINES/2); center (x,y); } /* if */ mapdr(NOSU); /* Draw map, census header and census */ censusinfo(x,y); move(y-starty, x-startx); while (refresh(), ((c = getac()) != 'q')) { update = 0; /* Initialize variables for next command */ curx = x; cury = y; switch(c) { /* Movement commands */ case 'y': x--; y--; break; case 'u': x++; y--; break; case 'j': x += 2; break; case 'n': x++; y++; break; case 'b': x--; y++; break; case 'g': x -= 2; break; case CTRL(B): case CTRL(N): y += 6; break; case CTRL(Y): case CTRL(U): y -= 6; break; case CTRL(G): x -= 6; break; case CTRL(J): x += 6; break; case '\f': clear(); /* Redraw the screen */ mapdr(surmap); censusinfo(x,y); break; case '?': query(); /* Do query at bottom */ mapdr(surmap); censusinfo(x,y); break; case '!': /* Fork a shell */ if ((bp = getenv("SHELL")) == NULL) strcpy(prbuf, SHPATH); else strcpy(prbuf, bp); if (outf) fclose(outf); if (fork() == 0) { move(LINES-1, 0); clrtoeol(); refresh(); endtty(); execl(prbuf, prbuf, 0); } else wait(&status); presetty(); clear(); mapdr(surmap); censusinfo(x,y); if (outf) if ((outf = fopen(oname, "a")) == NULL) putline("Cannot reopen %s", oname); break; case '+': nextship(x,y); /* Advance to next ship */ update++; break; case '-': previousship(x,y); /* Back up to prev ship */ update++; break; case '/': firstship(x,y); /* Go to first ship */ update++; break; case 'C': case 'c': clearmks(c=='C'); /* Clear marks */ mapdr(surmap); break; case 'M': curmark = '>'; /* Reset mark */ break; case 'm': getline(buf,"mark: ",NOX); /* Change mark */ if (*buf) curmark = *buf; break; case 'G': locateship (&x,&y,surmap); /* Leap to ship */ update++; break; case 'P': pflg = (pflg == 0); /* Toggle census refresh */ move(LINES-1, 0); clrtoeol(); printw("Printing %s", pflg ? "on" : "off"); break; case 'N': /* Toggle ship display */ shipmode = (shipmode == FALSE); mapdr(surmap); censusinfo(x,y); break; case 'a': if (outf) { /* Append to the file */ getline(buf, "", EX); x = curx; y = cury; if (*buf) { strcat(buf, "\n"); fputs(buf, outf); } /* if */ } else putline("No output file specified - use O"); break; case 'i': /* Read in input data (map,...) */ case 'I': getline(buf, "New input file: ", NOX); if ((inpf = fopen(buf, "r")) == NULL) { putline("%s: cannot open", buf); break; } strcpy(iname, buf); if (fgets(buf, sizeof buf, inpf) == NULL || fgets(buf, sizeof buf, inpf) == NULL) { putline("%s: wrong format\n", iname); break; } noise = FALSE; /* don't report production */ for (fp = fsw; *fp->type; fp++) if (!strncmp(fp->type, buf, strlen(fp->type))) (fp->func)(inpf); noise = TRUE; fclose(inpf); mapdr(surmap); censusinfo(x,y); break; case 'o': /* Change/create output file */ case 'O': getline(buf, "New output file: ", NOX); if (outf) fclose(outf); if ((outf = fopen(buf, "a")) == NULL) putline("%s: cannot create", buf); else strcpy(oname, buf); break; case 's': /* Set a macro */ getline(buf, "macro name: ", NOX); getline(prbuf, "define: ", NOX); strcopy(prbuf,macros[*buf]); break; case 'd': /* Delete a macro */ getline(buf, "delete macro: ", NOX); *macros[*buf] = 0; break; case 'V': if ((bp = getenv("VISUAL")) == NULL) strcpy(prbuf, VIPATH); else strcpy(prbuf, bp); goto forkeditor; case 'E': if ((bp = getenv("EDITOR")) == NULL) strcpy(prbuf, EXPATH); else strcpy(prbuf, bp); forkeditor: if (outf) { fclose(outf); move(LINES-1, 0); clrtoeol(); refresh(); if (fork() == 0) { endtty(); execl(prbuf, prbuf, oname, 0); } else wait(&status); presetty(); clear(); mapdr(surmap); censusinfo(x,y); if ((outf = fopen(oname, "a")) == NULL) putline("Cannot reopen %s", oname); } else putline("No output file"); break; case 'S': /* Survey */ getline(buf, "Survey: ", NOX); survey(buf); mapdr(surmap = SURV); break; case 'R': /* Range for Survey */ sprintf(prbuf, "Range (%d): ", range*10); getline(buf, prbuf, NOX); if (*buf) { range = atoi(buf)/10; if (range < 1) { putline("range should be >= 10"); range = 10; } /* if */ } /* if */ break; case CTRL(F): /* Flip maps */ mapdr((surmap = (surmap == NOSU))); break; case 'r': /* Trace route */ getline(buf, "Route: "); for (crou = -1, ip = items; ip->len; ip++) if (!strncmp(buf, ip->nm, ip->len)) crou = ip - items; if (crou < 0) putline("I don't know about %s", buf); break; case 'w': /* Walk along route */ readvalues (x,y); if (crou > -1 && values.del[crou] != '.') peekc = values.del[crou]; break; case 'p': break; /* Print census */ case 'l': getline(buf, "Leap to: "); if (*buf && (bp = (char *)index(buf, ','))) { tx = atoi(buf) ; ty = atoi(++bp); if (!VALID(tx, ty)) { tx -= ODD(tx); ty -= ODD(ty); } /* if */ x = tx; y = ty; center(x,y); update++; } /* if */ break; } /* switch */ if (x < startx || x > startx+MCOLS) { startx = (x < startx) ? x : x-MCOLS; update++; } /* if */ if (y < starty || y > starty+MLINES) { starty = (y < starty) ? y : y-MLINES; update++; } /* if */ if (update) { mapdr(surmap); censusinfo(x,y); touchwin(stdscr); } else { if (pflg || c == 'p') censusinfo(x,y); } /* if */ move(y-starty, x-startx); } /* while */ } /* commands */ X/* * endtty - Restore terminal to normal mode. */ endtty() { nl(); echo(); crmode(); endwin(); closetf(); } /* endtty */ X/* * findblank - Find next blank character. */ char *findblank(addr) register char *addr; { while ((*addr != 0) && (*addr != ' ')) addr++; return (addr); } /* findblank */ X/* * findchar - Find next non-blank character. */ char *findchar(addr) char *addr; { while ((*addr != 0) && (*addr == ' ')) addr++; return (addr); } /* findchar */ X/* * findship - Find ship or first ship of fleet. */ findship(ship,fleet) register int ship; register char fleet; { register int i; if (ship == UNKNOWN) { for (i = 0; i < shipcount; i++) if (ships[i].fleet == fleet) { ship = ships[i].number; break; } /* if */ } /* if */ if (ship == UNKNOWN) return (NOSHIPS); return (readship (UNKNOWN, ship)); } /* findship */ X/* * firstship - Locate first ship at x,y. */ firstship(x,y) int x,y; { register int mx,my; register int i; struct sector *mp; struct shipentry *sp; if (!shipmode) return; mx = offset(x); my = offset(y); mp = &map[mx][my]; if (mp->shp == NOSHIPS) return; for (i = 0; i < shipcount; i++) { sp = &ships[i]; if (offset (sp->x) == mx && offset(sp->y) == my) { mp->shp = i; return; } /* if */ } /* for */ } /* firstship */ X/* * getac - Get a character. Return peekc if non-zero, * otherwise read a character from the keyboard. */ getac() { register char tc; if (peekc) { tc = peekc; peekc = 0; return(tc); } else return(getch()); } /* getac */ X/* * getline - Get input line from the bottom of the screen, * using pr as a prompt if non-zero. If ex is set, * then expand macros. */ getline(bp, pr, ex) char *bp; char *pr; int ex; { register int x,y; register char c; char *mp; char *np; char nbuf[10]; /* Number buffer */ char processmove(); char *ip = bp; move(LINES-1, 0); clrtoeol(); if (*pr) addstr(pr); while (refresh(), (c = getch()) != '\r') { if (ex && *macros[c]) { /* check for macros */ mp = macros[c]; while (*mp) { if (*mp == '.') { /* expand . */ mp++; sprintf(np = nbuf, "%d,%d ", curx, cury); while (*ip++ = *np++); ip--; addstr(nbuf); } else { addch( *ip++ = *mp++); } /* if */ } /* while */ continue; } /* if */ switch(c) { case '\b': if (ip > bp) { /* backspace */ ip--; *ip = 0; addstr("\b \b"); } /* if */ continue; case '\\': addstr("\\\b"); /* backslash */ refresh(); c = getch(); break; case '.': if (ex) { /* expand . */ sprintf(np = nbuf, "%d,%d ", curx, cury); while (*ip++ = *np++); ip--; *ip = 0; addstr(nbuf); continue; } else break; case ESC: getyx(stdscr,y,x); /* jump to current x,y */ move(cury-starty, curx-startx); refresh(); sleep(1); move(y, x); continue; case '\n': continue; case CTRL(P): if (ex) c = processmove (bp, &ip); if (c > ' ') break; continue; case '@': move(LINES-1, 0); /* erase the line */ if (*pr) addstr(pr); clrtoeol(); *(ip = bp) = 0; continue; } /* switch */ addch(*ip++ = c); *ip = 0; } /* while */ *ip = 0; } /* getline */ X/* * getnewxy - Get last postion of MOVE or NAV command. */ getnewxy(bp,x,y) char *bp; int *x,*y; { register char *ip = bp; char *findblank(); char *findchar(); char fleet; char xbuf[6]; char ybuf[6]; int oldy,oldx; int shipnumber; register int i; switch(*ip) { case 'm': if (index(ip,'mov') == 0) return(0); if (*(ip = findblank(ip)) == 0) return(0); if (*(ip = findchar (ip)) == 0) return(0); if (*(ip = findblank(ip)) == 0) return(0); if (*(ip = findchar (ip)) == 0) return(0); for (i = 0; (i < 5) && (*ip != ',') && (*ip != 0); i++) { xbuf[i] = *ip++; xbuf[i+1] = 0; } /* for */ if ((*ip != ',') || (*ip == 0)) return(0); ip++; for (i = 0; (i < 5) && (*ip != ' ') && (*ip != 0); i++) { ybuf[i] = *ip++; ybuf[i+1] = 0; } /* for */ if ((*ip != ' ') || (*ip == 0)) return(0); *x = atoi(xbuf); *y = atoi(ybuf); if (*(ip = findchar(ip)) == 0) return(0); if (*(ip = findblank(ip)) == 0) return(0); if (*(ip = findchar(ip)) == 0) return(1); break; case 'n': if (index(ip,'nav') == 0) return(0); if (*(ip = findblank(ip)) == 0 ) return (0); if (*(ip = findchar (ip)) == 0 ) return (0); shipnumber = UNKNOWN; fleet = *ip; if ((fleet >= '0') && (fleet <= '9')) { for (i = 0; (i <5 ) && (*ip != '/') && (*ip != ' ') && (*ip != 0); i++) { xbuf[i] = *ip++; xbuf[i+1] = 0; } /* for */ shipnumber = atoi(xbuf); } /* if */ if ((i = findship(shipnumber,fleet)) == NOSHIPS) return(0); *x = ships[i].x; *y = ships[i].y; if (*ip != ' ') ip = findblank(ip); if (*ip == 0) return(0); shipmode = TRUE; map[offset(*x)][offset(*y)].shp = i; getyx(stdscr,oldy,oldx); curx = *x; cury = *y; center(curx,cury); mapdr(surmap); touchwin(stdscr); censusinfo(curx,cury); move(oldy,oldx); if (*(ip = findchar(ip)) == 0) return(1); break; default: return(0); } /* switch */ while (*ip != 0) { switch(*ip) { case 'y': (*x)--; (*y)--; break; case 'u': (*x)++; (*y)--; break; case 'j': *x += 2; break; case 'n': (*x)++; (*y)++; break; case 'b': (*x)--; (*y)++; break; case 'g': *x -= 2; break; default: return(0); } /* switch */ ip++; } /* while */ return(1); } /* getnewxy */ X/* * locateship - Locate arbitrary ship and move display window. */ locateship(sx,sy,sflg) register int *sx,*sy; int sflg; { register int number; register int i; char fleet; getline (buf, "Ship number: ", NOX); if (*buf) { fleet = buf[0]; if (fleet >= '0' && fleet <= '9') number = atoi (buf); else number = UNKNOWN; if ((i = findship (number, fleet)) == NOSHIPS) { putline("No info on ship"); return; } /* if */ *sx = ships[i].x; *sy = ships[i].y; center(*sx,*sy); map[offset(*sx)][offset(*sy)].shp = i; if (!shipmode) { shipmode = TRUE; mapdr(sflg); } /* if */ censusinfo(*sx,*sy); return; } /* if */ } /* locateship */ X/* * mapdr - Display map. */ mapdr(sflg) register int sflg; { register int x,y; register char des; register struct sector *mp; for (y = starty; y <= starty + MLINES; y++) for (x = startx; x <= startx + MCOLS; x++) { mvaddch(y-starty, x-startx, ' '); if (!VALID(x, y)) continue; mp = &map[offset(x)][offset(y)]; if (shipmode && mp->shp != NOSHIPS) des = ships[mp->shp].des; else if (sflg && mp->surv) des = mp->surv; else des = mp->des; mvaddch(y-starty, x-startx-1, (mp->mark)?mp->mark:' '); if (des) mvaddch(y-starty, x-startx, des); } /* for */ } /* mapdr */ X/* * mark - Mark map according to command. */ mark(sp, pass) char *sp; int pass; { register int itm1; register int itm2; register int x,y; register int num; register int val; register int markit; register struct item *ip; register struct item *tp; char cmd[20]; char *cp = cmd; struct sector *mp; while (isalpha(*cp++ = *sp++)); /* get first word */ *--cp = 0; if (!*--sp) return; for (ip = items; ip->len; ip++) /* check it */ if (!strncmp(cmd, ip->nm, ip->len)) break; if (!ip->len) { putline("I don't know about %s\n", cmd); return; } /* if */ itm1 = ip - items; /* * At this point, cmd contains the left side, *sp * is the operator and sp+1 is the right side. */ num = (itm1 == DES) ? *(sp+1) : atoi(sp+1); if (itm1 == CONT || itm1 == DEL) { for (tp = items; tp->len; tp++) if (!strncmp(sp+1, tp->nm, tp->len)) break; if (!tp->len) { putline("I don't know about %s", cmd); return; } /* if */ itm2 = tp - items; } /* if */ for (y = 0; y < MAPSIZE; y++) for (x = 0; x < MAPSIZE; x++) { mp = &map[x][y]; if (!VALID(x, y) || !mp->own || mp->des == '.') continue; readvalues (x,y); if (values.val[COU] != -1) continue; markit = 0; val = values.val[itm1]; if (itm1 == CONT) { num = '$'; val = values.cnt[itm2]; } else { if (itm1 == DEL) { num = '.'; /* KLUDGE */ *sp = '#'; val = values.del[itm2]; } /* if */ } /* if */ switch( *sp) { case '=': if (val == num) markit++; break; case '#': if (val != num) markit++; break; case '>': if (val > num) markit++; break; case '<': if (val < num) markit++; break; } /* switch */ if (markit && (!pass || (pass && mp->mark))) mp->mark = curmark; else if (mp->mark == curmark) mp->mark = 0; } /* for */ } /* mark */ X/* * nextship - Advance ship index to next ship at x,y. */ nextship(x,y) int x,y; { register int mx,my; register int i; struct sector *mp; struct shipentry *sp; if (!shipmode) return; mx = offset(x); my = offset(y); mp = &map[mx][my]; if (mp->shp == NOSHIPS) return; for (i = mp->shp+1; i < shipcount; i++) { sp = &ships[i]; if (offset(sp->x) == mx && offset(sp->y) == my) { mp->shp = i; return; } /* if */ } /* for */ for (i = 0; i < mp->shp; i++) { sp = &ships[i]; if (offset(sp->x) == mx && offset(sp->y) == my) { mp->shp = i; readship (i, sp->number); return; } /* if */ } /* for */ } /* nextship */ X/* * offset - Return transformed coordinate. */ offset(coordinate) int coordinate; { register int modulo; modulo = coordinate%MAPSIZE; return (modulo < 0 ? modulo+MAPSIZE : modulo); } /* offset */ X/* * opentf - open temporary file. */ opentf() { sprintf(tfile, "%s%d", TEMPFILE, getpid()); temp = creat(tfile, 0600); if (temp < 0) { write(2, "can't create temp file\n", 23); exit(1); } /* if */ /* * Re-open tfile in read/write mode. This shouldn't be * necessary. It wouldn't be if some blooming idiot hadn't * made creat() and open() be two different system calls. * (At very least creat() should be able to return a file * descriptor which can be used both to read and to write.) */ close(temp); temp = open(tfile, 2); if (temp < 0) { unlink(tfile); write(2, "can't open temp file\n", 22); exit(1); } /* if */ unlink(tfile); } /* opentf */ pitchline(inpf) FILE *inpf; { register int c; while ((c = getc(inpf)) != '\n') if (c == EOF) break; } /* pitchline */ X/* * presetmap - Preset map array. */ presetmap() { register int x,y; register int i; struct shipentry *sp; for (y = 0; y < MAPSIZE ; y++) for (x = 0; x < MAPSIZE ; x++) { map[x][y].des = 0; map[x][y].own = 0; map[x][y].shp = NOSHIPS; map[x][y].diskaddr = NODISK; } /* for */ for (i = 0; i < MAXSHIPS; i++) { sp = &ships[i]; sp->des = 0; sp->number = UNKNOWN; sp->diskaddr = NODISK; } /* for */ } /* presetmap */ X/* * presetty - Set up terminal for display mode. */ presetty() { crmode(); noecho(); nonl(); } /* presetty /* X/* * previousship - Back up to previous ship at x,y. */ previousship(x,y) int x,y; { register int mx,my; register int i; struct sector *mp; struct shipentry *sp; if (!shipmode) return; mx = offset(x); my = offset(y); mp = &map[mx][my]; if (mp->shp == NOSHIPS) return; for (i = mp->shp-1; i >= 0; i--) { sp = &ships[i]; if (offset(sp->x) == mx && offset(sp->y) == my) { mp->shp = i; return; } /* if */ } /* for */ for (i = shipcount-1; i > mp->shp; i--) { sp = &ships[i]; if (offset(sp->x) == mx && offset(sp->y) == my) { mp->shp = i; readship (i, sp->number); return; } /* if */ } /* for */ } /* previousship */ X/* * processmove - process MOVE or NAV command. */ char processmove(bp,ip) char *bp; char **ip; { register char c; int x,y; int oldx,oldy; if (getnewxy(bp,&x,&y) == 0) return(0); getyx(stdscr,oldy,oldx); updatescreen(x,y); while (refresh(),(c = getch()) != -1 ) { switch (c) { case 'y': x--; y--; break; case 'u': x++; y--; break; case 'j': x += 2; break; case 'n': x++; y++; break; case 'b': x--; y++; break; case 'g': x -= 2; break; default: updatescreen(curx,cury); move(oldy,oldx); refresh(); return(c); } /* switch */ move(oldy,oldx); **ip = c; (*ip)++; **ip = 0; addch(c); oldx++; updatescreen(x,y); } /* while */ } /* processmove */ X/* * putline - Do a printw at the bottom of the screen. */ putline(fmt, a1, a2, a3, a4) { move(LINES-1, 0); printw(fmt, a1, a2, a3, a4); } /* putline */ X/* * query - Parse ? command. */ query() { register int pass = 0; char *bp = buf; char *tp; getline(bp, "?", NOX); if (!*bp) return; clearmks(0); for (;;) { if (tp = (char *)index(bp, '&')) { *tp++ = 0; mark(bp, pass); bp = tp; } else { mark(bp, pass); break; } /* if */ pass++; } /* for */ } /* query */ X/* * readship - Read ship values from temporary file. */ readship(ix, number) register int ix; /* Index into ship vector if known */ register int number; /* Ship number (used if index unknown) */ { register int i; for (i = 0; i < VALUESIZE; i++) values.val[i] = 0; for (i = 0; i < DELSIZE; i++) values.del[i] = 0; for (i = 0; i < CNTSIZE; i++) values.cnt[i] = 0; if ((i = ix) == UNKNOWN) { for (i = 0; i < shipcount; i++) if (ships[i].number == number) goto match; return (NOSHIPS); } /* if */ match: if (ships[i].diskaddr == NODISK) return (i); lseek (temp, ships[i].diskaddr, 0); read (temp, &values, sizeof (struct value)); return (i); } /* readship */ X/* * readvalues - Read sector values from temporary file. */ readvalues (x,y) int x,y; { register int xt,yt; register int i; xt = offset(x); yt = offset(y); if (map[xt][yt].diskaddr == NODISK) { for (i = 0; i < VALUESIZE; i++) values.val[i] = 0; for (i = 0; i < DELSIZE; i++) values.del[i] = 0; for (i = 0; i < CNTSIZE; i++) values.cnt[i] = 0; return; } /* if */ lseek(temp,map[xt][yt].diskaddr,0); read(temp,&values,sizeof (struct value)); } /* readvalues */ skipword(inpf) FILE *inpf; { register char c; for (;;) { c = getc(inpf); if (c == '\n' || c == ' ' || c == '\t') return(1); if (c == EOF) return(0); } /* for */ } /* skipword */ X/* * strcopy - copy string. */ strcopy (str,dst) register char *str,*dst; { while(*dst++ = *str++ ); } X/* * survey - Display survey info for a given item. */ survey(sp) char *sp; { register struct item *ip; register int itm; register int x,y; register struct sector *mp; register int surval; for (ip = items; ip->len; ip++) if (!strncmp(sp, ip->nm, ip->len)) break; if (!ip->len) { putline("I don't know about %s", sp); return; } /* if */ itm = ip - items; for (y = 0; y < MAPSIZE; y++) for (x = 0; x < MAPSIZE; x++) { mp = &map[x][y]; if (mp->own && mp->des != '.') { readvalues (x,y); surval = values.val[itm]/range; if (surval > 35) mp->surv = '$'; else { mp->surv = surval; mp->surv += (mp->surv > 9) ? ('A'-10) : '0'; } /* if */ } /* if */ } /* for */ } /* survey */ X/* * updatescreen - Update screen if display window moved. */ updatescreen(x,y) register int x,y; { register int update = 0; if (x < startx || x > startx + MCOLS) { startx = (x < startx) ? x : x - MCOLS; update++; } /* if */ if (y < starty || y > starty + MLINES) { starty = (y < starty) ? y : y - MLINES; update++; } /* if */ if (update) { mapdr(surmap); touchwin(stdscr); } /* if */ censusinfo(x,y); move(y-starty,x-startx); refresh(); } /* updatescreen */ X/* * writeship - Write ship values to temporary file. */ writeship(ix, number) register int ix; /* Index into ship vector if known */ register int number; /* Ship number (used if index unknown) */ { register int i; long tell(); if ((i = ix) == UNKNOWN) { for (i = 0; i < shipcount; i++) if (ships[i].number == number) goto match; return (NOSHIPS); } /* if */ match: if (ships[i].diskaddr == NODISK) { lseek (temp, 0L, 2); ships[i].diskaddr = tell (temp); } else lseek (temp, ships[i].diskaddr, 0); write (temp, &values, sizeof (struct value)); return (i); } /* writeship */ X/* * writevalues - write sector values to temporary file. */ writevalues(x,y) int x,y; { register int xt,yt; long tell(); xt = offset(x); yt = offset(y); if(map[xt][yt].diskaddr == NODISK) { lseek(temp,0L,2); map[xt][yt].diskaddr = tell(temp); } else lseek(temp,map[xt][yt].diskaddr,0); write(temp,&values,sizeof (struct value)); } /* writevalues */ //go.sysin dd * made=TRUE if [ $made = TRUE ]; then /bin/chmod 640 ve.c /bin/echo -n ' '; /bin/ls -ld ve.c fi