[comp.sources.games] v01i086: xconq - multiplayer strategy game for X-windows, Part06/07

games-request@tekred.UUCP (07/10/87)

Submitted by: "Stanley T. Shebs" <shebs%orion@cs.utah.edu>
Comp.sources.games: Volume 1, Issue 86
Archive-name: xconq/Part06


#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 6 (of 7)."
# Contents:  bitmaps.h greek.u init.c input.c output.c side.c util.c
# Wrapped by billr@tekred on Thu Jul  9 17:45:50 1987
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f bitmaps.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"bitmaps.h\"
else
echo shar: Extracting \"bitmaps.h\" \(2639 characters\)
sed "s/^X//" >bitmaps.h <<'END_OF_bitmaps.h'
X/* Copyright (c) 1987  Stanley T. Shebs, University of Utah. */
X/* This program may be used, copied, modified, and redistributed freely */
X/* for noncommercial purposes, so long as this notice remains intact. */
X
X/* RCS $Header: bitmaps.h,v 1.5 87/06/06 20:04:13 shebs Exp $ */
X
X#define cmask_width 16
X#define cmask_height 16
Xstatic short cmask_bits[] = {
X   0xffff, 0x8001, 0xbffd, 0xa005,
X   0xa005, 0xa005, 0xa005, 0xa005,
X   0xa005, 0xa005, 0xa005, 0xa005,
X   0xa005, 0xbffd, 0x8001, 0xffff};
X
X#define ccurs_width 16
X#define ccurs_height 16
Xstatic short ccurs_bits[] = {
X   0x0000, 0x7ffe, 0x4002, 0x4002,
X   0x4002, 0x4002, 0x4002, 0x4002,
X   0x4002, 0x4002, 0x4002, 0x4002,
X   0x4002, 0x4002, 0x7ffe, 0x0000};
X
X#define mcurs_width 16
X#define mcurs_height 16
Xstatic short mcurs_bits[] = {
X   0x03e0, 0x0c98, 0x1084, 0x2082,
X   0x2082, 0x4081, 0x4081, 0x7fff,
X   0x4081, 0x4081, 0x2082, 0x2082,
X   0x1084, 0x0c98, 0x03e0, 0x0000};
X
X#define mmask_width 16
X#define mmask_height 16
Xstatic short mmask_bits[] = {
X   0x03e0, 0x0fd8, 0x19b4, 0x218a,
X   0x6186, 0x4185, 0xc183, 0xffff,
X   0xffff, 0xc183, 0xa182, 0x6186,
X   0x5184, 0x2d98, 0x1bf0, 0x07c0};
X
X#define dots_width 6
X#define dots_height 6
Xstatic short dots_bits[] = {
X   0x0001, 0x0000, 0x0000, 0x0008,
X   0x0000, 0x0000};
X
X#define bomb1_width 16
X#define bomb1_height 16
Xstatic short bomb1_bits[] = {
X   0x0000, 0x0000, 0x0000, 0x0000,
X   0x0000, 0x0000, 0x0380, 0x07e0,
X   0x0ff0, 0x0ff0, 0x0ff8, 0x1ff8,
X   0x1ff8, 0x0ff0, 0x0000, 0x0000};
X
X#define bomb2_width 24
X#define bomb2_height 24
Xstatic short bomb2_bits[] = {
X   0x0000, 0x0000, 0x0000, 0x0000,
X   0x0000, 0x0000, 0x0000, 0x0000,
X   0x0000, 0x0000, 0x3c00, 0x005a,
X   0xff80, 0x0024, 0xffdc, 0x000d,
X   0xffe0, 0x0003, 0xffee, 0x0003,
X   0xffe0, 0x0003, 0xffc0, 0x0001,
X   0xff80, 0x0000, 0x3f00, 0x0000,
X   0x3f00, 0x0000, 0x3f00, 0x0000,
X   0x3f00, 0x0000, 0x7f00, 0x0000,
X   0x7f80, 0x0000, 0x7f80, 0x0000,
X   0x7f80, 0x0000, 0xffc0, 0x0000,
X   0x0000, 0x0000, 0x0000, 0x0000};
X
X#define bomb3_width 32
X#define bomb3_height 32
Xstatic short bomb3_bits[] = {
X   0x0000, 0x000f, 0x1ff0, 0x7ff0,
X   0x0000, 0x0000, 0xe2fe, 0x3fa3,
X   0xfc00, 0x001f, 0xff3c, 0x007f,
X   0xff80, 0x00ff, 0xefc0, 0x01fb,
X   0xefc0, 0x01fb, 0xefe0, 0x03fb,
X   0xffe0, 0x03ff, 0xffe0, 0x03ff,
X   0xfde0, 0x01bf, 0xfbe0, 0x49df,
X   0xe782, 0x34e7, 0x1e14, 0x4238,
X   0x9fe2, 0x3499, 0xbe40, 0x413d,
X   0xfdbe, 0x1edf, 0xf800, 0x011f,
X   0xfdfe, 0x7fdf, 0xfc00, 0x001f,
X   0xfc00, 0x001f, 0xfc00, 0x003f,
X   0xfe00, 0x001f, 0xfe00, 0x003f,
X   0xff00, 0x003f, 0xffc0, 0x00ff,
X   0xfffc, 0x3fff, 0xfffe, 0x7fff,
X   0x0000, 0x0000, 0x0000, 0x0000};
END_OF_bitmaps.h
if test 2639 -ne `wc -c <bitmaps.h`; then
    echo shar: \"bitmaps.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f greek.u -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"greek.u\"
