games@tekred.TEK.COM (06/29/88)
Submitted by: "Stanley T. Shebs" <shebs%defun@cs.utah.edu>
Comp.sources.games: Volume 4, Issue 90
Archive-name: xconq5/Part02
#! /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 2 (of 18)."
# Contents: X11.c init.c
# Wrapped by billr@saab on Wed Jun 29 08:55:29 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f X11.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"X11.c\"
else
echo shar: Extracting \"X11.c\" \(35753 characters\)
sed "s/^X//" >X11.c <<'END_OF_X11.c'
X/* Copyright (c) 1987, 1988 Stanley T. Shebs, University of Utah. */
X/* Copyright 1988 by Chris D. Peterson, MIT. */
X/* Many improvements by Tim Moore, 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: X11.c,v 1.1 88/06/21 12:30:00 shebs Exp $ */
X
X/* Interface implementations for the X11 version of xconq. */
X
X#include "config.h"
X#include "misc.h"
X#include "period.h"
X#include "side.h"
X#include "unit.h"
X#include "map.h"
X#include "global.h"
X
X/* careful of the path of the X header files. */
X
X#ifdef UNIX
X#include <signal.h> /* needed for ^C disabling */
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#endif UNIX
X
X/* various bitmap definitions. */
X
X#define dots_width 16
X#define dots_height 16
Xstatic char dots_bits[] = {
X 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
X
X#define mask_width 16
X#define mask_height 16
Xstatic char mask_bits[] = {
X 0xe0, 0x03, 0xd8, 0x0f, 0xb4, 0x19, 0x8a, 0x21,
X 0x86, 0x61, 0x85, 0x41, 0x83, 0xc1, 0xff, 0xff,
X 0xff, 0xff, 0x83, 0xc1, 0x82, 0xa1, 0x86, 0x61,
X 0x84, 0x51, 0x98, 0x2d, 0xf0, 0x1b, 0xc0, 0x07};
X
X#define curs_width 16
X#define curs_height 16
Xstatic char curs_bits[] = {
X 0xe0, 0x03, 0x98, 0x0c, 0x84, 0x10, 0x82, 0x20,
X 0x82, 0x20, 0x81, 0x40, 0x81, 0x40, 0xff, 0x7f,
X 0x81, 0x40, 0x81, 0x40, 0x82, 0x20, 0x82, 0x20,
X 0x84, 0x10, 0x98, 0x0c, 0xe0, 0x03, 0x00, 0x00};
X
X#define bomb1_width 32
X#define bomb1_height 32
Xstatic char bomb1_bits[] = {
X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X 0x00, 0xc0, 0x01, 0x00, 0x00, 0xf0, 0x07, 0x00,
X 0x00, 0xf0, 0x07, 0x00, 0x00, 0xf8, 0x0f, 0x00,
X 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xfc, 0x0f, 0x00,
X 0x00, 0xfe, 0x1f, 0x00, 0x00, 0xfe, 0x3f, 0x00,
X 0x00, 0xfe, 0x3f, 0x00, 0x00, 0xfc, 0x1f, 0x00,
X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
X
X#define bomb2_width 32
X#define bomb2_height 32
Xstatic char bomb2_bits[] = {
X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00,
X 0x00, 0xf8, 0x07, 0x00, 0x00, 0xfc, 0x0f, 0x00,
X 0x00, 0xfc, 0x1f, 0x00, 0x00, 0xfe, 0x1f, 0x00,
X 0x00, 0xfe, 0x3f, 0x00, 0x00, 0xfc, 0x1f, 0x00,
X 0x00, 0xfc, 0x0f, 0x00, 0x00, 0xf0, 0x07, 0x00,
X 0x00, 0xf0, 0x03, 0x00, 0x00, 0xe0, 0x03, 0x00,
X 0x00, 0xf0, 0x07, 0x00, 0x00, 0xf0, 0x07, 0x00,
X 0x00, 0xf0, 0x0f, 0x00, 0x00, 0xf0, 0x0f, 0x00,
X 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xf8, 0x1f, 0x00,
X 0x00, 0xf8, 0x1f, 0x00, 0x00, 0xfc, 0x1f, 0x00,
X 0x00, 0xff, 0x7f, 0x00, 0xc0, 0xff, 0xff, 0x03,
X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
X
X#define bomb3_width 32
X#define bomb3_height 32
Xstatic char bomb3_bits[] = {
X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X 0x00, 0x00, 0x00, 0x00, 0xfe, 0xe2, 0xa3, 0x3f,
X 0x00, 0xfc, 0x1f, 0x00, 0x3c, 0xff, 0x7f, 0x7c,
X 0x80, 0xff, 0xff, 0x00, 0xc0, 0xff, 0xff, 0x01,
X 0xc0, 0xff, 0xff, 0x01, 0xe0, 0xff, 0xff, 0x03,
X 0xe0, 0xff, 0xff, 0x03, 0xe0, 0xff, 0xff, 0x03,
X 0xe0, 0xff, 0xff, 0x01, 0xe0, 0xff, 0xff, 0x49,
X 0x82, 0xff, 0xff, 0x34, 0x14, 0xfe, 0x3f, 0x42,
X 0xe2, 0xff, 0x9f, 0x34, 0x40, 0xfe, 0x3f, 0x41,
X 0xbe, 0xfd, 0xdf, 0x1e, 0x00, 0xf8, 0x1f, 0x01,
X 0xfe, 0xfd, 0xdf, 0x7f, 0x00, 0xfc, 0x1f, 0x00,
X 0x00, 0xfc, 0x1f, 0x00, 0x00, 0xfc, 0x3f, 0x00,
X 0x00, 0xfe, 0x1f, 0x00, 0x00, 0xfe, 0x3f, 0x00,
X 0x00, 0xff, 0x3f, 0x00, 0xc0, 0xff, 0xff, 0x00,
X 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x7f,
X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
X
X#define bomb4_width 32
X#define bomb4_height 32
Xstatic char bomb4_bits[] = {
X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00,
X 0x00, 0x78, 0x10, 0x00, 0x00, 0x0f, 0x46, 0x00,
X 0x80, 0x61, 0x81, 0x00, 0xc0, 0x1c, 0x00, 0x01,
X 0x40, 0x02, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
X 0x20, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
X 0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
X 0x80, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
X 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
X 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
X 0x00, 0x01, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,
X 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
X
X/* This is the name of a family of programs, so argv[0] inadequate. */
X
X#define PROGRAMNAME "xconq"
X
X/* Name of default font - why is this wired in? */
X
X#define STANDARD "standard"
X
X/* Magic number meaning that this pixmap intentionally left blank. */
X
X#define NOPIXMAP 17
X
X#define INFOLINES 4
X#define DELAY 100000
X
X#define BH 32
X
X/* Use with caution - variable name "side" embedded! */
X
X#define sd() ((Screeno *) side->display)
X
X#define sdd() (((Screeno *) side->display)->disp)
X
Xtypedef unsigned int unint;
X
X/* GC rules are for different fonts etc, but not colors or bitmaps. */
X
Xtypedef struct a_screen {
X Display *disp;
X GC gc; /* a tmp graphics context for this display */
X GC flashgc; /* The gc for drawing the flash lines. */
X GC textgc; /* foreground on background text */
X GC icongc; /* icon graphics context */
X GC invicongc; /* icon gc inverted colors. */
X GC varicongc; /* This is an icon gc with variable fgcolor. */
X GC unitgc; /* unit bitmap printing gc. */
X GC unittextgc; /* unit text printing gc. */
X GC cleargc; /* The gc to use for clearing areas. */
X GC clearbitgc; /* gc for clearing bitmaps */
X XFontStruct *textfont; /* font for text display */
X XFontStruct *iconfont; /* utility font with assorted icons */
X XFontStruct *unitfont; /* font for unit characters */
X Pixmap bombpics[4]; /* mushroom clouds */
X Pixmap unitpics[MAXUTYPES]; /* used instead of font sometimes */
X Pixmap wbdots, bwdots; /* blue border and dotted backgrounds */
X Cursor curs; /* the cursor object itself */
X} Screeno;
X
Xextern int giventime;
X
X/* Random function declarations. */
X
XXFontStruct * open_font();
XPixmap load_bitmap();
Xvoid get_font_size();
XCursor make_cursor();
X
X/* The array of screen objects. */
X
XScreeno screens[MAXSIDES]; /* All the "screen objects" */
X
X/* Values of parameters generally tied to fonts and the like. */
X
Xint hw = 20;
Xint hh = 22;
Xint hch = 17;
Xint margin = 2;
Xint bd = 1;
X
Xint helpwinlines = 1; /* size of help window */
X
Xbool rootcursor; /* true if using parent window's cursor */
X
X/* Put in a default player, probably the invoker of the program. */
X/* An empty host name will confuse everybody. */
X
Xadd_default_player()
X{
X#ifdef UNIX
X add_player(TRUE, getenv("DISPLAY"));
X#endif UNIX
X}
X
X/* Ignore ^C if humans in the game, do it otherwise, including when the */
X/* last human player turns into a machine (this is called by option cmd). */
X/* Attempts to be more clever seem to be bad news. */
X
Xinit_sighandlers()
X{
X#ifdef UNIX
X if (numhumans > 0 && !Debug) {
X signal(SIGINT, SIG_IGN);
X } else {
X signal(SIGINT, SIG_DFL);
X }
X#endif UNIX
X}
X
X/* Note that the open_display function syncronizes the X server when the */
X/* Debug flag is set. */
X
Xopen_display(side)
XSide *side;
X{
X side->display = (long) &(screens[side_number(side)]);
X sdd() = XOpenDisplay(side->host);
X if (Debug) {
X XSynchronize(sdd(), TRUE);
X printf("Synching the X server.\n");
X }
X side->main = XCreateSimpleWindow(sdd(), DefaultRootWindow(sdd()),
X 50, 3, 100, 100,
X 3, white_color(side), black_color(side));
X return (sdd() != NULL);
X}
X
X/* A predicate that tests whether our display can safely be written to. */
X
Xactive_display(side)
XSide *side;
X{
X return (side && side->host && !side->lost && side->display);
X}
X
Xdisplay_width(side)
XSide *side;
X{
X return ((19 * XDisplayWidth(sdd(), 0)) / 20);
X}
X
Xdisplay_height(side)
XSide *side;
X{
X return ((19 * XDisplayHeight(sdd(), 0)) / 20);
X}
X
X/* Most X displays have enough screen to do a world map. */
X
Xworld_display(side) Side *side; { return TRUE; }
X
X/* Could use handlers for X failures... */
X
X/* Do misc setup thingies. */
X
X/* Do the rigmarole to convert all those short arrays into X-approved */
X/* Bitmaps. Note that this has to be for *each* display separately (!) */
X/* Also get the cursor shape. If the hardware can't hack the desired */
X/* cursor size, warn about it and just use the root window's cursor. */
X/* 0x0 cursor specs seem to be don't cares - machine can handle any size */
X/* X11 also needs gazillions of GCs, since we've got so many fonts and */
X/* colors and bitmaps. */
X
Xinit_misc(side)
XSide *side;
X{
X int u, w, h;
X unsigned long mask;
X XGCValues values;
X Pixmap mmask, mcurs, dots;
X GC gc;
X
X side->margin = margin;
X side->bd = bd;
X side->hw = hw;
X side->hh = hh;
X side->hch = hch;
X mask = GCForeground | GCBackground;
X values.foreground = side->fgcolor;
X values.background = side->bgcolor;
X gc = XCreateGC(sdd(), side->main, mask, &values);
X sd()->gc = XCreateGC(sdd(), side->main, mask, &values);
X sd()->flashgc = XCreateGC(sdd(), side->main, mask, &values);
X sd()->textgc = XCreateGC(sdd(), side->main, mask, &values);
X sd()->icongc = XCreateGC(sdd(), side->main, mask, &values);
X sd()->varicongc = XCreateGC(sdd(), side->main, mask, &values);
X sd()->unitgc = XCreateGC(sdd(), side->main, mask, &values);
X sd()->unittextgc = XCreateGC(sdd(), side->main, mask, &values);
X values.foreground = side->bgcolor;
X values.background = side->fgcolor;
X sd()->invicongc = XCreateGC(sdd(), side->main, mask, &values);
X values.function = GXclear;
X mask = GCFunction;
X sd()->cleargc = XCreateGC(sdd(), side->main, mask, &values);
X
X sd()->textfont = open_font(side, TEXTFONT, "TextFont", NULL);
X get_font_size(sd()->textfont, &(side->fw), &(side->fh) );
X sd()->iconfont = open_font(side, ICONFONT, "IconFont", sd()->textfont);
X get_font_size(sd()->iconfont, &(side->hw), &(side->hh) );
X if (period.fontname != NULL && strlen(period.fontname) > 0) {
X sd()->unitfont =
X open_font(side, period.fontname, "UnitFont", sd()->textfont);
X get_font_size(sd()->unitfont, &(side->uw), &(side->uh) );
X } else {
X sd()->unitfont =
X open_font(side, STANDARD, "UnitFont", sd()->textfont);
X get_font_size(sd()->unitfont, &(side->uw), &(side->uh) );
X }
X XSetFont(sdd(), sd()->textgc, sd()->textfont->fid);
X XSetFont(sdd(), sd()->icongc, sd()->iconfont->fid);
X mask = GCFillStyle | GCGraphicsExposures;
X values.fill_style = FillSolid;
X values.graphics_exposures = FALSE;
X XChangeGC(sdd(), sd()->unitgc, mask, &values);
X XSetFont(sdd(), sd()->unittextgc, sd()->unitfont->fid);
X XSetFont(sdd(), sd()->invicongc, sd()->iconfont->fid);
X XSetFont(sdd(), sd()->varicongc, sd()->iconfont->fid);
X XSetFunction(sdd(), sd()->flashgc, GXinvert);
X
X mmask = XCreateBitmapFromData(sdd(), side->main,
X mask_bits, mask_width, mask_height);
X mcurs = XCreateBitmapFromData(sdd(), side->main,
X curs_bits, curs_width, curs_height);
X
X dots = XCreateBitmapFromData(sdd(), side->main,
X dots_bits, dots_width, dots_height);
X
X sd()->bombpics[0] = XCreateBitmapFromData(sdd(), side->main,
X bomb1_bits, bomb1_width, bomb1_height);
X sd()->bombpics[1] = XCreateBitmapFromData(sdd(), side->main,
X bomb2_bits, bomb2_width, bomb2_height);
X sd()->bombpics[2] = XCreateBitmapFromData(sdd(), side->main,
X bomb3_bits, bomb3_width, bomb3_height);
X sd()->bombpics[3] = XCreateBitmapFromData(sdd(), side->main,
X bomb4_bits, bomb4_width, bomb4_height);
X for_all_unit_types(u) {
X if (utypes[u].bitmapname && (strlen(utypes[u].bitmapname) > 0)) {
X sd()->unitpics[u] = load_bitmap(side, utypes[u].bitmapname);
X } else {
X utypes[u].bitmapname = NULL;
X }
X }
X if (Debug) printf("Bitmaps stored ...\n");
X
X sd()->wbdots = XCreatePixmap(sdd(), side->main, dots_width, dots_height,
X DefaultDepth(sdd(), 0) );
X sd()->bwdots = XCreatePixmap(sdd(), side->main, dots_width, dots_height,
X DefaultDepth(sdd(), 0) );
X
X /* Since clearbitgc has to have a depth of 1 we'll */
X /* hang it off bombpics[0] */
X mask = GCFunction;
X values.function = GXclear;
X sd()->clearbitgc = XCreateGC(sdd(), sd()->bombpics[0], mask, &values);
X
X XSetForeground(sdd(), gc, side->fgcolor);
X XSetBackground(sdd(), gc, side->bgcolor);
X XSetStipple(sdd(), gc, dots);
X XSetFillStyle(sdd(), gc, FillOpaqueStippled);
X XFillRectangle(sdd(), sd()->wbdots, gc, 0, 0, dots_width, dots_height);
X
X XSetForeground(sdd(), gc, side->bgcolor);
X XSetBackground(sdd(), gc, side->fgcolor);
X XFillRectangle(sdd(), sd()->bwdots, gc, 0, 0, dots_width, dots_height);
X if (Debug) printf("Tiles stored ...\n");
X
X rootcursor = FALSE;
X XQueryBestCursor(sdd(), side->main, curs_width, curs_height, &w, &h);
X if (Debug) printf("Allowed cursor shape is %dx%d\n", w, h);
X if (w == curs_width && h == curs_height) {
X sd()->curs =
X make_cursor(sdd(), mcurs, mmask, white_color(side),
X black_color(side), 7, 7);
X
X } else {
X fprintf(stderr, "Warning: Can't have %dx%d cursors on \"%s\"!\n",
X curs_width, curs_height, side->host);
X fprintf(stderr, "Using default cursor...\n");
X rootcursor = TRUE;
X }
X if (Debug) printf("Cursor stored ...\n");
X XFreeGC(sdd(), gc);
X XFreePixmap(sdd(), dots);
X XFreePixmap(sdd(), mmask);
X XFreePixmap(sdd(), mcurs);
X}
X
X/* Since XCreatePixmapCursor() takes XColors and not pixel values we */
X/* have to look the colors associated with the foreground and */
X/* background pixel values up in the color table and pass them to */
X/* XCreatePixmapCursor(). */
X
XCursor make_cursor(dpy, curs, mask, foreground, background, x, y)
XDisplay *dpy;
XPixmap curs, mask;
Xunsigned long foreground, background;
Xunsigned int x, y;
X{
X XColor defs[2];
X
X defs[0].pixel = foreground;
X defs[1].pixel = background;
X XQueryColors(dpy, DefaultColormap(dpy, 0), defs, 2);
X return XCreatePixmapCursor(dpy, curs, mask, &defs[0], &defs[1], x, y);
X}
X
X/* Since font lookup is still not smart among Xs, this is a general routine */
X/* that can deal with unopenable, missing, etc, fonts, as well as the use of */
X/* .Xdefaults. One of the inputs is another font that can be substituted if */
X/* necessary. */
X
XXFontStruct *
Xopen_font(side, name, xdefault, altfont)
XSide *side;
Xchar *name, *xdefault;
XXFontStruct * altfont;
X{
X char *firstname, *altname;
X XFontStruct * font;
X
X if ((altname = XGetDefault(sdd(), PROGRAMNAME, xdefault)) != NULL)
X name = altname;
X firstname = name;
X if ((font = XLoadQueryFont(sdd(), name)) == NULL) {
X make_pathname(XCONQLIB, name, "snf", spbuf);
X name = spbuf;
X if ((font = XLoadQueryFont(sdd(), name)) == NULL) {
X fprintf(stderr, "Can't open fonts \"%s\" or \"%s\" on \"%s\"\n",
X firstname, name, side->host);
X if (altfont != NULL) {
X fprintf(stderr, "Substituting another font...\n");
X return altfont;
X } else {
X fprintf(stderr, "No font to substitute!!\n");
X exit(1);
X }
X }
X }
X if (Debug) printf("Opened font \"%s\" ...\n", name);
X return font;
X}
X
X/* Force X11 font fanciness into semblance of X10 font plainness. */
X
Xvoid
Xget_font_size(font, width, height)
XXFontStruct * font;
Xshort *width, *height;
X{
X *width = font->max_bounds.rbearing - font->min_bounds.lbearing;
X *height = font->max_bounds.ascent + font->min_bounds.descent;
X if (Debug) {
X printf("rbearing = %d lbearing = %d\n",
X (int)font->max_bounds.rbearing, (int)font->min_bounds.lbearing);
X printf("returning font size %d %d\n", (int)*width, (int)*height);
X }
X}
X
X/* Try to load a bitmap of the given name - can be either X11-only (.b11) */
X/* or X10 (.b) bitmaps, but prefer X11 flavor. */
X
XPixmap
Xload_bitmap(side, name)
XSide *side;
Xchar *name;
X{
X int w, h, junk, a;
X Pixmap rslt;
X
X make_pathname(NULL, name, "b11", spbuf);
X a = XReadBitmapFile(sdd(), side->main, spbuf, &w, &h, &rslt, &junk, &junk);
X if (a == BitmapSuccess) return rslt;
X make_pathname(XCONQLIB, name, "b11", spbuf);
X a = XReadBitmapFile(sdd(), side->main, spbuf, &w, &h, &rslt, &junk, &junk);
X if (a == BitmapSuccess) return rslt;
X make_pathname(XCONQLIB, name, "b", spbuf);
X a = XReadBitmapFile(sdd(), side->main, spbuf, &w, &h, &rslt, &junk, &junk);
X if (a == BitmapSuccess) return rslt;
X fprintf(stderr, "Bitmap name \"%s\" not found anywhere!\n", name);
X return (-1);
X}
X
X/* This routine has to be able to cope with window managers constraining */
X/* size. Actually, the main window was already opened when the display */
X/* was opened, so the name is not quite accurate! */
X
Xcreate_main_window(side)
XSide *side;
X{
X Pixmap dots;
X XSizeHints hints;
X
X XStoreName(sdd(), side->main, PROGRAMNAME);
X dots = (side->bonw ? sd()->bwdots : sd()->wbdots);
X XSetWindowBackgroundPixmap(sdd(), side->main, dots);
X
X hints.width = side->mw;
X hints.height = side->mh;
X hints.min_width = side->mw;
X hints.min_height = side->mh;
X hints.flags = PSize|PMinSize;
X XSetNormalHints(sdd(), side->main, &hints);
X}
X
X/* Help window is not necessarily a subwindow, though it might be sometimes. */
X
Xcreate_help_window(side)
XSide *side;
X{
X helpwinlines =
X max(45, (24 + period.numrtypes + period.numttypes + period.numutypes));
X
X side->help = XCreateSimpleWindow(sdd(), DefaultRootWindow(sdd()),
X 0, 0, 80*side->fw+1,
X helpwinlines*side->fh+1,
X 1, side->fgcolor, side->bgcolor);
X XStoreName(sdd(), side->help, "xconq-help");
X}
X
X/* Subwindow creator. */
X
Xcreate_window(side, x, y, w, h)
XSide *side;
Xint x, y, w, h;
X{
X return XCreateSimpleWindow(sdd(), side->main, x, y, w, h,
X 1, side->fgcolor, side->bgcolor);
X}
X
X/* Do little things necesary to make it all go, in this case mapping all */
X/* the windows (except help win). */
X
Xfixup_windows(side)
XSide *side;
X{
X XMapWindow(sdd(), side->main);
X XMapSubwindows(sdd(), side->main);
X if (!giventime) XUnmapWindow(sdd(), side->clock);
X if (!rootcursor) XDefineCursor(sdd(), side->map, sd()->curs);
X}
X
X/* Specify the sorts of input that will be allowed. */
X
Xenable_input(side)
XSide *side;
X{
X XSelectInput(sdd(), side->main, KeyPressMask|ExposureMask);
X XSelectInput(sdd(), side->map, ButtonPressMask|ExposureMask);
X XSelectInput(sdd(), side->help, KeyPressMask|ExposureMask);
X}
X
X/* Move windows and change their sizes to correspond with the new sizes of */
X/* viewports, etc */
X
Xreset_misc(side)
XSide *side;
X{
X Pixmap dots;
X XSizeHints hints;
X XGCValues values;
X unsigned int gcmask;
X
X dots = (side->bonw ? sd()->bwdots : sd()->wbdots);
X
X XResizeWindow(sdd(), side->main, side->mw, side->mh);
X hints.width = side->mw; hints.height = side->mh;
X hints.min_width = side->mw; hints.min_height = side->mh;
X hints.flags = PSize|PMinSize;
X XSetNormalHints(sdd(), side->main, &hints);
X
X XSetWindowBackgroundPixmap(sdd(), side->main, dots);
X XSetWindowBackground(sdd(), side->msg, side->bgcolor);
X XSetWindowBackground(sdd(), side->info, side->bgcolor);
X XSetWindowBackground(sdd(), side->prompt, side->bgcolor);
X XSetWindowBackground(sdd(), side->map, side->bgcolor);
X XSetWindowBackground(sdd(), side->timemode, side->bgcolor);
X XSetWindowBackground(sdd(), side->clock, side->bgcolor);
X XSetWindowBackground(sdd(), side->state, side->bgcolor);
X XSetWindowBackground(sdd(), side->help, side->bgcolor);
X XSetWindowBackground(sdd(), side->sides, side->bgcolor);
X XSetWindowBackground(sdd(), side->world, side->bgcolor);
X XSetWindowBorder(sdd(), side->msg, side->fgcolor);
X XSetWindowBorder(sdd(), side->info, side->fgcolor);
X XSetWindowBorder(sdd(), side->prompt, side->fgcolor);
X XSetWindowBorder(sdd(), side->map, side->fgcolor);
X XSetWindowBorder(sdd(), side->timemode, side->fgcolor);
X XSetWindowBorder(sdd(), side->clock, side->fgcolor);
X XSetWindowBorder(sdd(), side->state, side->fgcolor);
X XSetWindowBorder(sdd(), side->help, side->fgcolor);
X XSetWindowBorder(sdd(), side->sides, side->fgcolor);
X XSetWindowBorder(sdd(), side->world, side->fgcolor);
X
X gcmask = GCForeground | GCBackground;
X values.foreground = side->fgcolor;
X values.background = side->bgcolor;
X XChangeGC(sdd(), sd()->gc, gcmask, &values);
X XChangeGC(sdd(), sd()->flashgc, gcmask, &values);
X XChangeGC(sdd(), sd()->textgc, gcmask, &values);
X XChangeGC(sdd(), sd()->icongc, gcmask, &values);
X XChangeGC(sdd(), sd()->unitgc, gcmask, &values);
X values.foreground = side->bgcolor;
X values.background = side->fgcolor;
X XChangeGC(sdd(), sd()->invicongc, gcmask, &values);
X}
X
X/* Alter the size and position of a window. */
X
Xchange_window(side, win, x, y, w, h)
XSide *side;
XWindow win;
Xint x, y, w, h;
X{
X unsigned int mask;
X XWindowChanges changes;
X
X if (active_display(side)) {
X if (x >= 0) {
X if (w >= 0) {
X mask = CWX | CWY | CWWidth | CWHeight;
X changes.x = x; changes.y = y;
X changes.width = w; changes.height = h;
X } else {
X mask = CWX | CWY;
X changes.x = x; changes.y = y;
X }
X } else {
X mask = CWWidth | CWHeight;
X changes.width = w; changes.height = h;
X }
X }
X XConfigureWindow(sdd(), win, mask, &changes);
X}
X
X/* Return the number of colors - this is used to guess about monochromeness. */
X
Xdisplay_colors(side) Side *side; { return XDisplayCells(sdd(), 0); }
X
Xwhite_color(side) Side *side; { return WhitePixel(sdd(), 0); }
X
Xblack_color(side) Side *side; { return BlackPixel(sdd(), 0); }
X
X/* Get a color set up and warn if not getting what was asked for. */
X
Xlong
Xrequest_color(side, name)
XSide *side;
Xchar *name;
X{
X XColor c, avail;
X
X if (Debug) printf("Allocating %s\n", name);
X XAllocNamedColor(sdd(), DefaultColormap(sdd(), 0), name, &avail, &c);
X if (c.red != avail.red || c.green != avail.green || c.blue != avail.blue) {
X fprintf(stderr, "Warning: %s color not exact on \"%s\"!\n",
X name, side->host);
X fprintf(stderr, "Is %d %d %d instead of %d %d %d\n",
X avail.red, avail.green, avail.blue, c.red, c.green, c.blue);
X }
X return avail.pixel;
X}
X
X/* Main funnel for input returns both mouse and keyboard events, and maybe */
X/* other kinds eventually. Some events like window exposure are handled */
X/* strictly locally. */
X
Xget_input()
X{
X#ifdef SELECT2
X int i, mask;
X Side *side, *asides[32];
X
X mask = 0;
X for_all_sides(side) {
X if (active_display(side)) {
X mask |= (1 << ConnectionNumber(sdd()));
X asides[ConnectionNumber(sdd())] = side;
X while (XPending(sdd()) > 0) {
X process_events(side);
X }
X side->lasttime = time(0);
X }
X }
X if (Debug) {
X printf("Waiting for input from ");
X for_all_sides(side)
X if (active_display(side)) printf("%s ", side->host);
X printf("\n");
X }
X if (select(32, &mask, 0, 0, 0) < 0) {
X fprintf(stderr, "error in select!\n");
X abort();
X } else {
X for (i = 0; i < 32; ++i) {
X if (mask & (1 << i)) {
X process_events(asides[i]);
X asides[i]->timeleft -= (time(0) - asides[i]->lasttime);
X update_clock(asides[i]);
X }
X }
X }
X#else
X extern Side *curside;
X
X /* No simultaneity, but there's no portable way to do it, sigh */
X if (active_display(curside) && humanside(curside)) {
X if (Debug) printf("Waiting for input from %s\n", curside->host);
X process_events(curside);
X }
X#endif SELECT2
X}
X
X/* Look at a single event and fill the request structure appropriately. */
X
Xprocess_events(side)
XSide *side;
X{
X XEvent evt;
X char buf[BUFSIZE];
X int nchar, rawx, rawy;
X unsigned int junk;
X
X while (TRUE) {
X XNextEvent(sdd(), &evt);
X switch (evt.type) {
X case KeyPress:
X if (evt.xkey.window != side->main &&
X evt.xkey.window != side->help)
X return FALSE;
X nchar = XLookupString(&evt, buf, BUFSIZE, NULL, NULL);
X if (nchar > 0) {
X side->reqtype = KEYBOARD;
X side->reqch = *buf;
X if (Debug) printf("Host %s returns key '%c'\n",
X side->host, side->reqch);
X return;
X }
X break;
X case ButtonPress:
X if (evt.xbutton.window == side->map) {
X rawx = evt.xbutton.x; rawy = evt.xbutton.y;
X side->reqtype = MAPPOS;
X deform(side, rawx, rawy, &(side->reqx), &(side->reqy));
X if (Debug) printf("Host %s returns map %d %d\n",
X side->host, side->reqx, side->reqy);
X } else if (evt.xbutton.window == side->state) {
X rawx = evt.xbutton.x; rawy = evt.xbutton.y;
X side->reqtype = UNITTYPE;
X side->requtype = rawy / max(side->hh, side->fh);
X if (Debug) printf("Host %s returns unit type %d\n",
X side->host, side->requtype);
X }
X return;
X case Expose:
X if (evt.xexpose.window == side->main ||
X evt.xexpose.window == side->map) {
X flush_input(side);
X redraw(side);
X }
X if (Debug) printf("Host %s exposes itself\n", side->host);
X return FALSE;
X break;
X default:
X case_panic("event type", evt.type);
X break;
X }
X }
X}
X
X/* Freese everything until given side supplies input, use sparingly. */
X
Xfreeze_wait(side)
XSide *side;
X{
X XEvent evt;
X char buf[BUFSIZE];
X int nchar;
X
X if (Debug) printf("Waiting for a %s event\n", side->host);
X flush_input(side);
X while(TRUE) {
X XNextEvent(sdd(), &evt);
X if (evt.type == KeyPress) {
X nchar = XLookupString(&evt, buf, BUFSIZE, NULL, NULL);
X if (nchar > 0)
X return *buf;
X else
X return '\0';
X }
X }
X}
X
X/* Get rid of extra key/mouse clicks. */
X
Xflush_input(side)
XSide *side;
X{
X if (humanside(side)) XSync(sdd(), TRUE);
X}
X
X/* Trivial abstraction - sometimes other routines like to ensure all output */
X/* actually on the screen. */
X
Xflush_output(side)
XSide *side;
X{
X if (humanside(side)) XFlush(sdd());
X}
X
X/* General window clearing. */
X
Xclear_window(side, win)
XSide *side;
XWindow win;
X{
X XClearWindow(sdd(), win);
X}
X
X/* Draw a single horizontal constant-color bar on the world map. If part */
X/* would not be drawn because of the map's obliqueness, cut it in two and */
X/* wrap one of the pieces around. */
X
Xdraw_bar(side, x, y, len, color)
XSide *side;
Xint x, y, len, color;
X{
X int sx1, sx2, sy, sww;
X
X w_xform(side, x, y, &sx1, &sy);
X w_xform(side, x + len, y, &sx2, &sy);
X sww = side->mm * world.width;
X XSetFillStyle(sdd(), sd()->gc, FillSolid);
X XSetForeground(sdd(), sd()->gc, color);
X if (sx1 < sww && sx2 >= sww) {
X XFillRectangle(sdd(), side->world, sd()->gc,
X sx1, sy, (unint) sww - sx1, (unint) side->mm);
X XFillRectangle(sdd(), side->world, sd()->gc,
X 0, sy, (unint) sx2 - sww, (unint) side->mm);
X } else {
X sx1 %= sww;
X sx2 %= sww;
X XFillRectangle(sdd(), side->world, sd()->gc,
X sx1, sy, (unint) sx2 - sx1, (unint) side->mm);
X }
X}
X
X/* Invert the outline box on the world map. This is a little tricky, */
X/* because we want the lines to run through the middle of the world's */
X/* hexes, and because the line drawn should not overlap (or the overlaps */
X/* will be doubly inverted and look strange). */
X
Xinvert_box(side, vcx, vcy)
XSide *side;
Xint vcx, vcy;
X{
X int x1, y1, x2, y2, sx1, sy1, sx2, sy2, mm2 = side->mm/2;
X
X x1 = vcx - side->vw2 + side->vh2/2; y1 = vcy - side->vh2;
X x2 = vcx + side->vw2 - side->vh2/2; y2 = vcy + side->vh2;
X w_xform(side, x1, y1, &sx1, &sy1);
X w_xform(side, x2, y2, &sx2, &sy2);
X sx1 += mm2; sy1 -= mm2; sx2 += mm2; sy2 += mm2;
X XSetFunction(sdd(), sd()->gc, GXinvert);
X /* is this next call really necessary? */
X XSetLineAttributes(sdd(), sd()->gc, 1, LineSolid, CapButt, JoinMiter);
X XDrawLine(sdd(), side->world, sd()->gc, sx1, sy1, sx2, sy1);
X XDrawLine(sdd(), side->world, sd()->gc, sx2, sy1-1, sx2, sy2+1);
X XDrawLine(sdd(), side->world, sd()->gc, sx2, sy2, sx1, sy2);
X XDrawLine(sdd(), side->world, sd()->gc, sx1, sy2+1, sx1, sy1-1);
X XSetFunction(sdd(), sd()->gc, GXcopy);
X}
X
X/* This interfaces higher-level drawing decisions to the rendition of */
X/* individual pieces of display. */
X
Xdraw_terrain_row(side, sx, sy, buf, len, color)
XSide *side;
Xint sx, sy, len, color;
Xchar *buf;
X{
X sy += sd()->iconfont->max_bounds.ascent;
X XSetForeground(sdd(), sd()->icongc, color);
X XDrawString(sdd(), side->map, sd()->icongc, sx, sy, buf, len);
X}
X
X/* Flash a pair of lines up, slow enough to draw the eye, but not so slow */
X/* as to get in the way. */
X
Xflash_position(side, sx, sy)
XSide *side;
Xint sx, sy;
X{
X int i, sx1, sy1, sx2, sy2;
X
X sx1 = sx - 50 + side->hw/2; sy1 = sy + 50 + side->hch/2;
X sx2 = sx + 50 + side->hw/2; sy2 = sy - 50 + side->hch/2;
X XDrawLine(sdd(), side->map, sd()->flashgc, sx1, sy1, sx2, sy2);
X XDrawLine(sdd(), side->map, sd()->flashgc, sx1, sy2, sx2, sy1);
X flush_output(side);
X for (i = 0; i < DELAY; ++i);
X XDrawLine(sdd(), side->map, sd()->flashgc, sx1, sy1, sx2, sy2);
X XDrawLine(sdd(), side->map, sd()->flashgc, sx1, sy2, sx2, sy1);
X}
X
X/* The "cursor icon" is just a pair of special chars - nothing to do with */
X/* X's notion of cursors. */
X
Xdraw_cursor_icon(side, sx, sy)
XSide *side;
Xint sx, sy;
X{
X sy += sd()->iconfont->max_bounds.ascent;
X XDrawString(sdd(), side->map, sd()->invicongc, sx, sy, "[", 1);
X XSetForeground(sdd(), sd()->icongc, side->fgcolor);
X XDrawString(sdd(), side->map, sd()->icongc, sx, sy, "]", 1);
X}
X
X/* Draw the icon for a hex (given as a char). */
X
Xdraw_hex_icon(side, win, sx, sy, color, ch)
XSide *side;
XWindow win;
Xint sx, sy, color;
Xchar ch;
X{
X XSetForeground(sdd(), sd()->varicongc, color);
X sy += sd()->iconfont->max_bounds.ascent;
X XDrawString(sdd(), win, sd()->varicongc, sx, sy, &ch, 1);
X}
X
X/* Draw the number of an unfriendly side (never called for own units). */
X
Xdraw_side_number(side, win, sx, sy, n, color)
XSide *side;
XWindow win;
Xint sx, sy, n, color;
X{
X char ch = n + '0';
X
X if (n >= 0) {
X XSetForeground(sdd(), sd()->varicongc, color);
X sy += sd()->iconfont->max_bounds.ascent;
X XDrawString(sdd(), win, sd()->varicongc, sx, sy, &ch, 1);
X }
X}
X
Xdraw_blast_icon(side, win, sx, sy, type, color)
XSide *side;
XWindow win;
Xint sx, sy, color;
Xchar type;
X{
X char buf[1];
X
X XSetForeground(sdd(), sd()->varicongc, color);
X buf[0] = type;
X sy += sd()->iconfont->max_bounds.ascent;
X XDrawString(sdd(), win, sd()->varicongc, sx, sy, buf, 1);
X}
X
X/* Flash the player's screen in an unmistakable way. */
X
Xinvert_whole_map(side)
XSide *side;
X{
X int sw = side->vw * side->hw, sh = side->vh * side->hh;
X
X /* GC needs to be set for inverted drawing */
X XDrawRectangle(sdd(), side->map, sd()->gc, 0, 0, sw, sh);
X flush_output(side);
X}
X
X/* Draw just one of the mushroom cloud shapes. */
X
Xdraw_mushroom(side, x, y, i)
XSide *side;
Xint x, y, i;
X{
X int sx, sy;
X int color;
X
X color = ((side->monochrome || i == 3) ? side->fgcolor : side->bgcolor);
X xform(side, unwrap(side, x), y, &sx, &sy);
X XSetForeground(sdd(), sd()->unitgc, color);
X XSetClipMask(sdd(), sd()->unitgc, sd()->bombpics[i]);
X XSetClipOrigin(sdd(), sd()->unitgc, sx-BH/4, sy-BH/2);
X XFillRectangle(sdd(), side->map, sd()->unitgc, sx-BH/4, sy-BH/2, BH, BH);
X flush_output(side);
X}
X
X/* Confirm that we can indeed do bar graph displays. */
X
Xbar_graphs(side) Side *side; { return TRUE; }
X
X/* Do yet another X-toolkit-type function. This draws a bar graph. */
X
Xdraw_graph(side, number, amount, total, critical, title)
XSide *side;
Xint number, amount, total, critical;
X{
X int boxwidth, boxheight, boxoffset, boxleft, barwidth, barheight;
X
X if (total > 0) {
X boxwidth = 5*side->fw;
X boxheight = (INFOLINES-1)*side->fh - 2*side->margin;
X boxoffset = side->margin;
X boxleft = 30*side->fw + number * boxwidth;
X barwidth = boxwidth / 3;
X barheight = (boxheight * amount) / total;
X XSetForeground(sdd(), sd()->gc, side->fgcolor);
X XFillRectangle(sdd(), side->info, sd()->gc,
X boxleft + boxwidth/3 - 1, boxoffset - 1,
X barwidth + 2, boxheight + 2);
X XSetForeground(sdd(), sd()->gc, side->bgcolor);
X XFillRectangle(sdd(), side->info, sd()->gc,
X boxleft + boxwidth/3, boxoffset,
X barwidth, boxheight);
X if ( amount > critical)
X XSetForeground(sdd(), sd()->gc, side->goodcolor);
X else
X XSetForeground(sdd(), sd()->gc, side->badcolor);
X XFillRectangle(sdd(), side->info, sd()->gc,
X boxleft + boxwidth/3, boxoffset + boxheight - barheight,
X barwidth, barheight);
X draw_text(side, side->info,
X boxleft+(boxwidth-strlen(title)*side->fw)/2,
X (INFOLINES-1)*side->fh, title, side->fgcolor);
X }
X}
X
X/* Splash a unit image (either bitmap or font char) onto some window. */
X
Xdraw_unit_icon(side, win, x, y, u, color)
XSide *side;
XWindow win;
Xint x, y, u, color;
X{
X char buf[1];
X
X y += 3; /* fudge factor to make x11 look */
X x += 2; /* like X10 (ugh). */
X if (utypes[u].bitmapname != NULL ) {
X XSetForeground(sdd(), sd()->unitgc, color);
X XSetClipMask(sdd(), sd()->unitgc, sd()->unitpics[u]);
X XSetClipOrigin(sdd(), sd()->unitgc, x, y);
X XFillRectangle(sdd(), win, sd()->unitgc, x, y, side->uw, side->uh);
X } else {
X XSetForeground(sdd(), sd()->unittextgc, color);
X buf[0] = utypes[u].uchar;
X y += sd()->unitfont->max_bounds.ascent;
X XDrawString(sdd(), win, sd()->unittextgc, x, y, buf, 1);
X }
X}
X
X/* General text drawer. */
X
Xdraw_text(side, win, x, y, str, color)
XSide *side;
XWindow win;
Xint x, y, color;
Xchar *str;
X{
X y += sd()->textfont->max_bounds.ascent;
X if (color != side->bgcolor) {
X XSetForeground(sdd(), sd()->textgc, color);
X XDrawImageString(sdd(), win, sd()->textgc, x, y, str, strlen(str));
X } else {
X XSetForeground(sdd(), sd()->textgc, side->bgcolor);
X XSetBackground(sdd(), sd()->textgc, side->fgcolor);
X XDrawImageString(sdd(), win, sd()->textgc, x, y, str, strlen(str));
X XSetBackground(sdd(), sd()->textgc, side->bgcolor);
X }
X}
X
X/* Draw a line through some side's title. */
X
Xdraw_scratchout(side, pos)
XSide *side;
Xint pos;
X{
X XSetForeground(sdd(), sd()->textgc, side->fgcolor);
X XDrawLine(sdd(), side->sides, sd()->textgc, 0, pos, 30*side->fw, pos);
X}
X
X/* Beep the beeper! */
X
Xbeep(side)
XSide *side;
X{
X XBell(sdd(), 0);
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
Xreveal_help(side)
XSide *side;
X{
X XEvent evt;
X
X XMapWindow(sdd(), side->help);
X /* wait until this window is exposed to return. */
X XWindowEvent(sdd(), side->help, ExposureMask, &evt);
X return TRUE;
X}
X
Xconceal_help(side)
XSide *side;
X{
X XUnmapWindow(sdd(), side->help);
X flush_output(side);
X}
X
X/* Shut a single display down, but only if there's one to operate on. */
X/* Hit the display slot, for safety. */
X
Xclose_display(side)
XSide *side;
X{
X XCloseDisplay(sdd());
X side->display = (long) NULL;
X}
X
END_OF_X11.c
if test 35753 -ne `wc -c <X11.c`; then
echo shar: \"X11.c\" 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\" \(15558 characters\)
sed "s/^X//" >init.c <<'END_OF_init.c'
X/* Copyright (c) 1987, 1988 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.2 88/06/28 10:06:13 shebs Exp $ */
X
X/* Initialization is complicated, because xconq needs lots of setup for */
X/* maps, units, sides, and the like. The data must also be able to come */
X/* from saved games, scenarios, bare maps in files, period descriptions, */
X/* or be synthesized if necessary. */
X
X#include "config.h"
X#include "misc.h"
X#include "dir.h"
X#include "period.h"
X#include "side.h"
X#include "unit.h"
X#include "map.h"
X#include "global.h"
X
Xextern char *rawfilenames[];
X
Xextern int numfiles, giventime;
X
Xint good_place(); /* to make gcc happy */
X
X/* Keep track of whether each sort of data has been loaded or not. */
X/* The version isn't important enough to need any sort of flag. */
X
Xbool periodmade, mapmade, globalsmade, sidesmade, unitsmade;
Xbool populations = FALSE; /* true if populace ever nonzero */
X
Xint favterr[MAXUTYPES]; /* "favorite terrain" of each unit type */
Xint numhexes[MAXUTYPES]; /* temporaries used by country placement */
Xint countryx[MAXSIDES], countryy[MAXSIDES]; /* centers of countries */
Xint snameused[MAXSNAMES]; /* flags side names already used by somebody */
Xint unameused[MAXUNAMES]; /* flags unit names already used */
X
X/* Either load a saved game or load mapfiles from cmd line and then make up */
X/* any stuff that didn't get loaded. */
X
Xinit_game()
X{
X int i;
X
X periodmade = mapmade = globalsmade = sidesmade = unitsmade = FALSE;
X
X if (saved_game()) {
X printf("Restoring from \"%s\" ...\n", SAVEFILE);
X load_mapfile(SAVEFILE);
X } else {
X for (i = 0; i < numfiles; ++i) {
X load_mapfile(rawfilenames[i]);
X }
X if (!mapmade) {
X printf("Please wait six days while I create the world...\n");
X make_up_map();
X }
X if (!globalsmade) {
X make_up_globals();
X }
X if (!sidesmade) {
X make_up_sides();
X }
X if (numsides <= 0) {
X fprintf(stderr, "No player sides in this game!\n");
X exit(1);
X } else if (numsides < numgivens) {
X fprintf(stderr,
X "Warning: only made %d of the %d sides requested.\n",
X numsides, numgivens);
X }
X if (!unitsmade) {
X make_up_units();
X }
X }
X init_unit_views();
X fixup_things();
X printf("\nThe time is %s.\n", period.name);
X}
X
X/* Sort out the mess created by loading some things and creating others. */
X/* Should only be possible to start with 0 units when building a scenario. */
X/* Need to make friends and enemies; normally the machine players gang up */
X/* on the humans. */
X
Xfixup_things()
X{
X bool hasany;
X int x, y;
X Unit *unit;
X Side *side, *side2;
X
X if (period.scale != world.scale) {
X fprintf(stderr,
X "Reality check: Period is %d km/hex but map is %d km/hex.\n",
X period.scale, world.scale);
X }
X if (no_statistics()) {
X for_all_units(unit) {
X if (!neutral(unit)) unit->side->balance[unit->type][FIRSTUNIT]++;
X }
X }
X for_all_sides(side) {
X side->timeleft = giventime;
X hasany = FALSE;
X for_all_units(unit) {
X if (unit->side == side) {
X hasany = TRUE;
X break;
X }
X }
X if (!hasany && (unit = random_start_unit()) != NULL) {
X unit_changes_side(unit, side, FIRSTUNIT, -1);
X unit->trueside = unit->side;
X set_product(unit, period.firstptype);
X set_schedule(unit);
X }
X }
X for_all_sides(side) {
X for_all_sides(side2) {
X if (neutral_side(side, side2)) {
X if (side->host != NULL || side2->host != NULL)
X declare_war(side, side2);
X else
X declare_alliance(side, side2);
X }
X }
X }
X /* this slowness is necessary to solve chicken/egg problems of loading */
X /* units and sides from files... */
X if (period.allseen || world.known) {
X for_all_sides(side) {
X for (x = 0; x < world.width; ++x) {
X for (y = 0; y < world.height; ++y) {
X set_side_view(side, x, y, EMPTY);
X if ((unit = unit_at(x, y)) != NULL) {
X if (utypes[unit->type].alreadyseen ||
X utypes[unit->type].seealways ||
X unit->side == side) {
X see_exact(side, x, y);
X }
X if (utypes[unit->type].seealways) {
X set_cover(side, x, y, 100);
X }
X }
X }
X }
X }
X }
X}
X
Xiview_hex(x, y)
Xint x, y;
X{
X Unit *unit;
X
X set_side_view(tmpside, x, y, EMPTY);
X if ((unit = unit_at(x, y)) != NULL) {
X if (cover(tmpside, x, y) > 0 || utypes[unit->type].alreadyseen) {
X see_exact(tmpside, unit->x, unit->y);
X }
X }
X}
X
Xinit_unit_views()
X{
X Unit *unit;
X
X for_all_units(unit) {
X if (!neutral(unit)) {
X see_exact(unit->side, unit->x, unit->y);
X if (period.knownradius > 0) {
X tmpside = unit->side;
X apply_to_area(unit->x, unit->y, period.knownradius, iview_hex);
X }
X }
X }
X}
X
Xno_statistics()
X{
X int u;
X Side *side = sidelist;
X
X for_all_unit_types(u) if (side->balance[u][FIRSTUNIT] > 0) return FALSE;
X return TRUE;
X}
X
X/* Invent global values as necessary. */
X
Xmake_up_globals()
X{
X if (Debug) printf("Going to make up some globals ...\n");
X global.time = 0;
X global.endtime = DEFAULTTURNS;
X global.setproduct = TRUE;
X global.leavemap = FALSE;
X global.numconds = 0;
X if (Debug) printf("... Done making up globals.\n");
X}
X
X/* Create some random sides with default characteristics. */
X
Xmake_up_sides()
X{
X int i;
X Side *side;
X
X if (Debug) printf("Going to make up some sides ...\n");
X for (i = 0; i < MAXSNAMES; ++i) snameused[i] = FALSE;
X for (i = 0; i < numgivens; ++i) {
X side = create_side(random_side_name(), humans[i], hosts[i]);
X /* Pretty bad if side creation fails... */
X if (side == NULL) abort();
X }
X if (Debug) printf("... Done making up sides.\n");
X}
X
X/* If no units supplied with the map, then make some up and place them. */
X/* There is an option to start with one or with a country. */
X
Xmake_up_units()
X{
X int u, t, i;
X
X if (Debug) printf("Going to make up some units ...\n");
X for_all_unit_types(u) {
X favterr[u] = 0; /* doesn't really matter which one */
X for_all_terrain_types(t) {
X if (utypes[u].favored[t] > utypes[u].favored[favterr[u]])
X favterr[u] = t;
X }
X }
X /* Check for existence of favorite terrain on map */
X for (i = 0; i < MAXUNAMES; ++i) unameused[i] = FALSE;
X place_countries();
X place_neutrals();
X if (Debug) printf("... Done making up units.\n");
X}
X
X/* Place all the units belonging to countries. Once placed, set ownership */
X/* and production appropriately. */
X
Xplace_countries()
X{
X int x0, y0, u, i, num, first = period.firstutype, numleft[MAXUTYPES];
X Unit *unit;
X Side *side;
X
X for_all_sides(side) {
X find_a_place(&x0, &y0);
X if (Debug) printf("Country at %d,%d\n", x0, y0);
X countryx[side_number(side)] = x0; countryy[side_number(side)] = y0;
X place_inhabitants(side, x0, y0);
X if (first != NOTHING) {
X unit = create_unit(first, random_unit_name(first));
X occupy_hex(unit, x0, y0);
X init_supply(unit);
X unit_changes_side(unit, side, FIRSTUNIT, -1);
X unit->trueside = unit->side;
X set_product(unit, period.firstptype);
X set_schedule(unit);
X }
X for_all_unit_types(u) {
X num = utypes[u].incountry;
X if (first == u) num--;
X numleft[u] = num;
X for (i = 0; i < num; ++i) {
X unit = create_unit(u, random_unit_name(u));
X if (place_unit(unit, x0, y0)) {
X numleft[u]--;
X if (first == NOTHING) {
X unit_changes_side(unit, side, FIRSTUNIT, -1);
X unit->trueside = unit->side;
X }
X } else {
X kill_unit(unit, -1);
X }
X }
X }
X /* second pass for units that have to be occupants */
X for_all_unit_types(u) {
X for (i = 0; i < numleft[u]; ++i) {
X unit = create_unit(u, random_unit_name(u));
X if (place_unit(unit, x0, y0)) {
X if (first == NOTHING) {
X unit_changes_side(unit, side, FIRSTUNIT, -1);
X unit->trueside = unit->side;
X } else {
X /* give up finally - needs to be more informative */
X fprintf(stderr, "Can't place a %s!\n", utypes[u].name);
X exit(1);
X }
X }
X }
X }
X }
X}
X
X/* Work hard to find a place for a side's country. First make some random *
X/* trials, then start searching from the "center" of the map outwards. */
X/* If neither approach works, things are too screwed up to keep going. */
X
Xfind_a_place(cxp, cyp)
Xint *cxp, *cyp;
X{
X int tries, x, y, diam = (2 * period.countrysize + 1);
X
X for (tries = 0; tries < 200; ++tries) {
X x = random(world.width);
X x = wrap(x);
X y = random(world.height - diam) + period.countrysize;
X if (good_place(x, y)) {
X *cxp = x; *cyp = y;
X if (Debug) printf("Country placed on try %d\n", tries);
X return;
X }
X }
X if (search_area(world.width/2, world.height/2,
X max(world.width, world.height), good_place, cxp, cyp)) {
X if (Debug) printf("Country placed after search\n");
X return;
X } else {
X fprintf(stderr, "Can't place all the countries!\n");
X fprintf(stderr, "Try bigger maps or fewer sides next time.\n");
X exit(1);
X }
X}
X
X/* Decide whether the given location is desirable for a country. It should */
X/* not be too near or too far from other sides' countries, and there must be */
X/* enough terrain to place all the initial units. In addition, the center */
X/* of the country must have the right terrain for the firstutype. */
X
Xcount_hexes(x, y)
Xint x, y;
X{
X int u, terr = terrain_at(x, y);
X
X for_all_unit_types(u) if (terr == favterr[u]) numhexes[u]++;
X}
X
Xgood_place(cx, cy)
Xint cx, cy;
X{
X bool toofar = TRUE, notfirst = FALSE;
X int c, px, py, t, u, x, y, toplace, allhexes, first = period.firstutype;
X
X for (c = 0; c < numsides; ++c) {
X px = countryx[c]; py = countryy[c];
X if (px > 0 && py > 0) {
X notfirst = TRUE;
X if (distance(cx, cy, px, py) < period.mindistance) return FALSE;
X if (distance(cx, cy, px, py) < period.maxdistance) toofar = FALSE;
X }
X }
X if (toofar && notfirst) return FALSE;
X if (first != NOTHING && terrain_at(cx, cy) != favterr[first])
X return FALSE;
X toplace = allhexes = 0;
X for_all_unit_types(u) numhexes[u] = 0;
X apply_to_area(cx, cy, period.countrysize, count_hexes);
X for_all_unit_types(u) {
X if (utypes[u].incountry > numhexes[u]) return FALSE;
X toplace += utypes[u].incountry;
X allhexes += numhexes[u];
X }
X return (toplace < allhexes);
X}
X
X/* Place the populace on appropriate terrain within the country. */
X/* If countries overlap, then flip coins to decide about intermix (heh-heh, */
X/* so it resembles 17th-century Germany - more fun that way!). */
X/* The loops are a standard regular hexagon filler. */
X
Xplace_inhabitants(side, x0, y0)
XSide *side;
Xint x0, y0;
X{
X int x, y, x1, y1, x2, y2, dist = period.countrysize;
X
X y1 = interior(y0 - dist);
X y2 = interior(y0 + dist);
X for (y = y1; y <= y2; ++y) {
X x1 = x0 - (y < y0 ? (y - y1) : dist);
X x2 = x0 + (y > y0 ? (y2 - y) : dist);
X for (x = x1; x <= x2; ++x) {
X if (ttypes[terrain_at(wrap(x), y)].inhabitants) {
X populations = TRUE;
X if (unpopulated(wrap(x), y) || flip_coin()) {
X set_people_at(wrap(x), y, 8+side_number(side));
X }
X }
X }
X }
X}
X
X/* The basic conditions that *must* be met by an initial unit placement. */
X
Xint tmputype;
X
Xvalid_place(x, y)
Xint x, y;
X{
X Unit *unit = unit_at(x, y);
X
X return ((unit == NULL && utypes[tmputype].favored[terrain_at(x, y)] > 0) ||
X (unit != NULL && could_carry(unit->type, tmputype)));
X}
X
X/* Put a unit down somewhere in the designated area, following constraints */
X/* on terrain and adjacency. Returns success of placement. */
X
X/* "favterr" is poorly and unrobustly handled here... */
X
Xplace_unit(unit, cx, cy)
XUnit *unit;
Xint cx, cy;
X{
X bool canmove = FALSE;
X int u = unit->type, t, tries, x, y, chance, r, favterr = 0;
X int csize = period.countrysize;
X
X for_all_terrain_types(t) {
X if (could_move(u, t))
X canmove = TRUE;
X if (utypes[u].favored[t] > utypes[u].favored[favterr])
X favterr = t;
X }
X tmputype = u;
X for (tries = 0; tries < 500; ++tries) {
X x = random(2*csize+1) + cx - csize; x = wrap(x);
X y = random(2*csize+1) + cy - csize; y = interior(y);
X if (valid_place(x, y) && distance(cx, cy, x, y) <= csize) {
X chance = 100;
X t = terrain_at(x, y);
X if (canmove && !could_move(u, t)) chance -= 90;
X for_all_resource_types(r) {
X if (utypes[u].produce[r] > 0 && utypes[u].productivity[t] == 0)
X chance -= 20;
X }
X if (adj_unit(x, y)) chance -= 70;
X if (probability(chance)) {
X occupy_hex(unit, x, y);
X init_supply(unit);
X if (Debug) printf("Unit placed on try %d\n", tries);
X return TRUE;
X }
X }
X }
X if (search_area(cx, cy, csize, valid_place, &x, &y)) {
X occupy_hex(unit, x, y);
X init_supply(unit);
X if (Debug) printf("Unit placed after search\n");
X return TRUE;
X }
X return FALSE;
X}
X
X/* The number of neutral units is given by a parameter, and adjusted by */
X/* the number of units assigned to specific countries. The number is at */
X/* least 1 (if nonzero density), even for small maps. */
X
Xplace_neutrals()
X{
X int u, num, i;
X
X for_all_unit_types(u) {
X if (utypes[u].density > 0) {
X num = (((utypes[u].density * world.width * world.height) / 10000) -
X (numsides * utypes[u].incountry));
X num = max(1, num);
X for (i = 0; i < num; ++i) {
X place_neutral(create_unit(u, random_unit_name(u)));
X }
X }
X }
X}
X
X/* Neutral places should be uncommon in hostile terrain. If we can't find */
X/* a place, just blow it off and go to the next one. */
X
Xplace_neutral(unit)
XUnit *unit;
X{
X int tries, x, y, u = unit->type;
X
X for (tries = 0; tries < 500; ++tries) {
X x = random(world.width); y = random(world.height - 2) + 1;
X if ((probability(utypes[u].favored[terrain_at(x, y)])) &&
X (unit_at(x, y) == NULL) &&
X (!adj_unit(x, y) || flip_coin())) {
X occupy_hex(unit, x, y);
X init_supply(unit);
X return;
X }
X }
X kill_unit(unit, ENDOFWORLD);
X}
X
X/* True if anybody already on given hex or adjacent to it. */
X
Xadj_unit(x, y)
Xint x, y;
X{
X int d, x1, y1;
X
X for_all_directions(d) {
X x1 = wrap(x + dirx[d]); y1 = y + diry[d];
X if (unit_at(x1, y1)) return TRUE;
X }
X return FALSE;
X}
X
X/* Give the unit what it is declared to have stockpiled already. */
X
Xinit_supply(unit)
XUnit *unit;
X{
X int r, u = unit->type;
X
X for_all_resource_types(r) {
X unit->supply[r] =
X (utypes[u].storage[r] * utypes[u].stockpile[r]) / 100;
X }
X}
X
X/* Pick any name not already used in the giant array of unit names. */
X/* First try randomly, then sequentially. */
X
Xchar *
Xrandom_unit_name(u)
Xint u;
X{
X int i, n;
X
X if (utypes[u].named) {
X for (i = 0; i < period.numunames; ++i) {
X if (!unameused[(n = random(period.numunames))]) {
X unameused[n] = TRUE;
X return unames[n];
X }
X }
X for (i = 0; i < period.numunames; ++i) {
X if (!unameused[i]) {
X unameused[i] = TRUE;
X return unames[i];
X }
X }
X return NULL;
X } else {
X return NULL;
X }
X}
X
X/* Pick a side name not already used. Don't get uptight if we ran out of */
X/* names; perhaps a unit will lend a name, and certainly the players will */
X/* notice and change side names manually! */
X
Xchar *
Xrandom_side_name()
X{
X int i, n;
X
X for (i = 0; i < period.numsnames; ++i) {
X if (!snameused[(n = random(period.numsnames))]) {
X snameused[n] = TRUE;
X return snames[n];
X }
X }
X for (i = 0; i < period.numsnames; ++i) {
X if (!snameused[i]) {
X snameused[i] = TRUE;
X return snames[i];
X }
X }
X return "???";
X}
X
X/* Quicky test needed in a couple places. */
X
Xsaved_game()
X{
X FILE *fp;
X
X if ((fp = fopen(SAVEFILE, "r")) != NULL) {
X fclose(fp);
X return TRUE;
X } else {
X return FALSE;
X }
X}
END_OF_init.c
if test 15558 -ne `wc -c <init.c`; then
echo shar: \"init.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 2 \(of 18\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 18 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0