James T. Perkins · 22 September 1987
Hello everyone!
Here's a program which takes a subsector as input and produces a subsector map
as output. It uses the same line-by-line system file as gensec produces
(except gensec produces an entire sector, whereas mapsub only maps a single
sector).
If you use this program please tell me. I want to know if it is worth it
posting these things to the list.
_ ___
| | / _ \ James T. Perkins, [email removed], 629-1149
| |__ | |_| | Tektronix Logic Analyzers, DAS System Software, Display
|[address removed]
Killed processes never die... They just go to the big Bit Bicket in the sky.
P.S. for you VMS types out there, it should be easy to use a text editor to
seperate out the two files. If you have trouble with the shar archive
please contact me and I'll resend the files individually for you.
# This is a shell archive. Remove anything before this line, then
# unpack it by saving it in a file and typing "sh file". (Files
# unpacked will be owned by you and have default permissions.)
#
# This archive contains:
# mapsub.c subhex
echo x - mapsub.c
cat > "mapsub.c" << '//E*O*F mapsub.c//'
/*
* mapsub - produce a subsector hex-grid map from subsector data
*
* SYNOPSIS
* mapsub <Subsector.dat >Subsector.hex
*
* DESCRIPTION
* Mapsub processes the star system information on the standard input and
* produces a hex-grid map on the standard output. The format expected is
* very precise, consisting of one formatted line for each system, each
* exactly 59 bytes followed by a newline. Example:
*
* "0102 Gruenwald B775400-9 N TN NI TI GP"
*
* XXYY System_Name_______ UPP______ B Trade_Codes___ Al Z GP
*
* Where:
* XXYY is the system coordinates, in the range 0101-3240
* System_Name is the 18-character system name
* UPP is the Universal Planetary profile
* B is the base code: 'N' navy, 'S' scout, 'A' both
* Trade_Codes is up to fifteen characters worth of Trading codes,
* from this list: TN (Terran-Norm), TP (Terran-Prime), AG
* (Agricultural), NA (Non-AG), IN (Industrial), NI (Non-IN), RI
* (Rich), PO (Poor), WA (Water world), DE (Desert World), VA
* (Vacuum World), AS (Asteroid Belt), IC (Ice-capped), CA (Subsector
* Capitol)
* The only Trade_Code that does anything is CA, which causes
* "Capitol" to be written into the system's hex.
* Al is the system alignment. "IM" is the official alignment for the
* Imperium. I use "IN" for independent worlds.
* Z is the travel zone, either " " (Green), "A" (Amber), "R" (Red).
* G is the gas-giant-present flag, either " " (None), or "G" (exists).
* P is the planetoids-present flag, either " " (None), or "P" (exists).
*
* The output is an array of empty and filled hexes, which look like this:
* ______
* / XXYY \ XXYY - System coordinates
* / * S T \ * - Navy base, S - Starport class, T - Tech level
* / ^ O . \ ^ - Scout base, "O" "@" or "%" - Desert or Non-desert
* \ System / world or Asteroid belt, . - Gas giant
* \ Name /
* \Zone__/ Zone - blank for green or "amber" or "RED" or "Capitol"
*
* WARNING
* Mapsub assumes that the input is only one subsector's worth of worlds.
* if you give it a sector's worth of worlds (Example: "gensec | mapsub")
* it will print them all, overlapping many worlds!
*
* Ergo, if you want to generate worlds automatically, use gensec to
* produce a sector file of systems, then glean all the worlds belonging
* to a particular sector out of that file and put it in a subsector file,
* then use mapsub on the new subsector file.
*
* TO COMPILE
* On BSD systems, use: cc -O -s -o mapsub mapsub.c
* On SYSV systems, use: cc -O -DSYSV -s -o mapsub mapsub.c
*
* FILES
* Needs a blank hex map template, defined by default to be "./subhex".
* Change the MAP_TEMPLATE parameter to change this file's location.
*
* SEE ALSO
* gensec - the sector generator program (produces compatible format)
*
* AUTHOR
* James T. Perkins, [email removed], [email removed]
*
* BUGS
* The code is somewhat messy, as it was hacked out on a whim.
*
* As stated above, one cannot simply use the output of gensec as input
* to mapsub -- the gensec output must be edited.
*/
/*
Copyright 1987 James T. Perkins
This notice and any statement of authorship must be reproduced
on all copies. The author does not make any warranty expressed
or implied, or assumes any liability or responsiblity for the
use of this software.
Any distributor of copies of this software shall grant the
recipient permission for further redistribution as permitted
by this notice. Any distributor must distribute this software
without any fee or other monetary gains, unless expressed written
permission is granted by the author.
This software or its use shall not be: sold, rented, leased,
traded, or otherwise marketed without the expressed written
permission of the author.
If the software is modified in a manner creating derivative
copyrights, appropriate legends may be placed on derivative
work in addition to that set forth above.
Permission is hereby granted to copy, reproduce, redistribute or
otherwise use this software as long as the conditions above
are met.
All rights not granted by this notice are reserved.
*/
#define MAP_TEMPLATE "./subhex" /* empty hex grid file */
#include <stdio.h>
#include <strings.h>
#define mapxy(x, y, dx, dy) \
&map[(((y) - 1) % 10) * 6 + ((2 * ((x) / 2) == (x)) ? 1 : 4) + (dy)]\
[(((x) - 1) % 8) * 9 + 1 + (dx)]
/*
* Define SYSV if you are compiling on any machine that uses the string
* library functions strchr() and strrchr(). Do not define SYSV for BSD-like
* machines, which use index() and rindex().
*/
#ifdef SYSV
#define index strchr
#endif
char map[70][81]; /* in-memory copy of map that we operate on */
main(ac, av, envp)
int ac;
char *av[], *envp[];
{
char *center_name();
char system[81], name[19], upp[10], trade[16], align[3];
char base, zone, gas, belt;
char *s;
int n_lines = 0, x, y, i;
FILE *fp;
/*
* Read hex map template into memory
*/
if ((fp = fopen(MAP_TEMPLATE, "r")) == NULL)
{
fprintf(stderr, "%s: cannot open %s.\n", av[0], MAP_TEMPLATE);
exit(1);
}
while (!feof(fp))
{
fgets(map[n_lines++], 81, fp);
}
fclose(fp);
/*
* Start with empty, null-terminated strings
*/
bzero(name, sizeof(name));
bzero(upp, sizeof(upp));
bzero(trade, sizeof(trade));
bzero(align, sizeof(align));
/*
* Read in each system and place it on the map
*/
while (!feof(stdin))
{
fgets(system, sizeof(system), stdin);
sscanf(system,
"%2d%2d%*c%18c%*c%9c%*c%c%*c%15c%*c%2c%*c%c%*c%c%c\n",
&x, &y, name, upp, &base, trade, align,
&zone, &gas, &belt);
rem_trail_sp(name);
rem_trail_sp(trade);
/*
* write hex:
* ______
* &/ XXYY \ & is where the x, y offset is
* / * S T \
* / ^ @ . \
* \ System /
* \ Name /
* \______/
*/
overwrite(mapxy(x, y, 3, 0), system, 4);
overwrite(mapxy(x, y, 3, 1), ((base == 'N' || base == 'A') ?
"*" : " "), 1);
overwrite(mapxy(x, y, 5, 1), upp, 1);
overwrite(mapxy(x, y, 7, 1), &upp[8], 1);
overwrite(mapxy(x, y, 2, 2), ((base == 'S' || base == 'A') ?
"^" : " "), 1);
overwrite(mapxy(x, y, 4, 2), ((upp[1] == '0') ? "%" :
((upp[3] == '0') ? "O" : "@")), 1);
overwrite(mapxy(x, y, 6, 2), ((gas == 'G') ? "." : " "), 1);
s = center_name(name, x, y, 0, 3, 10);
if (*s)
{
(void)center_name(s + 1, x, y, 1, 4, 8);
}
switch (zone)
{
case 'A': /* Amber */
overwrite(mapxy(x, y, 2, 5), "amber", 5);
break;
case 'R': /* Red */
overwrite(mapxy(x, y, 2, 5), "RED", 3);
break;
}
s = trade;
while (s = index(s, 'C'))
{
if (strncmp(s, "CA", 2) == NULL)
{
overwrite(mapxy(x, y, 2, 5), "Capitol", 7);
break;
}
else
{
s++;
}
}
}
/*
* Write out finished map
*/
for (i = 0; i < n_lines; i++)
{
printf("%s", map[i]);
}
exit(0);
}
/*
* Remove all trailing spaces from the given null-terminated string
*/
rem_trail_sp(s)
char *s;
{
int i = strlen(s) - 1;
while (i >= 0 && s[i] == ' ')
{
s[i--] = '\0';
}
}
/*
* Overwrite memory, beginning at the given address, with the first n
* characters of the given string.
*/
overwrite(p, s, n)
char *p, *s;
int n;
{
while (n-- > 0)
{
*p++ = *s++;
}
}
/*
* Take the given name and try to place as many words as will fit in given
* width into the map at x, y, dx, dy. Also center each line of output in
* the width. Unfortunately, a word may be too long to fit, in which case
* place it anyway, overlapping.
*
* Returns 0 if it was able to place the entire name, or a pointer to the
* space just following the last word placed. Nasty kludges, beware,
*/
char *
center_name(name, x, y, dx, dy, width)
char *name;
int x, y, dx, dy, width;
{
char *end, *cur, *retval, *oldcur;
int offset;
cur = index(name, ' ');
if (cur == NULL)
{
end = name + strlen(name) - 1;
}
else
{
end = cur - 1;
oldcur = NULL;
while (cur && cur - name <= width && cur != oldcur)
{
end = cur - 1;
oldcur = cur;
cur = index(cur + 1, ' ');
if (cur == NULL)
{
cur = name + strlen(name);
}
}
}
offset = (width - (end - name + 1)) / 2;
dx = dx + offset;
overwrite(mapxy(x, y, dx, dy), name, end - name + 1);
if (index(end, ' '))
{
return end + 1;
}
else
{
return NULL;
}
}
//E*O*F mapsub.c//
echo x - subhex
cat > "subhex" << '//E*O*F subhex//'
______ ______ ______ ______
/ \ / \ / \ / \
/ \ / \ / \ / \
______/ \______/ \______/ \______/ \
/ \ / \ / \ / \ /
/ \ / \ / \ / \ /
/ \______/ \______/ \______/ \______/
\ / \ / \ / \ / \
\ / \ / \ / \ / \
\______/ \______/ \______/ \______/ \
/ \ / \ / \ / \ /
/ \ / \ / \ / \ /
/ \______/ \______/ \______/ \______/
\ / \ / \ / \ / \
\ / \ / \ / \ / \
\______/ \______/ \______/ \______/ \
/ \ / \ / \ / \ /
/ \ / \ / \ / \ /
/ \______/ \______/ \______/ \______/
\ / \ / \ / \ / \
\ / \ / \ / \ / \
\______/ \______/ \______/ \______/ \
/ \ / \ / \ / \ /
/ \ / \ / \ / \ /
/ \______/ \______/ \______/ \______/
\ / \ / \ / \ / \
\ / \ / \ / \ / \
\______/ \______/ \______/ \______/ \
/ \ / \ / \ / \ /
/ \ / \ / \ / \ /
/ \______/ \______/ \______/ \______/
\ / \ / \ / \ / \
\ / \ / \ / \ / \
\______/ \______/ \______/ \______/ \
/ \ / \ / \ / \ /
/ \ / \ / \ / \ /
/ \______/ \______/ \______/ \______/
\ / \ / \ / \ / \
\ / \ / \ / \ / \
\______/ \______/ \______/ \______/ \
/ \ / \ / \ / \ /
/ \ / \ / \ / \ /
/ \______/ \______/ \______/ \______/
\ / \ / \ / \ / \
\ / \ / \ / \ / \
\______/ \______/ \______/ \______/ \
/ \ / \ / \ / \ /
/ \ / \ / \ / \ /
/ \______/ \______/ \______/ \______/
\ / \ / \ / \ / \
\ / \ / \ / \ / \
\______/ \______/ \______/ \______/ \
/ \ / \ / \ / \ /
/ \ / \ / \ / \ /
/ \______/ \______/ \______/ \______/
\ / \ / \ / \ / \
\ / \ / \ / \ / \
\______/ \______/ \______/ \______/ \
/ \ / \ / \ / \ /
/ \ / \ / \ / \ /
/ \______/ \______/ \______/ \______/
\ / \ / \ / \ /
\ / \ / \ / \ /
\______/ \______/ \______/ \______/
//E*O*F subhex//
echo Possible errors detected by \'wc\' [hopefully none]:
temp=/tmp/shar$$
trap "rm -f $temp; exit" 0 1 2 3 15
cat > $temp <<\!!!
321 1462 8381 mapsub.c
64 482 4771 subhex
385 1944 13152 total
!!!
wc mapsub.c subhex | sed 's=[^ ]*/==' | diff -b $temp -
exit 0