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