else
echo shar: Extracting \"greek.u\" \(6012 characters\)
sed "s/^X//" >greek.u <<'END_OF_greek.u'
Xbegin 644 greek.onx
XM&````/`'$``!````?@#X#P``"P`!`!``__\`````````````````````````
XM````````````````````````````````````````````````````````````
XM`````/]__W_4Z@`````````````!@0`````!`0``````````````````````
XM````````````````````````````````````````````````````````````
XM``````````````0```````````````````````````!551`(````````````
XM````````````````````````````````````````````````````````````
XM````````B8#__P``````````````````````````````````````````````
XM````````````````````````````````````````````@V"!0*UI````````
XM``````)!`````(*"````(`!``'``<`!0`'``8```````````````````````
XM`````````,`````````````0````````````````````0```````#```````
XM`````````````````````"``$`@`````````````````````````````````
XM```````````````````````````````````````````````"4`/`````````
XM````````````````````````````````````````````````````````````
XM``````````````````````"%4(%`5K<`````````````!"'_#P``?'P```!0
XM`$``0`!``%``$``0``````````````````````````"`````P```````````
XM`-`"``````````````````"@`0`````<````````````````````````````
XM=548&```````````````````````````````````````````````````````
XM`````````````````````````%0%`\``````````````````````````````
XM````````````````````````````````````````````````````````````
XM`(E(@4"]W0`````````````($0```````````%``0`!P`&``<`!P`'``````
XM`````````````````````)@!``!`$```````````V`8`````````````````
XM`)`!`````#P`@`0```````````````````````#X@#@\````````````````
XM````````````````````````````````````````````````````````````
XM`````5$#P```````````````````````````````````````````````````
XM````````````````````````````````````````D42!0'=W````````````
XM`!`)`_\``!`0@`$`4`!``!``0`!``$``4````````````````````````(`!
XMF`*``,`[``````````#(!P``````````````````B!@`````>`"``P``````
XM`````````````````/W3.#P`````````````````````````````````````
XM``````````````````````````````````````````!4"0/`````````````
XM````````````````````````````````````````````````````````````
XM``````````````````"A0H%`W=T`````````````(`4`````*"A@!@`@`$``
XM<`!P`$``<``@````````````````````````8`:(`N`#P#P``#@``````.P/
XM``````````````````#4/0````#``.``````````````````````````S\<X
XM/```````````````````````````````````````````````````````````
XM`````````````````````"!%`\``````````````````````````````````
XM`````````````````````````````````````````````````````````,%!
XM@4"W=@````````````!``_P_``#'QQ@8````````````````````````````
XM```````````````8&/P'@`#`;@``_`\`````_`\``````````````````.(_
XM`````(`!D`````````````````````````!7?SP\````````````````````
XM````````````````````````````````````````````````````````````
XM11,#P```````````````````````````````````````````````````````
XM````````````````````````````````````_W__?_W;```````````&8(`!
XM````````Q",```````````````````````````````````````````9@W!^`
XM`/!/``#T'P````#>#P``````````````````@!D```````>`````````````
XM`````````````(,^?#P`````````````````````````````````````````
XM``````````````````````````````````````"0`0/`````````````````
XM````````````````````````````````````````````````````````````
XM``````````````#!08%`5G<``````````+9M__\/_````0%$(@``````````
XM````````````````````````````````__^X!/P__`\``/P_`````,(.````
XM``````````````"``0````#X'X``````````````````````````55U\?@``
XM````````````````````````````````````````````````````````````
XM`````````````````,_]`\``````````````````````````````````````
XM`````````````````````````````````````````````````````*%"@4#O
XMO0``````````_G]``P````""@D0B````````````````````````````````
XM``````````!F9I@"^'_Z'P``[#\`````PP0``````````````````(`!````
XM`!@=_S\````````````````````````J^'Q^````````````````````````
XM``````````````````````````````````````````````````````````,#
XMP```````````````````````````````````````````````````````````
XM````````````````````````````````D42!0+;K``````````#^?R`%_N<`
XM`'Q\1"(``````````````````````````````````````````&9FG`(0$?0X
XM``#$/P````#A!0``````````````````P`(`````F!S^/P``````````````
XM`````````%_E?GX`````````````````````````````````````````````
XM```````````````````````````````````D%0/`````````````````````
XM````````````````````````````````````````````````````````````
XM``````````")2(%`IFL``````````+Y_$`D```````#\/P``````````````
XM````````````````````````````9F:4`8@(8B@``,0P`````"$!````````
XM``````````!``@````!8./S_````````````````````````/_#^?@``````
XM````````````````````````````````````````````````````````````
XM`````````````)%(`\``````````````````````````````````````````
XM`````````````````````````````````````````````````(50@4"F:0``
XM````````OG\($?P#```0$```````````````````````````````````````
XM``````!F9K8```"T)```Q#``````,`$``````````````````"`$`````#Q\
XM)`D```````````````````````#UO_Y^````````````````````````````
XM````````````````````````````````````````````````````*!$#P```
XM````````````````````````````````````````````````````````````
XM````````````````````````````@V"!0*9I``````````````0A`````"@H
XM`````````````````````````````````````````````&9F(@```)`4``#"
XM,``````0`0``````````````````8`P`````_O^2!```````````````````
XM`````.@<_O\`````````````````````````````````````````````````
XM```````````````````````````````%!?__````````````````````````
XM````````````````````````````````````````````````````````````
XM``````#_?_]_AF$``````````````D&/CP``Q\<`````````````````````
XM````````````````````````__]F````(`$``,`P`````!@#````````````
XM```````````````<.```````````````````````````U5___P``````````
XM````````````````````````````````````````````````````````````
XM`````````$I!__\`````````````````````````````````````````````
XM``````````````````````````````````````````````````"&80``````
XM```````!@0``````````````````````````````````````````````````
XM````````````````````````````````````````````````````````````
XM```````````````````````"(?__````````````````````````````````
XM`````````````````````````````````````````````````94``!``(``P
XM`$``4`!@`'``@`"0`*``L`#``-``X`#P```!$`$@`3`!0`%0`6`!<`&``9`!
XMH`&P`<`!T`'@`?`!``(0`B`",`)``E`"8`)P`H`"D`*@`K`"P`+0`N`"\`(`
XM`Q`#(`,P`T`#4`-@`W`#@`.0`Z`#L`/``]`#X`/P`P`$$`0@!#`$0`10!&`$
XM<`2`!)`$H`2P!,`$T`3@!/`$``40!2`%,`5`!5`%8`5P!8`%D`6@!;`%P`70
XM!>`%\`4`!A`&(`8P!D`&4`9@!G`&@`:0!J`&L`;`!M`&X`;P!@`'$`<@!S`'
X80`=0!V`'<`>`!Y`'H`>P!\`'T`?@!_`'
X`
Xend
END_OF_greek.u
if test 6012 -ne `wc -c <greek.u`; then
    echo shar: \"greek.u\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f init.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"init.c\"
else
echo shar: Extracting \"init.c\" \(6315 characters\)
sed "s/^X//" >init.c <<'END_OF_init.c'
X/* Copyright (c) 1987  Stanley T. Shebs, University of Utah. */
X/* This program may be used, copied, modified, and redistributed freely */
X/* for noncommercial purposes, so long as this notice remains intact. */
X
X/* RCS $Header: init.c,v 1.5 87/06/08 21:45:27 shebs Exp $ */
X
X#include "xconq.h"
X
X/* This is the character used to separate city name from side name in */
X/* predefined maps.  So far as I know, no city or people in the world */
X/* has a '*' in the name, so we're pretty safe with this choice. */
X
X#define SEPCHAR '*'
X
Xchar citybuf[MAXCITYBUF];  /* Storage for names of cities and sides */
X
X/* Set up some random cache-type variables - probably worthless. */
X/* Also start out in movement mode. */
X
Xinit_vars()
X{
X    int i;
X
X    for (i = 0; i < numutypes; ++i) {
X	unitchars[i] = utypes[i].uchar;
X	unitnames[i] = utypes[i].name;
X    }
X    for (i = 0; i < numctypes; ++i) {
X	citychars[i] = ctypes[i].cchar;
X	citynames[i] = ctypes[i].name;
X    }
X    mode = MOVE;
X}
X
X/* This initialization is for NEW games being set up on either a predefined */
X/* or just-generated map. (new maps having names in /tmp probably) */
X
Xinit_game()
X{
X    bool gotmap = FALSE;
X    char *name, *sname, *next;
X    int i, x, y, size;
X    City *city;
X    Side *side;
X
X    gotmap = read_named_map(TRUE);
X    if (!gotmap) exit(1);
X
X    /* now make a list of all the cities on the map */
X
X    numcities = 0;
X    name = citybuf;
X    for (y = worldheight-1; y >= 0; --y) {
X	for (x = 0; x < worldwidth; ++x) {
X	    if (is_urban(x, y)) {
X		next = (char *) index(name,'\0');
X		sname = (char *) index(name, SEPCHAR);
X		if (sname != NULL) *sname++ = '\0';
X		size = urb(x, y);
X		city = create_city(size, x, y, name, sname,
X				   NOTHING, 0, ctypes[size].hp, numcities++);
X		if (city == NULL) exit(1);
X	        while (*next++ == '\0');
X		name = next-1;
X	    }
X	}
X    }
X    if (numcities < numsides) {
X	fprintf(stderr, "%d cities not enough for %d sides\n",
X		numcities, numsides);
X	exit(1);
X    }
X    if (Debug) printf("Created %d cities\n", numcities);
X    for (i = 0; i < numsides; ++i) {
X	city = random_start_city();
X	side = create_side(humans[i], hosts[i], city->sname,
X                           avgstrat, 0, MINMORALE, 0, FALSE);
X	city_changes_side(city, side, CAPTURED);
X	set_product(city, 0, TRUE);
X	side->morale = SATISFIED;
X	update_view(side, city->x, city->y);
X    }
X    gametime = 0;
X}
X
X/* Initialization related specifically to setting up the world map. */
X
X/* Read a map out of a file and push it into an array in the internal format */
X/* Also get all the names of cities but just buffer them up */
X/* Cities and towns are assumed to sit on open land. */
X
Xread_world(fp, getcities)
XFILE *fp;
Xbool getcities;
X{
X    char ch, maptype;
X    int i, x, y, terr, ctype;
X    
X    fscanf(fp, "%c %d %d %d %d %d\n",
X	   &maptype, &worldwidth, &worldheight, &greenwich, &equator, &scale);
X    if (worldwidth > MAXWIDTH || worldheight > MAXHEIGHT) {
X	fprintf(stderr, "%dx%d map too big\n", worldwidth, worldheight);
X	exit(1);
X    }
X    if (worldwidth < 35 || worldheight < 35) {
X	fprintf(stderr, "%dx%d map too small\n", worldwidth, worldheight);
X	exit(1);
X    }
X    for (y = worldheight-1; y >= 0; --y) {
X	for (x = 0; x < worldwidth; ++x) {
X	    fscanf(fp, "%c", &ch);
X	    terr = iindex(ch, terrchars);
X	    if (terr < 0) terr = OPEN;
X	    ctype = iindex(ch, citychars);
X	    if (ctype < 0 || !getcities) ctype = RURAL;
X	    set_square(x, y, terr, ctype);
X	}
X	fscanf(fp, "\n");
X    }
X    if (getcities) {
X	/* suck in the rest of the file and stash */
X	i = 0;
X	while ((ch = getc(fp)) != EOF) {
X	    if (ch == ' ' || ch == '\n' || ch == '\t') ch = '\0';
X	    if (ch == '\\') ch = getc(fp);
X	    citybuf[i++] = ch;
X	}
X	citybuf[i++] = '\0';  /* in case somebody forgot a newline at EOF */
X    }
X    if (Debug) printf("Finished creating map\n");
X}
X
X/* A save file may either be an ordinary file in the current directory, */
X/* or a scenario in the library directory.  Look for both. */
X
Xrestore_game()
X{
X    FILE *fp;
X
X    if ((fp = fopen(rawsavename, "r")) != NULL) {
X	printf("Restoring from %s ...\n", rawsavename);
X	restore_game_aux(fp);
X	fclose(fp);
X#ifdef UNIX
X	unlink(rawsavename);
X#endif UNIX
X	return TRUE;
X    } else if ((fp = fopen(savename, "r")) != NULL) {
X	printf("Restoring from %s ...\n", savename);
X	restore_game_aux(fp);
X	fclose(fp);
X	/* don't delete the scenarios! */
X	return TRUE;
X    } else {
X	if (Debug) printf("`%s' not found...\n", savename);
X	return FALSE;
X    }
X}
X
X/* This reads in the data proper, taking care to override saved displays */
X/* and player types with anything that was on the command line. */
X
Xrestore_game_aux(fp)
XFILE *fp;
X{
X    int gorydetails;
X    char filetype, terr;
X    int i, x, y;
X
X    fscanf(fp, "%c %d %d\n",
X	   &filetype, &gametime, &gorydetails);
X    if (filetype == 'S') {
X	fgets(rawmapname, BUFSIZE-1, fp);
X	rawmapname[strlen(rawmapname)-1] = '\0';
X	make_lib_pathname(rawmapname, "map", mapname);
X	read_named_map(FALSE);
X    } else {
X	fscanf(fp, "M %d %d %d %d\n",
X	       &worldwidth, &worldheight, &greenwich, &equator);
X	for (y = 0; y < worldheight; ++y) {
X	    for (x = 0; x < worldwidth; ++x) {
X		fscanf(fp, "%c", &terr);
X		set_square(x, y, iindex(terr, terrchars), RURAL);
X		fscanf(fp, "\n");
X	    }
X	}
X    }
X    fscanf(fp, "Sides %d %d\n", &numsides, &numhosts);
X    for (i = 0; i < numsides; ++i) {
X	if (i < numgivens) {
X	    restore_side(fp, gorydetails, TRUE, humans[i], hosts[i]);
X	} else {
X	    restore_side(fp, gorydetails, FALSE, FALSE, NULL);
X	}
X    }
X    fscanf(fp, "Cities %d\n", &numcities);
X    for (i = 0; i < numcities; ++i) {
X	restore_city(fp);
X    }
X    fscanf(fp, "Units %d %d\n", &numunits, &nextid);
X    for (i = 0; i < numunits; ++i) {
X	restore_unit(fp);
X    }
X}
X
X/* Abstraction to read a map given a name of the file. */
X
Xread_named_map(getcities)
Xbool getcities;
X{
X    FILE *fp;
X
X    if ((fp = fopen(mapname, "r")) != NULL) {
X	read_world(fp, getcities);
X	fclose(fp);
X	return TRUE;
X    } else {
X#ifdef EXPERIMENTING
X	if ((fp = fopen(rawmapname, "r")) != NULL) {
X	    read_world(fp, getcities);
X	    fclose(fp);
X	    return TRUE;
X	} else {
X	    fprintf(stderr, "Can't open map files named '%s' or '%s'\n",
X		    mapname, rawmapname);
X	    exit(1);
X	}
X#endif EXPERIMENTING
X	fprintf(stderr, "Can't open map file named '%s'\n", mapname);
X    }
X    return FALSE;
X}
END_OF_init.c
if test 6315 -ne `wc -c <init.c`; then
    echo shar: \"init.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f input.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"input.c\"
else
echo shar: Extracting \"input.c\" \(9936 characters\)
sed "s/^X//" >input.c <<'END_OF_input.c'
X/* Copyright (c) 1987  Stanley T. Shebs, University of Utah. */
X/* This program may be used, copied, modified, and redistributed freely */
X/* for noncommercial purposes, so long as this notice remains intact. */
X
X/* RCS $Header: input.c,v 1.5 87/06/08 21:45:50 shebs Exp $ */
X
X#include "xconq.h"
X
Xint itertime = 100;    /* default time for repetition */
X
X/* the following structure is used for the dispatch table. */
X
Xstruct func_tab {
X    char f_char;       /* character to match against */
X    int (*f_func)();   /* pointer to command's function */
X    int f_default;     /* default repetition */
X    char *f_doc;       /* short documentation string */
X};
X
X/* Movement handled differently, to reduce size/complexity of table lookup. */
X
Xchar hjklmoves[] = "kulnjbhy";
X
X/* Predeclarations of all commands. */
X
Xint	do_sentry(), do_random(), do_wakeup(), do_wakeall(), do_embark(),
X        do_exit(), do_exit_self(), do_message(), do_follow(),
X	do_redraw(), do_disperse(), do_viewall(), do_return();
X	do_sit(), do_product(), do_idle(), do_help(), do_version(),
X	do_save(), do_standing(), do_ident(), do_moveto(), do_coast(),
X	do_construct(), do_survey_mode(), do_unit_info(), do_period_dump();
X
X/* Dummy to use to make blank lines in cmd display. (what a frob) */
X
Xdo_dummy() {}
X
X/* The command table itself.  Note that although blank appears several times */
X/* its real command is in the first occurrence, so everything works out. */
X/* Default iterations of -1 actually turn into whatever the standard default */
X/* is, might have been changed by player. */
X
Xstruct func_tab cmdtab[] = {
X	's', do_sentry, -1, "put a unit on sentry duty",
X	'w', do_wakeup, 1, "wake unit up from whatever it was doing",
X	' ', do_sit, 1, "(Space Bar) make unit be on sentry this turn only",
X	'm', do_moveto, 1, "move to given location",
X	'r', do_return, 1, "return unit to nearest city or transport",
X        'c', do_construct, 1, "construct a base",
X	'd', do_disperse, 1, "disband unit and send it home",
X	'e', do_embark, 1, "embark units in city onto transport in that city",
X	'f', do_follow, -1, "follow a designated leader",
X	'z', do_survey_mode, 1, "toggle between survey and move modes",
X	' ', do_dummy, 1, "",
X	'P', do_product, 1, "set/change city production",
X	'I', do_idle, -1, "set city to not produce anything",
X	'O', do_standing, 1, "set standing orders for units in city",
X	'F', do_coast,  -1, "follow a coastline",
X	'R', do_random, -1, "move unit randomly",
X	'W', do_wakeall, 1, "wake up ALL units",
X	'M', do_message, 1, "send a message to another side",
X	'X', do_exit_self, 1, "resign from the game",
X	'Q', do_exit, 1, "kill game for all players",
X	'S', do_save, 1, "save game",
X	' ', do_dummy, 1, "",
X	'?', do_help, 1, "show help info",
X	'/', do_ident, 1, "identify things on screen",
X	'=', do_unit_info, 1, "display details about unit type",
X	'+', do_period_dump, 1, "run all parameters into a file",
X	'V', do_version, 1, "display program version",
X	'\014', do_redraw, 1, "(^L) redraw screen",
X	'\022', do_redraw, 1, "(^R) redraw screen",
X#ifdef DEBUGGING
X        'v', do_viewall, 1, "look at everything",
X#endif DEBUGGING
X	0,0,0,0,0,0,0,0   /* paranoia padding */
X};
X
X/* Acquire a command from the player.  Command may be prefixed with a number */
X/* which is given as an argument to the command function (otherwise arg */
X/* defaults to value in third column of command table).  This routine takes */
X/* in both keyboard and mouse input, this is the place to handle other kinds */
X/* of devices also. */
X/* This routine also checks on the number of commands that a player is */
X/* allowed to put in each turn. */
X
Xread_command()
X{
X    char ch;
X    int inp, x, y, n = -1, dir = -1;
X    
X    if ((usecount && countedout) || (usetimer && timedout)) {
X	if (mode == SURVEY) mode = MOVE;
X	do_sit(1);
X	return;
X    }
X    /* acquire a parameter in n, otherwise leave it negative for later */
X    while ((inp = get_input(&ch, &x, &y)) == KEYBOARD && isdigit(ch)) {
X	n = (n < 0) ? ch-'0' : n*10 + ch-'0';
X    }
X    if (inp == KEYBOARD) {
X	if ((dir = iindex(ch, hjklmoves)) >= 0) {
X	    if (n < 0) n = 1;
X	    do_dir(dir, n);
X	} else if ((dir = iindex(tolower(ch), hjklmoves)) >= 0) {
X	    if (n == itertime && mode == SURVEY) n = 10;
X	    if (n < 0) n = itertime;
X	    do_dir(dir, n);
X	} else {
X	    execute_command(ch, n);
X	}
X    } else if (inp == MOUSE) {
X	if (x == curx && y == cury) {
X	    do_sit(1);
X	} else if (abs(curx-x) <= 1 && abs(cury-y) <= 1) {
X	    do_dir(find_dir(x-curx, y-cury), 1);
X	} else {
X	    switch (mode) {
X	    case MOVE:
X		order_moveto(curunit, x, y);
X		break;
X	    case SURVEY:
X		move_survey(x-curx, y-cury);
X		break;
X	    default:
X		case_panic("mode", mode);
X	    }
X	}
X    } else {
X	case_panic("input type", inp);
X    }
X    if (usecount) {
X	--numinputs;
X	update_count(curside);
X	if (numinputs <= 0) {
X	    countedout = TRUE;
X	    notify(curside, "No more orders this turn!");
X	    beep(curside);
X	}
X    }
X}
X
X/* Search in command table and execute function if found */
X
Xexecute_command(ch, n)
Xchar ch;
Xint n;
X{
X    struct func_tab *cmdentry;
X    
X    cmdentry = cmdtab;
X    while (cmdentry->f_char) {
X	if (ch == cmdentry->f_char) {
X	    if (n < 0) n = cmdentry->f_default;  /* try default */
X	    if (n < 0) n = itertime;
X	    (*(cmdentry->f_func))(n);               /* do it!! */
X	    return;
X	}
X	++cmdentry;
X    }
X    notify(curside, "Unknown command '%c'", ch);
X}
X
X/* Get a type of a unit from the player */
X
Xread_unit_type(prompt)
Xchar *prompt;
X{
X    char ch;
X    int inp, x, y, type;
X
X    while (TRUE) {
X	clear_prompt(curside);
X	sprintf(curside->promptbuf, "%s [%s] ", prompt, unitchars);
X	show_prompt(curside);
X	draw_cursor(curside, curx, cury);
X	inp = get_input(&ch, &x, &y);
X	if (inp == KEYBOARD) {
X	    echo_at_prompt(ch);
X	    if (islower(ch)) ch = toupper(ch);
X	    if (ch == '?') {
X		help_unit_type();
X		continue;
X	    } else if ((type = iindex(ch, unitchars)) == -1) {
X		clear_prompt(curside);
X		sprintf(curside->promptbuf, "Unit type '%c' not in '%s'",
X			ch, unitchars);
X		show_prompt(curside);
X		flush_output();
X		sleep(1);
X	    } else {
X		break;
X	    }
X	}
X    }
X    clear_prompt(curside);
X    flush_output();
X    return type;
X}
X
X/* User picks a position on map */
X
Xread_position(prompt, xp, yp)
Xchar *prompt;
Xint *xp, *yp;
X{
X    char ch;
X    int inp, oldx, oldy;
X
X    oldx = curx;  oldy = cury;
X
X    sprintf(curside->promptbuf, "%s [mouse to move, hit key to place] ",
X	    prompt);
X    show_prompt(curside);
X    while ((inp = get_input(&ch, xp, yp)) == MOUSE) {
X	put_on_screen(curside, *xp, *yp);
X	draw_cursor(curside, *xp, *yp);
X    }
X    curx = oldx;  cury = oldy;
X    clear_prompt(curside);
X    redraw(curside);
X}
X
X/* Get a number from the user */
X
Xread_number(prompt, deflt)
Xchar *prompt;
Xint deflt;
X{
X    char ch;
X    int inp, x, y, n;
X
X    sprintf(curside->promptbuf, "%s: [default %d]", prompt, deflt);
X    show_prompt(curside);
X    n = 0;
X    while ((inp = get_input(&ch, &x, &y)) == KEYBOARD && isdigit(ch)) {
X	echo_at_prompt(ch);
X	n = n*10 + ch-'0';
X    }
X    if (n == 0) n = deflt;
X    clear_prompt(curside);
X    return n;
X}
X
X/* Get a direction from user.  The general scheme is to get a moused point, */
X/* then limit the deltas to [-1,1].  This makes it harder to get 0 delta */
X/* values, but that's OK. */
X
Xread_direction(prompt)
Xchar *prompt;
X{
X    char ch;
X    int inp, x, y, dir;
X
X    sprintf(curside->promptbuf, "%s [mouse the direction] ", prompt);
X    show_prompt(curside);
X    while ((inp = get_input(&ch, &x, &y)) == KEYBOARD) {
X    }
X    clear_prompt(curside);
X    return find_dir(x - curx, y - cury);
X}
X
X/* Get a type of order */
X
Xread_order_type(prompt)
Xchar *prompt;
X{
X    char ch;
X    int inp, type, x, y;
X
X    while (TRUE) {
X	clear_prompt(curside);
X	sprintf(curside->promptbuf, "%s [%s] ", prompt, orderchars);
X	show_prompt(curside);
X	draw_cursor(curside, curx, cury);
X	inp = get_input(&ch, &x, &y);
X	if (inp == KEYBOARD) {
X	    echo_at_prompt(ch);
X	    if (ch == '?') {
X		help_order_type();
X		continue;
X	    } else if ((type = iindex(tolower(ch), orderchars)) == -1) {
X		clear_prompt(curside);
X		sprintf(curside->promptbuf, "Order type '%c' not in '%s'",
X			ch, orderchars);
X		show_prompt(curside);
X		flush_output();
X		sleep(1);
X	    } else {
X		break;
X	    }
X	}
X    }
X    clear_prompt(curside);
X    flush_output();
X    return type;
X}
X
X/* read a message string */
X
Xchar msgbuf[BUFSIZE];
X
Xchar *
Xread_message(toside)
XSide *toside;
X{
X    char ch;
X    int inp, x, y, i;
X
X    sprintf(curside->promptbuf, "Say to the %s: ", plural_form(toside->name));
X    show_prompt(curside);
X    i = 0;
X    while ((inp = get_input(&ch, &x, &y)) == KEYBOARD &&
X	   ch != '\n' && ch != '\r' && i < BUFSIZE-1) {
X	echo_at_prompt(ch);
X	if (ch == '\010') {
X	    if (i >= 0) --i;
X	} else {
X	    msgbuf[i++] = ch;
X	}
X    }
X    msgbuf[i] = '\0';
X    clear_prompt(curside);
X    flush_output();
X    return msgbuf;
X}
X
X/* Help for the main command mode just dumps part of the table, and a little */
X/* extra info about what's not in the table. */
X
Xcommand_help()
X{
X    struct func_tab *cmdentry;
X
X    wprintf(curside, "To move a unit, use the mouse or [hjklyubn]");
X    wprintf(curside, "[HJKLYUBN] moves repeatedly in that direction");
X    wprintf(curside, "Mousing unit makes it sit, mousing city or unit");
X    wprintf(curside, "initiates attack.");
X    wprintf(curside, "  ");
X    cmdentry = cmdtab;
X    while (cmdentry->f_char) {
X	wprintf(curside, "%c  %s", cmdentry->f_char, cmdentry->f_doc);
X	++cmdentry;
X    }
X}
X
X/* Predicate to verify that some side wants to do something irreversible. */
X/* This should never be called for machine-played sides. */
X
Xconfirm_choice(side, question)
XSide *side;
Xchar *question;
X{
X    char ch;
X    int inp, x, y;
X
X    sprintf(side->promptbuf, "%s [ny]", question);
X    show_prompt(side);
X    inp = get_input(&ch, &x, &y);
X    clear_prompt(side);
X    if (inp == KEYBOARD && (ch == 'Y' || ch == 'y')) {
X	return TRUE;
X    } else {
X	redraw(side);
X	return FALSE;
X    }
X}
END_OF_input.c
if test 9936 -ne `wc -c <input.c`; then
    echo shar: \"input.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f output.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"output.c\"
else
echo shar: Extracting \"output.c\" \(9556 characters\)
sed "s/^X//" >output.c <<'END_OF_output.c'
X/* Copyright (c) 1987  Stanley T. Shebs, University of Utah. */
X/* This program may be used, copied, modified, and redistributed freely */
X/* for noncommercial purposes, so long as this notice remains intact. */
X
X/* RCS $Header: output.c,v 1.4 87/06/08 21:45:22 shebs Exp $ */
X
X#include "xconq.h"
X
Xchar *modenames[] = MODENAMES;  /* names of the modes */
X
X/* Only defined/used here, so no defs in global file. */
X
Xchar *moralenames[] = { "Rebellious", "Seditious", "Disaffected", "Weary",
X			"Bored", "Satisfied", "Supportive", "Enthusiastic",
X			"Militant", "Fanatical" };
X
X/* The current column to insert at on the prompt line (where oh where is */
X/* a good X toolkit?) */
X
Xint promptcol;
X
X/* Variables for the "window printf" utility */
X
Xbool wprintmode;     /* true when printing is going into a file */
X
Xchar wbuf[BUFSIZE];  /* accumulated line of text */
X
Xint wcol, wline;     /* current position of output */
X
XFILE *wfp;           /* file pointer for wprintf in file writing mode */
X
X/* Send a message to everybody who's got a screen. */
X
Xnotify_all(control, a1, a2, a3, a4, a5, a6)
Xchar *control, *a1, *a2, *a3, *a4, *a5, *a6;
X{
X    Side *side;
X
X    for_all_sides(side) {
X	notify(side, control, a1, a2, a3, a4, a5, a6);
X    }
X}
X
X#ifdef XWINDOWS
X
X/* Main message-sending routine - does its own formatting and spits out to */
X/* the given side. */
X
Xnotify(side, control, a1, a2, a3, a4, a5, a6)
XSide *side;
Xchar *control, *a1, *a2, *a3, *a4, *a5, *a6;
X{
X    char tmpnote[BUFSIZE], notice[BUFSIZE];
X    int i;
X
X    if (active_display(side)) {
X	sprintf(tmpnote, control, a1, a2, a3, a4, a5, a6);
X	if (islower(tmpnote[0])) tmpnote[0] = toupper(tmpnote[0]);
X	sprintf(notice, "%d: %s", gametime, tmpnote);
X	for (i = 1; i < MAXNOTES; ++i) {
X	    strcpy(side->noticebuf[i-1], side->noticebuf[i]);
X	}
X	strcpy(side->noticebuf[MAXNOTES-1], notice);
X	show_note(side);
X	XFlush();
X	if (Debug) printf("%s\n", notice);
X    }
X}
X
X/* Notice area refresher.  All notes except the most recent one are grayed */
X/* out. */
X
Xshow_note(side)
XSide *side;
X{
X    int i;
X
X    XClear(side->msg);
X    for (i = 0; i < MAXNOTES; ++i) {
X	XText(side->msg, 0, i*fh,
X	      side->noticebuf[i], strlen(side->noticebuf[i]),
X	      side->msgfont,
X	      (i == MAXNOTES-1) ? side->fgcolor : side->graycolor,
X	      side->bgcolor);
X    }
X}
X
X/* Management of current unit/city info. */
X
Xset_current_info(side, str1, str2)
XSide *side;
Xchar *str1, *str2;
X{
X    strcpy(side->infobuf[0], str1);
X    strcpy(side->infobuf[1], str2);
X}
X
X/* Refreshes info lines. */
X
Xshow_info(side)
XSide *side;
X{
X    if (active_display(side)) {
X	XClear(side->info);
X	XText(side->info, 0, 0*fh, side->infobuf[0], strlen(side->infobuf[0]),
X	      side->msgfont, side->fgcolor, side->bgcolor);
X	XText(side->info, 0, 1*fh, side->infobuf[1], strlen(side->infobuf[1]),
X	      side->msgfont, side->fgcolor, side->bgcolor);
X	XFlush();
X    }
X}
X
X/* Erase info stuff.  Hit the arrays so we don't get annoyed when old and */
X/* worthless info reappears upon redraw. */
X
Xclear_info (side)
XSide *side;
X{
X    if (active_display(side)) {
X	sprintf(side->infobuf[0], " ");
X	sprintf(side->infobuf[1], " ");
X	XClear(side->info);
X    }
X}
X
X/* The prompt window consists of exactly one line, but we have to keep track */
X/* of where the blank space begins, for when people type into it. */
X
Xshow_prompt(side)
XSide *side;
X{
X    if (active_display(side)) {
X	XText(side->prompt, 0, 0, side->promptbuf, strlen(side->promptbuf),
X	      side->msgfont, side->fgcolor, side->bgcolor);
X	promptcol = strlen(side->promptbuf) + 1;
X    }
X}
X
X/* Spit a char onto the prompt line, hopefully after the previous one. */
X/* Kludge to handle backspaces, should be fixed, or else use toolkit... */
X
Xecho_at_prompt(ch)
Xchar ch;
X{
X    char tmp[2];
X
X    /* no display test needed ... */
X
X    if (ch == '\010') {
X	tmp[0] = ' ';
X	XText(curside->prompt, (--promptcol)*fw, 0, tmp, 1, 
X	      curside->msgfont, curside->fgcolor, curside->bgcolor);
X    } else {
X	tmp[0] = ch;
X	XText(curside->prompt, (promptcol++)*fw, 0, tmp, 1, 
X	      curside->msgfont, curside->fgcolor, curside->bgcolor);
X    }
X    XFlush();
X}
X
X/* Clear the prompt line.  We only call this when no display test needed. */
X
Xclear_prompt(side)
XSide *side;
X{
X    sprintf(side->promptbuf, " ");
X    XClear(side->prompt);
X}
X
X/* Update the turn number display. */
X
Xshow_time(side)
XSide *side;
X{
X    char timebuf[BUFSIZE];
X
X    if (active_display(side)) {
X	XClear(side->time);
X	sprintf(timebuf, "Turn %4d", gametime);
X	XText(side->time, 0, 0, timebuf, strlen(timebuf),
X	      side->msgfont, side->fgcolor, side->bgcolor);
X	XFlush();
X	if (Debug) printf("Turn %d\n", gametime);
X    }
X}
X
X/* Update the Mode display. */
X
Xshow_mode(side)
XSide *side;
X{
X    char modebuf[BUFSIZE];
X
X    if (active_display(side)) {
X	XClear(side->mode);
X	sprintf(modebuf, "%s Mode", modenames[mode]);
X	XText(side->mode, 0, 0, modebuf, strlen(modebuf),
X	      side->msgfont, side->fgcolor, side->bgcolor);
X	XFlush();
X    }
X}
X
X/* Update the State display (random global things about a side). */
X/* So far this includes morale and the number of inputs remaining that turn. */
X
Xshow_state(side)
XSide *side;
X{
X    char statebuf[BUFSIZE];
X
X    if (active_display(side)) {
X	XClear(side->state);
X	sprintf(statebuf, "Morale %d (%s) Score %d",
X		side->morale, moralenames[side->morale/1000], side->score);
X	XText(side->state, 0, 1*fh, statebuf, strlen(statebuf),
X	      side->msgfont, side->fgcolor, side->bgcolor);
X	if (usecount) {
X	    sprintf(statebuf, "%3d inputs left", numinputs);
X	    XText(side->state, 0, 0*fh, statebuf, strlen(statebuf),
X		  side->msgfont, side->fgcolor, side->bgcolor);
X	}
X	XFlush();
X    }
X}
X
X/* Tweak the counter only (probably a bogus optimization) */
X
Xupdate_count(side)
XSide *side;
X{
X    char tmp[BUFSIZE];
X
X    if (active_display(side)) {
X	sprintf(tmp, "%3d", numinputs);
X	XText(side->state, 0, 0, tmp, strlen(tmp),
X	      side->msgfont, side->fgcolor, side->bgcolor);
X	XFlush();
X    }
X}
X
X/* Show a list of all sides in action, drawing a line through any that have */
X/* lost out. */
X
Xshow_all_sides(side)
XSide *side;
X{
X    int midhgt;
X    Side *side2;
X
X    if (active_display(side)) {
X	XClear(side->sides);
X	for_all_sides(side2) {
X	    XText(side->sides, 0, side_number(side2)*fh,
X		  side2->titlebuf, strlen(side2->titlebuf),
X		  side->msgfont, side->graycolor, side->bgcolor);
X	    if (side2->lost) {
X		midhgt = side_number(side2)*fh+fh/2;
X		XLine(side->sides, 0, midhgt, 500, midhgt,
X		      1, 1, side->graycolor, GXcopy, AllPlanes);
X	    }
X	}
X	XFlush();
X    }
X}
X
X/* Highlight the side whose turn it is, using reverse video for current */
X/* player's own display (to wake she/he/it up) and white instead of gray */
X/* for everybody else. */
X
Xshow_curside(side)
XSide *side;
X{
X    if (active_display(side) && curside != NULL) {
X	XText(side->sides, 0, side_number(curside)*fh,
X	      curside->titlebuf, strlen(curside->titlebuf), side->msgfont,
X	      (side == curside ? side->bgcolor : side->fgcolor),
X	      (side == curside ? side->fgcolor : side->bgcolor));
X	XFlush();
X    }
X}
X
X/* Un-highlight the side whose turn it no longer is. */
X
Xunshow_curside(side)
XSide *side;
X{
X    if (active_display(side) && curside != NULL) {
X	XText(side->sides, 0, side_number(curside)*fh,
X	      curside->titlebuf, strlen(curside->titlebuf),
X	      side->msgfont, side->graycolor, side->bgcolor);
X	XFlush();
X    }
X}
X
X/* Update the countdown timer window. */
X
Xshow_countdown(side)
XSide *side;
X{
X    char clockbuf[BUFSIZE];
X
X    if (active_display(side)) {
X	XClear(side->clock);
X	sprintf(clockbuf, "%3d", countdown);
X	XText(side->clock, 0, 0, clockbuf, strlen(clockbuf),
X	      side->msgfont, side->fgcolor, side->bgcolor);
X	XFlush();
X    }
X}
X
X/* beep the beeper! */
X
Xbeep(side)
XSide *side;
X{
X    if (active_display(side)) XFeep(0);
X}
X
X/* Dump a file into the help window.  This routine is neither sophisticated */
X/* nor robust - lines must be short enough and file must be one page. */
X/* Returns success or failure of file opening. */
X
Xshow_file(side, fname)
XSide *side;
Xchar *fname;
X{
X    FILE *fp;
X
X    if ((fp = fopen(fname, "r")) != NULL) {
X	while (fgets(spbuf, BUFSIZE, fp)) {
X	    spbuf[strlen(spbuf)-1] = '\0';  /* cut off newline */
X	    wprintf(side, spbuf);
X	}
X	fclose(fp);
X	return TRUE;
X    } else {
X	return FALSE;
X    }
X}
X
X/* Little routines to pop up the help window and make it go away again */
X/* They only get called when display is in use */
X
XWindow tmphelp;
X
Xreveal_help()
X{
X    tmphelp = curside->help;
X
X    XMapWindow(tmphelp);
X    XClear(tmphelp);
X}
X
Xconceal_help()
X{
X    XUnmapWindow(tmphelp);
X    redraw(curside);
X    XFlush();
X}
X
X/* init our counters or open a file. */
X
Xinit_wprintf(fname)
Xchar *fname;
X{
X    wcol = 0;
X    wline = 0;
X    wprintmode = (fname != NULL);
X    if (wprintmode) {
X	wfp = fopen(fname, "w");
X    }
X}
X
X/* Make like printf, but to the help window.  This is pretty crude - has an */
X/* automatic newlining (mis)feature, and doesn't do anything about long */
X/* lines, but it's good enough. */
X
Xwprintf(side, control, a1, a2, a3, a4, a5, a6)
XSide *side;
Xchar *control, *a1, *a2, *a3, *a4, *a5, *a6;
X{
X    sprintf(wbuf, control, a1, a2, a3, a4, a5, a6);
X    if (wprintmode && wfp != NULL) {
X	fprintf(wfp, "%s\n", wbuf);
X    } else {
X	if (strlen(wbuf) > 0) {
X	    XText(side->help, wcol*fw, wline*fh, wbuf, strlen(wbuf),
X		  side->msgfont, side->fgcolor, side->bgcolor);
X	}
X	wline++;  /* should acct for newlines etc */
X    }
X}
X
X/* If we were actually printing to a file, close it down. */
X
Xfinish_wprintf()
X{
X    if (wprintmode && wfp != NULL) fclose(wfp);
X}
X
X#endif XWINDOWS
END_OF_output.c
if test 9556 -ne `wc -c <output.c`; then
    echo shar: \"output.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f side.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"side.c\"
else
echo shar: Extracting \"side.c\" \(9926 characters\)
sed "s/^X//" >side.c <<'END_OF_side.c'
X/* Copyright (c) 1987  Stanley T. Shebs, University of Utah. */
X/* This program may be used, copied, modified, and redistributed freely */
X/* for noncommercial purposes, so long as this notice remains intact. */
X
X/* RCS $Header: side.c,v 1.5 87/06/07 11:37:07 shebs Exp $ */
X
X#include "xconq.h"
X
X#include "side.h"
X
XSide sides[MAXSIDES];  /* arrays containing all sides */
XSide *sidelist;        /* head of list of all sides */
XSide *curside;         /* side whose turn it is right now */
X
Xbool snameused[MAXSIDENAMES];  /* flags true if a name of side already used */
X
Xint numsides;          /* number of sides in the game */
X
X/* Reset side array and related things. */
X
Xinit_sides()
X{
X    int i, s;
X
X    for (i = 0; i < MAXSIDENAMES; ++i) {
X	snameused[i] = FALSE;
X    }
X    for (s = 0; s < MAXSIDES; ++s) {
X	sides[s].name = NULL;
X    }
X    sidelist = NULL;
X}
X
X/* Create an object representing a side.  Most of the work is picking */
X/* a name, although there's plenty of other inits to do. */
X
XSide *
Xcreate_side(person, host, name, strategy, basenum, morale, score, lost)
Xbool person, lost;
Xchar *host, *name;
Xint basenum, strategy, morale, score;
X{
X    unsigned char ch, *tmp;
X    int s, n, i;
X
X    if (person && host == NULL) {
X	fprintf(stderr, "Human player with no display!\n");
X	abort();
X    }
X    for (s = 0; s < MAXSIDES; ++s) {
X	if (sides[s].name == NULL) {
X	    sides[s].humanp = person;
X	    if (host != NULL) {
X		sides[s].host = malloc(strlen(host)+2);
X		strcpy(sides[s].host, host);
X	    } else sides[s].host = NULL;
X#ifdef XWINDOWS
X	    if (name == NULL &&	host != NULL &&
X		strcmp(host, getenv("DISPLAY")) == 0) {
X		name = XGetDefault(programname, "SideName");
X	    }
X#endif XWINDOWS
X	    if (name == NULL) {
X		while (snameused[(n=random(MAXSIDENAMES))]);
X		snameused[n] = TRUE;
X		name = sidenames[n];
X	    }
X	    sides[s].name = malloc(strlen(name)+2);
X	    strcpy(sides[s].name, name);
X	    sprintf(sides[s].titlebuf,
X		    "%d: The %s (%s)",
X		    s, plural_form(sides[s].name), (host != NULL ? host : ""));
X	    for (i = 0; i < numutypes; ++i) {
X		sides[s].counts[i] = 1;        /* reset id# of units */
X	    }
X	    sides[s].view = (unsigned char *) malloc(worldwidth*worldheight);
X	    tmp = sides[s].view;
X	    for (i = 0; i < worldwidth*worldheight; ++i) *tmp++ = UNSEEN;
X	    sides[s].basenum = basenum;
X	    sides[s].morale = morale;
X	    sides[s].score = score;
X	    sides[s].lost = lost;
X	    sides[s].territory = 1;
X	    sides[s].strategy = strategy;
X	    link_in_side(&sides[s]);
X	    return &sides[s];
X	}
X    }
X    fprintf(stderr, "Cannot have more than %d sides total\n", MAXSIDES);
X    abort();
X}
X
X/* Add the new side to the end of the list of sides - this keeps our */
X/* list traversals going from top to bottom. */
X
Xlink_in_side(side)
XSide *side;
X{
X    Side *head, *last;
X
X    if (sidelist == NULL) {
X	sidelist = side;
X    } else {
X	for (head = sidelist; head != NULL; head = head->next) {
X	    if (head->next == NULL) last = head;
X	}
X	last->next = side;
X    }
X    side->next = NULL;
X}
X
X/* Given a side, get its relative position in array of sides (the "number"). */
X
Xside_number(side)
XSide *side;
X{
X    return (side == NULL ? -1 : (side - sides));
X}
X
X/* The inverse function - given a number, figure out which side it reps. */
X
XSide *
Xside_n(n)
Xint n;
X{
X    return ((n >= 0 && n < numsides) ? &sides[n] : NULL);
X}
X
X/* Pretty simple for a function, but some day we might want to re-use unit */
X/* numbers and only retire the numbers of the most successful units :-) */
X
Xassign_unit_number(type, side)
Xint type;
XSide *side;
X{
X    return (side->counts)[type]++;
X}
X
X/* Any effects of morale change should be in here. */
X
Xadjust_morale(side, n)
XSide *side;
Xint n;
X{
X    if (side == NULL) return;
X    side->morale += n;
X    side->morale = max(MINMORALE, min(side->morale, MAXMORALE));
X    show_state(side);
X}
X
X/* When size of territory changes, so does morale.  When territory is lost, */
X/* morale goes down by 1/3 more than it goes up from a comparable territory */
X/* gain.  The people are fickle (also keeps games from dragging out). */
X
Xadjust_territory(side, n, changemorale)
XSide *side;
Xint n, changemorale;
X{
X    int newterr, newmorale, diff;
X
X    if (side == NULL) return;
X    newterr = max(1, side->territory + n);
X    if (changemorale) {
X	newmorale = (side->morale * newterr) / side->territory;
X	newmorale = max(500, min(9000, newmorale));
X	diff = newmorale - side->morale;
X	if (diff < 0) diff += diff/3;
X	adjust_morale(side, diff);
X    }
X    side->territory = newterr;
X}
X
Xadjust_score(side, n)
XSide *side;
Xint n;
X{
X    if (side == NULL) return;
X    side->score += n;
X    show_state(side);
X}
X
X/* Make the whole world be known to all players. */
X    
Xall_view_world()
X{
X    int x, y;
X    Side *side;
X    
X    for (side = sidelist; side != NULL; side = side->next) {
X	for (x = 0; x < worldwidth; ++x) {
X	    for (y = 0; y < worldheight; ++y) {
X		see_something(side, x, y, FALSE);
X	    }
X	}
X    }
X}
X
X/* How things see others.  The tricky part of this is handling everybody's */
X/* different points of view at the same time.  We start with a side and pos */
X/* and update that sides' view of everything visible from that position.  At */
X/* the same time, we update everybody else's view of the that same position, */
X/* being careful to avoid computing views from neutral cities... */
X
Xupdate_view(side, x, y)
XSide *side;
Xint x, y;
X{
X    int d, x1, y1;
X    Unit *unit;
X    City *city;
X    Side *side2;
X
X    see_something(side, x, y, TRUE);
X    for (d = 0; d < 8; ++d) {
X	x1 = wrap(x + dirx[d]);  y1 = limit(y + diry[d]);
X	if ((city = city_at(x1, y1)) != NULL) {
X	    side2 = city->side;
X	} else if ((unit = unit_at(x1, y1)) != NULL) {
X	    side2 = unit->side;
X	} else {
X	    side2 = NULL;
X	}
X	see_something(side, x1, y1, FALSE);
X	see_something(side2, x, y, FALSE);
X    }
X}
X
X/* What the given side sees at the given location, irrespective of whether */
X/* anything sees it or not. */
X
Xsee_something(side, x, y, seehidden)
XSide *side;
Xint x, y, seehidden;
X{
X    Unit *unit;
X    City *city;
X
X    if (side == NULL) return;
X    if ((city = city_at(x, y)) != NULL) {
X	set_side_view(side, x, y,
X		      buildview(side_number(city->side), VCITY, city->size));
X    } else if ((unit = unit_at(x, y)) != NULL &&
X	       (seehidden || !(unit->hidden && side != unit->side))) {
X	set_side_view(side, x, y,
X		      buildview(side_number(unit->side), VUNIT, unit->type));
X    } else {
X	set_side_view(side, x, y, EMPTY);
X    }
X    if (active_display(side))
X	draw_square(side, x, y);
X}
X
X/* Verbal description of what you can see on the screen (plus city names). */
X
Xshow_thing_seen(side, x, y)
XSide *side;
Xint x, y;
X{
X    int view;
X    Side *side2;
X
X    view = side_view(side, x, y);
X    if (view == EMPTY) {
X	clear_info(side);
X    } else {
X	side2 = side_n(valign(view));
X	if (vthing(view) == VCITY) {
X	    sprintf(spbuf, "%s %s of %s",
X		    (side2 == NULL ? "neutral" : side2->name),
X		    citynames[vtype(view)],
X		    (city_at(x, y) ? city_at(x, y)->name : "graves"));
X	} else {
X	    sprintf(spbuf, "%s %s",
X		    side2->name, unitnames[vtype(view)]);
X	}
X	sprintf(spbuf2, "");
X	set_current_info(side, spbuf, spbuf2);
X    }
X    show_info(side);
X    draw_cursor(side, x, y);
X}
X
X/* A side can be saved with or without the entire view, which is a fairly */
X/* large sort of thing.  Machine sides without displays have their names */
X/* written as ___ - let us hope and pray that such a perverted name never */
X/* appears as a valid X display. */
X
Xsave_side(side, fp, gorydetails)
XSide *side;
XFILE *fp;
Xbool gorydetails;
X{
X    int i, x, y;
X
X    fprintf(fp, "%s\n%s\n%d %d %d %d %d %d ",
X	    side->name, (side->host ? side->host : "___"),
X	    side->humanp, side->strategy, side->basenum, side->morale,
X	    side->score, side->lost);
X    for (i = 0; i < 3; ++i) {
X	fprintf(fp, "%d ", side->stratparms[i]);
X    }
X    for (i = 0; i < numutypes; ++i) {
X	fprintf(fp, "%d ", side->counts[i]);
X    }
X    fprintf(fp, "\n");
X    if (gorydetails) {
X	for (y = 0; y < worldheight; ++y) {
X	    for (x = 0; x < worldwidth; ++x) {
X		fprintf(fp, "%d ", side_view(side, x, y));
X	    }
X	    fprintf(fp, "\n");
X	}
X    }
X}
X
X/* Machine-played sides have to be restored without getting attached to */
X/* displays.  */
X
Xrestore_side(fp, gorydetails, subst, cmdhuman, cmdhost)
XFILE *fp;
Xint gorydetails, subst, cmdhuman;
Xchar *cmdhost;
X{
X    char name[BUFSIZE], host[BUFSIZE], *hostptr;
X    int i, j, x, y, terr, tmp1, hum, strat, bn, mor, score, lost;
X    Side *side;
X
X    fgets(name, BUFSIZE-1, fp);  name[strlen(name)-1] = '\0';
X    fgets(host, BUFSIZE-1, fp);  host[strlen(host)-1] = '\0';
X    fscanf(fp, "%d %d %d %d %d %d", &hum, &strat, &bn, &mor, &score, &lost);
X    if (strcmp(host, "___") == 0)
X	hostptr = NULL;
X    else
X	hostptr = host;
X    if (subst) {
X	hostptr = cmdhost;
X	hum = cmdhuman;
X    }
X    side = create_side(hum, hostptr, name, strat, bn, mor, score, lost);
X    for (j = 0; j < 3; ++j) {
X	fscanf(fp, "%d ", &tmp1);
X	side->stratparms[j] = tmp1;
X    }
X    for (j = 0; j < numutypes; ++j) {
X	fscanf(fp, "%d ", &tmp1);
X	side->counts[j] = tmp1;
X    }
X    if (gorydetails) {
X	for (y = 0; y < worldheight; ++y) {
X	    for (x = 0; x < worldwidth; ++x) {
X		fscanf(fp, "%d", &tmp1);
X		set_side_view(side, x, y, tmp1);
X	    }
X	}
X	fscanf(fp, "\n");
X    }
X    if (Debug) printf("Restored side %s (%s)\n", side->name, side->host);
X}
X
X/* Show some overall numbers on performance of a side. */
X
Xprint_side_results(fp, side)
XFILE *fp;
XSide *side;
X{
X    int ctype;
X
X    fprintf(fp, "%s\n\n", side->titlebuf);
X    fprintf(fp,
X	    "Production (Time spent on finished products / total time):\n");
X    for (ctype = 1; ctype < numctypes; ++ctype) {
X	if (side->production[ctype] > 0) {
X	    fprintf(fp, "%s %4d / %4d (Efficiency %.2f)\n",
X		    citynames[ctype],
X		    side->completion[ctype], side->production[ctype],
X		    (((float) side->completion[ctype]) /
X		     side->production[ctype]));
X	}
X    }
X    fprintf(fp, "\n");
X}
END_OF_side.c
if test 9926 -ne `wc -c <side.c`; then
    echo shar: \"side.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f util.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"util.c\"
else
echo shar: Extracting \"util.c\" \(6229 characters\)
sed "s/^X//" >util.c <<'END_OF_util.c'
X/* Copyright (c) 1987  Stanley T. Shebs, University of Utah. */
X/* This program may be used, copied, modified, and redistributed freely */
X/* for noncommercial purposes, so long as this notice remains intact. */
X
X/* RCS $Header: util.c,v 1.5 87/06/08 21:45:08 shebs Exp $ */
X
X#include "xconq.h"
X
Xint dirx[] = DIRX, diry[] = DIRY;  /* arrays for dir-to-delta conversion */
X
X/* Random number handling is important to game but terrible in some Unices. */
X/* These should probably be replaced with homemade routines. */
X
Xinit_random()
X{
X    srand(getpid());
X}
X
X/* The 37 is a bit of magic inherited from Larry Wall's warp - he had */
X/* observed a rand() producing successive evens and odds. */
X
Xrandom(m)
X{
X    return ((rand() / 37) % m);
X}
X
X/* Different Unices have different favorite ways of making new filenames. */
X
Xchar *
Xtemp_name()
X{
X#ifdef HPUX
X    return tempnam("/tmp", "xconq");
X#endif HPUX
X#ifdef BSD
X    return (char *) mktemp("/tmp/xconqXXXXXX");
X#endif BSD
X}
X
Xmake_lib_pathname(name, extn, pathbuf)
Xchar *name, *extn, *pathbuf;
X{
X#ifdef UNIX
X    sprintf(pathbuf, "%s/%s.%s", XCONQLIB, name, extn);
X#endif UNIX
X}
X
X/* True if coords at or outside whole world or restriction of it */
X
Xat_world_edge(x, y)
Xint x, y;
X{
X    return (y >= worldheight-1 || y < 1);
X}
X
X/* Are we next to terrain where we can get supplies? */
X
Xis_adj_resupply(type, x, y)
Xint type, x, y;
X{
X    int x1, y1;
X    
X    for (x1 = x-1; x1 <= x+1; ++x1)
X	for (y1 = y-1; y1 <= y+1; ++y1)
X	    if (utypes[type].adj[terrain(wrap(x1), y1)]) return TRUE;
X    return FALSE;
X}
X
Xadj_obstacle(type, x, y)
Xint type, x, y;
X{
X    int x1, y1;
X    
X    for (x1 = x-1; x1 <= x+1; ++x1)
X	for (y1 = y-1; y1 <= y+1; ++y1)
X	    if (utypes[type].moveson[terrain(wrap(x1), y1)] == 0) return TRUE;
X    return FALSE;
X}
X
Xsurrounded(side, x, y)
XSide *side;
Xint x, y;
X{
X    int x1, y1;
X    
X    for (x1 = x-1; x1 <= x+1; ++x1)
X	for (y1 = y-1; y1 <= y+1; ++y1)
X	    if (!(x1 == x && y1 == y) &&
X		friendly_square(side, wrap(x1), limit(y1))) return FALSE;
X    return TRUE;
X}
X
Xfriendly_square(side, x, y)
XSide *side;
Xint x, y;
X{
X    Unit *unit;
X    City *city;
X
X    if ((unit = unit_at(x, y)) != NULL && side != unit->side)
X	return FALSE;
X    if ((city = city_at(x, y)) != NULL && side != city->side)
X	return FALSE;
X    return TRUE;
X}
X
X/* Given deltas, compute direction number. */
X
Xfind_dir(dx, dy)
Xint dx, dy;
X{
X    if (dx < 0) {
X	if (dy < 0) return SW;
X	if (dy == 0) return WEST;
X	return NW;
X    } else if (dx == 0) {
X	if (dy > 0) return NORTH;
X	if (dy == 0) { fprintf(stderr, "bogus deltas!\n"); abort(); }
X	return SOUTH;
X    } else {
X	if (dy < 0) return SE;
X	if (dy == 0) return EAST;
X	return NE;
X    }
X}
X
X/* Given a number, figure out what suffix should go with it. */
X
Xchar ordnum[10];
X
Xchar *
Xordinal(n)
Xint n;
X{
X    char *suff;
X    int n1;
X    
X    n1 = n % 100;
X
X    if (n1 == 11 || n1 == 12 || n1 == 13)
X	suff = "th";
X    else
X	switch (n % 10) {
X	case 1:   suff = "st"; break;
X	case 2:   suff = "nd"; break;
X	case 3:   suff = "rd"; break;
X	default:  suff = "th"; break;
X	}
X    sprintf(ordnum, "%d%s", n, suff);
X    return ordnum;
X}
X
Xchar pluralbuf[BUFSIZE];
X
Xchar *
Xplural_form(word)
Xchar *word;
X{
X    char endch;
X
X    endch = word[strlen(word)-1];
X    if (endch == 'h' || endch == 's')
X	sprintf(pluralbuf, "%s", word);
X    else
X	sprintf(pluralbuf, "%ss", word);
X    return pluralbuf;
X}
X
X/* almost worthless routine to display a useless coordinate pair */
X
Xchar posbuf[BUFSIZE];
X
Xchar *
Xpos_desig(x, y)
Xint x, y;
X{
X    sprintf(posbuf, " (%d,%d)", x - greenwich, y - equator);
X    return posbuf;
X}
X
X/* get a *numeric* index into a string (infinitely more useful than ptr!) */
X
Xiindex(ch, str)
Xchar ch, *str;
X{
X    char *rest;
X
X    return ((rest = (char *) index(str, ch)) == NULL) ? -1 : rest - str;
X}
X
X/* true if there is a unit of given type close by (used by machine strategy) */
X
Xadj_unit_type(unit, type, exp, eyp)
XUnit *unit;
Xint type, *exp, *eyp;
X{
X    int d, ix, iy;
X    Unit *other;
X    
X    for (d = 0; d < 8; ++d) {
X	ix = unit->x + dirx[d];  iy = unit->y + diry[d];
X	if ((other = unit_at(wrap(ix), iy)) != NULL &&
X	    other->side == unit->side &&
X	    other->type == type) {
X	    *exp = wrap(ix);  *eyp = iy;
X	    return TRUE;
X	}
X    }
X    return FALSE;
X}
X
X/* count up passengers for a given unit */
X
Xcargo_size(unit, type)
XUnit *unit;
Xint type;
X{
X    int num = 0;
X    Unit *carg;
X
X    for (carg = unit->cargo; carg != NULL; carg = carg->nexthere) {
X	if (carg->type == type) ++num;
X    }
X    return num;
X}
X
X/* generalized area search routine */
X/* It starts in the immediately adjacent squares and expands outwards */
X/* Always searches in same pattern - hard to change this... */
X
Xsearch_area(x0, y0, maxdist, pred, rxp, ryp)
Xint x0, y0, maxdist, (*pred)(), *rxp, *ryp;
X{
X    int x, y, y1, dist;
X
X    for (dist = 1; dist <= maxdist; ++dist) {
X	if (flip_coin()) {
X	    for (x = x0 - dist; x <= x0 + dist; ++x) {
X		y1 = limit(y0 - dist);
X		if ((*pred)(wrap(x), y1)) {
X		    *rxp = wrap(x);  *ryp = y1;
X		    return TRUE;
X		}
X		y1 = limit(y0 + dist);
X		if ((*pred)(wrap(x), y1)) {
X		    *rxp = wrap(x);  *ryp = y1;
X		    return TRUE;
X		}
X	    }
X	    for (y = y0 - dist; y <= y0 + dist; ++y) {
X		y1 = limit(y);
X		x = x0 - dist;
X		if ((*pred)(wrap(x), y1)) {
X		    *rxp = wrap(x);  *ryp = y1;
X		    return TRUE;
X		}
X		x = x0 + dist;
X		if ((*pred)(wrap(x), y1)) {
X		    *rxp = wrap(x);  *ryp = y1;
X		    return TRUE;
X		}
X	    }
X	} else {
X	    for (y = y0 - dist; y <= y0 + dist; ++y) {
X		y1 = limit(y);
X		x = x0 - dist;
X		if ((*pred)(wrap(x), y1)) {
X		    *rxp = wrap(x);  *ryp = y1;
X		    return TRUE;
X		}
X		x = x0 + dist;
X		if ((*pred)(wrap(x), y1)) {
X		    *rxp = wrap(x);  *ryp = y1;
X		    return TRUE;
X		}
X	    }
X	    for (x = x0 - dist; x <= x0 + dist; ++x) {
X		y1 = limit(y0 - dist);
X		if ((*pred)(wrap(x), y1)) {
X		    *rxp = wrap(x);  *ryp = y1;
X		    return TRUE;
X		}
X		y1 = limit(y0 + dist);
X		if ((*pred)(wrap(x), y1)) {
X		    *rxp = wrap(x);  *ryp = y1;
X		    return TRUE;
X		}
X	    }
X	}
X    }
X    return FALSE;
X}
X
X/* This little routine goes at the end of all case statements on internal */
X/* data that shouldn't go out of bounds. */
X
Xcase_panic(str, var)
Xchar *str;
Xint var;
X{
X    fprintf(stderr, "Panic! Unknown %s %d\n", str, var);
X    abort();
X}
END_OF_util.c
if test 6229 -ne `wc -c <util.c`; then
    echo shar: \"util.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 6 \(of 7\).
cp /dev/null ark6isdone
MISSING=""
for I in 1 2 3 4 5 6 7 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 7 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0