empire sources (part 6 of 6)

Charles Simmons chuck at amdahl.uts.amdahl.com
Mon Apr 11 11:01:36 AEST 1988



# This is a shell archive.  Remove anything before this line, then
# unpack it by saving it in a file and typing "sh file".  (Files
# unpacked will be owned by you and have default permissions.)
#
# This archive contains:
# term.c README extern.h attack.c math.c makefile MANIFEST

echo x - term.c
sed -e 's/^X//' > "term.c" << '//E*O*F term.c//'
X/* %W% %G% %U% - (c) Copyright 1987, 1988 Chuck Simmons */
X
X/*
X *    Copyright (C) 1987, 1988 Chuck Simmons
X * 
X * See the file COPYING, distributed with empire, for restriction
X * and warranty information.
X */
X
X/*
Xterm.c -- this file contains various routines used to control the
Xuser communications area of the terminal.  This area consists of
Xthe top 3 lines of the terminal where messages are displayed to the
Xuser and input is acquired from the user.
X
XThere are two types of output in this area.  One type is interactive
Xoutput.  This consists of a prompt line and an error message line.
XThe other type of output is informational output.  The user must
Xbe given time to read informational output.
X
XWhenever input is received, the top three lines are cleared and the
Xscreen refreshed as the user has had time to read these lines.  We
Xalso clear the 'need_delay' flag, saying that the user has read the
Xinformation on the screen.
X
XWhen information is to be displayed, if the 'need_delay' flag is set,
Xwe refresh the screen and pause momentarily to give the user a chance
Xto read the lines.  The new information is then displayed, and the
X'need_delay' flag is set.
X*/
X
X#include <stdio.h>
X#include <curses.h>
X#include <ctype.h>
X
X#include "empire.h"
X#include "extern.h"
X
Xstatic int need_delay;
X
Xvoid
X/* VARARGS1 */
Xpdebug (s, a, b, c, d, e, f, g, h)
Xchar *s;
Xint a, b, c, d, e, f, g, h;
X{
X	if (!print_debug) return;
X	comment (s, a, b, c, d, e, f, g, h);
X}
X
X/*
XHere are routines that handle printing to the top few lines of the
Xscreen.  'topini' should be called at initialization, and whenever
Xwe finish printing information to the screen.
X*/
X
Xvoid
Xtopini()
X{
X	info (0, 0, 0);
X}
X/*
XWrite a message to one of the top lines.
X*/
X
Xvoid
X/* VARARGS2 */
Xtopmsg(linep, buf, a, b, c, d, e, f, g, h)
Xint linep;
Xchar *buf;
Xint a, b, c, d, e, f, g, h;
X{
X	if (linep < 1 || linep > NUMTOPS)
X		linep = 1;
X	(void) move (linep - 1, 0);
X	
X	if (buf != NULL && strlen (buf) > 0)
X		addprintf (buf, a, b, c, d, e, f, g, h);
X	
X	(void) clrtoeol ();
X}
X
X/*
XPrint a prompt on the first message line.
X*/
X
Xvoid
X/* VARARGS1 */
Xprompt (buf, a, b, c, d, e, f, g, h)
Xchar *buf;
Xint a, b, c, d, e, f, g, h;
X{
X	topmsg (1, buf, a, b, c, d, e, f, g, h);
X}
X
X/*
XPrint an error message on the second message line.
X*/
X
Xvoid
X/* VARARGS1 */
Xerror (buf, a, b, c, d, e, f, g, h)
Xchar *buf;
Xint a, b, c, d, e, f, g, h;
X{
X	topmsg (2, buf, a, b, c, d, e, f, g, h);
X}
X
X/*
XPrint out extra information.
X*/
X
Xvoid
X/* VARARGS1 */
Xextra (buf, a, b, c, d, e, f, g, h)
Xchar *buf;
Xint a, b, c, d, e, f, g, h;
X{
X	topmsg (3, buf, a, b, c, d, e, f, g, h);
X}
X
X/*
XPrint out a generic error message.
X*/
X
Xvoid
Xhuh ()
X{
X	error ("Type H for Help.");
X}
X
X/*
XDisplay information on the screen.  If the 'need_delay' flag is set,
Xwe force a delay, then print the information.  After we print the
Xinformation, we set the need_delay flag.
X*/
X
Xvoid
Xinfo (a, b, c)
Xchar *a, *b, *c;
X{
X	if (need_delay) delay ();
X	topmsg (1, a);
X	topmsg (2, b);
X	topmsg (3, c);
X	need_delay = (a || b || c);
X}
X
Xvoid
Xset_need_delay () {
X	need_delay = 1;
X}
X
Xvoid
X/* VARARGS1 */
Xcomment (buf, a, b, c, d, e, f, g, h)
Xchar *buf;
Xint a, b, c, d, e, f, g, h;
X{
X	if (need_delay) delay ();
X	topmsg (1, 0);
X	topmsg (2, 0);
X	topmsg (3, buf, a, b, c, d, e, f, g, h);
X	need_delay = (buf != 0);
X}
X	
X/*
XGet a string from the user, echoing characters all the while.
X*/
X
Xvoid
Xget_str (buf, sizep)
Xchar *buf;
Xint sizep;
X{
X	(void) echo();
X	get_strq(buf, sizep);
X	(void) noecho();
X}
X
X/*
XGet a string from the user, ignoring the current echo mode.
X*/
X
Xvoid
Xget_strq (buf, sizep)
Xchar *buf;
Xint sizep;
X{
X	sizep = sizep; /* size of buf, currently unused */
X
X	(void) nocrmode ();
X	(void) refresh ();
X	(void) getstr (buf);
X	need_delay = FALSE;
X	info (0, 0, 0);
X	(void) crmode ();
X}
X
X/*
XGet a character from the user and convert it to uppercase.
X*/
X
Xchar
Xget_chx()
X{
X	char c;
X
X	c = get_cq ();
X
X	if (islower(c))
X		return (upper(c));
X	else
X		return (c);
X}
X
X/*
XInput an integer from the user.
X*/
X
Xint
Xgetint (message)
Xchar *message;
X{
X	char buf[STRSIZE];
X	char *p;
X
X	for (;;) { /* until we get a legal number */
X		prompt (message);
X		get_str (buf, sizeof (buf));
X		
X		for (p = buf; *p; p++) {
X			if (*p < '0' || *p > '9') {
X				error ("Please enter an integer.");
X				break;
X			}
X		}
X		if (*p == 0) { /* no error yet? */
X			if (p - buf > 7) /* too many digits? */
X				error ("Please enter a small integer.");
X			else return (atoi (buf));
X		}
X	}
X}
X
X/*
XInput a character from the user with echoing.
X*/
X
Xchar
Xget_c ()
X{
X	char c; /* one char and a null */
X
X	(void) echo ();
X	c = get_cq ();
X	(void) noecho ();
X	return (c);
X}
X
X/*
XInput a character quietly.
X*/
X
Xchar
Xget_cq ()
X{
X	char c;
X
X	(void) crmode ();
X	(void) refresh ();
X	c = getch ();
X	topini (); /* clear information lines */
X	(void) nocrmode ();
X	return (c);
X}
X
X/*
XInput a yes or no response from the user.  We loop until we get
Xa valid response.  We return TRUE iff the user replies 'y'.
X*/
X
Xint
Xgetyn (message)
Xchar *message;
X{
X	char c;
X
X	for (;;) {
X		prompt (message);
X		c = get_chx ();
X
X		if (c == 'Y') return (TRUE);
X		if (c == 'N') return (FALSE);
X
X		error ("Please answer Y or N.");
X	}
X}
X
X/*
XInput an integer in a range.
X*/
X
Xint
Xget_range (message, low, high)
Xchar *message;
Xint low, high;
X{
X	int result;
X
X	for (;;) {
X		result = getint (message);
X
X		if (result >= low && result <= high) return (result);
X
X		error ("Please enter an integer in the range %d..%d.",
X			low, high);
X	}
X}
X
X/*
XPrint a screen of help information.
X*/
X
Xvoid
Xhelp (text, nlines)
Xchar **text;
Xint nlines;
X{
X	int i, r, c;
X	int text_lines;
X
X	text_lines = (nlines + 1) / 2; /* lines of text */
X
X	clear_screen ();
X
X	pos_str (NUMTOPS, 1, text[0]); /* mode */
X	pos_str (NUMTOPS, 41, "See empire.doc for more information.");
X
X	for (i = 1; i < nlines; i++) {
X		if (i > text_lines)
X			pos_str (i - text_lines + NUMTOPS + 1, 41, text[i]);
X		else pos_str (i + NUMTOPS + 1, 1, text[i]);
X	}
X
X	pos_str (text_lines + NUMTOPS + 2,  1, "--Piece---Yours-Enemy-Moves-Hits-Cost");
X	pos_str (text_lines + NUMTOPS + 2, 41, "--Piece---Yours-Enemy-Moves-Hits-Cost");
X
X	for (i = 0; i < NUM_OBJECTS; i++) {
X		if (i >= (NUM_OBJECTS+1)/2) {
X			r = i - (NUM_OBJECTS+1)/2;
X			c = 41;
X		}
X		else {
X			r = i;
X			c = 1;
X		}
X		pos_str (r + text_lines + NUMTOPS + 3, c, 
X			"%-12s%c     %c%6d%5d%6d",
X			piece_attr[i].nickname,
X			piece_attr[i].sname,
X			tolower (piece_attr[i].sname),
X			piece_attr[i].speed,
X			piece_attr[i].max_hits,
X			piece_attr[i].build_time);
X
X	}
X	(void) refresh ();
X}
X
//E*O*F term.c//

echo x - README
sed -e 's/^X//' > "README" << '//E*O*F README//'
X/* %W% %G% %U% - (c) Copyright 1987, 1988 Chuck Simmons */
X
X/*
X *    Copyright (C) 1987, 1988 Chuck Simmons
X * 
X * See the file COPYING, distributed with empire, for restriction
X * and warranty information.
X */
X
XC Empire Sources
X
XHistory
X
X	Apparently, this game was originally written outside of Digital,
X	probably at a university.  The game was ported to DEC's VAX/VMS
X	from the TOPS-10/20 FORTRAN sources available around fall 1979.
X	Ed James got hold of the sources at Berkeley and converted
X	portions of the code to C, mostly to use curses for the screen
X	handling.  He published his modified sources on the net in
X	December 1986.  Because this game ran on VMS machines for so
X        long, a previous version is known as VMS Empire.
X
X	In early 1987 I reverse engineered the program and wrote a
X	version completely written in C.  In doing this, I used lots
X	of structures and defined constants, and I attempted to make
X	the code flexible and easy to modify.  The algorithms used
X	in this C version are completely new, the names of the commands
X	have been changed to be more mnemonic, and new commands have
X	been implemented.  Only the format of the display is the same.
X        I suspect that many of my changes are slower and less
X        intelligently implemented than the originals.  Also, I have
X	not implemented some of the original functionality.
X	However, my hope is that the commented C sources I have written
X	will prove far easier to modify and enhance than the original
X        FORTRAN sources.  If you make changes for the better, by
X        all means send Ed James and I a copy.
X
X	The basic game has been heavily modified.  I've changed the
X	types of objects built, modified the parameters on others,
X	and added lots of new kinds of movement functions.  Read
X	the man page for a complete description.
X
X	The file 'bugs' contains lots of ideas for enhancements,
X	and describes the bugs I haven't been able to find.
X
XOrganization
X
X        I have attempted to organize the sources into relatively few
X        coherent pieces.  The pieces are:
X
X        empire.h   -- definitions of data structures
X        extern.h   -- definitions of global variables
X        data.c     -- constant data
X	main.c     -- option parsing
X        empire.c   -- main program loop and outermost command handler
X        usermove.c -- move the user's pieces
X        compmove.c -- move the computer's pieces
X        edit.c     -- handle the user's edit mode commands
X        game.c     -- saving, restoring, and initializing the game board
X        display.c  -- update the screen
X	term.c     -- deal with information area of screen
X        math.c     -- mathematical routines
X        object.c   -- routines for manipulating objects
X	attack.c   -- handle attacks between pieces
X	map.c      -- find paths for moving pieces
X	util.c     -- miscellaneous routines, especially I/O.
X
XDebugging notes
X
X	From command mode, there are two special commands that
X	can be used to turn debugging mode on or off.  "++" turns
X	debugging mode on.  "+-" turns debugging mode off.
X
X	When debugging mode is turned on, the following commands are
X	available:
X
X	"#" -- display a sector of the computer's map.
X
X	"%" -- enter "movie" mode.  The computer continuously makes
X	       moves, and the computer's map is shown on the screen.
X	       This is useful for debugging the algorithm used by the
X	       computer when it makes a move.  Don't confuse this
X	       with saving a movie and replaying it.
X
X	"@" -- enable/disable "trace pathmap" mode.  If this command
X	       is followed by a "+", trace pathmap mode is enabled.
X	       If this command is followed by a "-", trace pathmap
X	       mode is disabled.  In this mode, every time a "pathmap"
X	       is created, it is displayed.  This is useful for
X	       debugging the subroutines that search for an optimal
X	       path along which to move a piece.
X
X	"$" -- enable/disable "print_debug".  This command is also
X	       followed by either a "+" or "-".  In this mode,
X	       various messages will be printed out at times which
X	       may indicate that something is being done non-optimally.
X
X	"&" -- enable/disable "print_vmap".  This command is followed
X	       by a char that specifies the type of vmap to be
X	       displayed.  Values are
X
X		"a" -- army load maps
X		"l" -- transport load maps
X		"u" -- transport unload maps
X		"s" -- ship maps
X		"i" -- pruned explore map
X
X	       Any other character disables the printing of vmaps.
X
X	The program will not provide any prompts for the debugging
X	commands.  If you make a mistake, the computer just beeps.
X
X	You can also replay a saved movie with the normal "W" command
X	when debugging mode is turned on.
X
X	Also, the -DDEBUG flag can be turned on to cause consistency
X	checking to be performed frequently on the internal database.
X	This consistency checking is fairly exhaustive and checks for
X	all sorts of screwed up pointers.  My measurements suggest
X	that consistency checking causes the program to run half
X	as fast.
X
XFinal Notes
X
X	Unfortunately, I have a rather powerful mainframe at my
X	disposal which is somewhere between 10 and 40 times as
X	fast as a 68020 based computer.  This means I can afford
X	to use extremely inefficient algorithms.  I suspect that
X	running this program on a smaller machine, such as a Sun
X	workstation or Vax will not be overly rewarding.  In particular,
X	the computer will take a very long time to move its pieces,
X	and it may not be desirable to save the game after every move.
X	(You mean your system doesn't write out 1/2 megabyte files in a
X	few milliseconds?)  This second problem is easily fixed, but
X	I don't yet have any good ideas for fixing the first problem.
X
X	The size of a saved file can be easily tuned by reducing the
X	LIST_SIZE constant in empire.h.  The only current simple tweak
X	for making the computer move faster is to reduce the size
X	of a map.
X
XChuck Simmons
Xamdahl!chuck
X
XEd James
Xedjames at ic.berkeley.edu
Xucbvax!edjames
//E*O*F README//

echo x - extern.h
sed -e 's/^X//' > "extern.h" << '//E*O*F extern.h//'
X/* %W% %G% %U% - (c) Copyright 1987, 1988 Chuck Simmons */
X
X/*
X *    Copyright (C) 1987, 1988 Chuck Simmons
X * 
X * See the file COPYING, distributed with empire, for restriction
X * and warranty information.
X */
X
X/*
Xextern.h -- define global non-constant storage.
X*/
X
X/* user-supplied parameters */
Xint SMOOTH;        /* number of times to smooth map */
Xint WATER_RATIO;   /* percentage of map that is water */
Xint MIN_CITY_DIST; /* cities must be at least this far apart */
Xint delay_time;
X
Xreal_map_t map[MAP_SIZE]; /* the way the world really looks */
Xview_map_t comp_map[MAP_SIZE]; /* computer's view of the world */
Xview_map_t user_map[MAP_SIZE]; /* user's view of the world */
X
Xcity_info_t city[NUM_CITY]; /* city information */
X
X/*
XThere is one array to hold all allocated objects no matter who
Xowns them.  Objects are allocated from the array and placed on
Xa list corresponding to the type of object and its owner.
X*/
X
Xpiece_info_t *free_list; /* index to free items in object list */
Xpiece_info_t *user_obj[NUM_OBJECTS]; /* indices to user lists */
Xpiece_info_t *comp_obj[NUM_OBJECTS]; /* indices to computer lists */
Xpiece_info_t object[LIST_SIZE]; /* object list */
X
X/* Display information. */
Xint lines; /* lines on screen */
Xint cols; /* columns on screen */
X
X/* constant data */
Xextern piece_attr_t piece_attr[];
Xextern int dir_offset[];
Xextern char *func_name[];
Xextern int move_order[];
Xextern char type_chars[];
Xextern char tt_attack[];
Xextern char army_attack[];
Xextern char fighter_attack[];
Xextern char ship_attack[];
X
Xextern move_info_t tt_load;
Xextern move_info_t tt_explore;
Xextern move_info_t tt_unload;
Xextern move_info_t army_fight;
Xextern move_info_t army_load;
Xextern move_info_t fighter_fight;
Xextern move_info_t ship_fight;
Xextern move_info_t ship_repair;
Xextern move_info_t user_army;
Xextern move_info_t user_army_attack;
Xextern move_info_t user_fighter;
Xextern move_info_t user_ship;
Xextern move_info_t user_ship_repair;
X
Xextern char *help_cmd[];
Xextern char *help_edit[];
Xextern char *help_user[];
Xextern int cmd_lines;
Xextern int edit_lines;
Xextern int user_lines;
X
X/* miscellaneous */
Xlong date; /* number of game turns played */
Xchar automove; /* TRUE iff user is in automove mode */
Xchar resigned; /* TRUE iff computer resigned */
Xchar debug; /* TRUE iff in debugging mode */
Xchar print_debug; /* TRUE iff we print debugging stuff */
Xchar print_vmap; /* TRUE iff we print view maps */
Xchar trace_pmap; /* TRUE if we are tracing pmaps */
Xint win; /* set when game is over */
Xchar jnkbuf[STRSIZE]; /* general purpose temporary buffer */
Xchar save_movie; /* TRUE iff we should save movie screens */
Xint user_score; /* "score" for user and computer */
Xint comp_score;
X
X/* Screen updating macros */
X#define display_loc_u(loc) display_loc(USER,user_map,loc)
X#define display_loc_c(loc) display_loc(COMP,comp_map,loc)
X#define print_sector_u(sector) print_sector(USER,user_map,sector)
X#define print_sector_c(sector) print_sector(COMP,comp_map,sector)
X#define loc_row(loc) ((loc)/MAP_WIDTH)
X#define loc_col(loc) ((loc)%MAP_WIDTH)
X#define row_col_loc(row,col) ((long)((row)*MAP_WIDTH + (col)))
X#define sector_row(sector) ((sector)%SECTOR_ROWS)
X#define sector_col(sector) ((sector)/SECTOR_ROWS)
X#define row_col_sector(row,col) ((int)((col)*SECTOR_ROWS+(row)))
X
X#define loc_sector(loc) \
X	row_col_sector(loc_row(loc)/ROWS_PER_SECTOR, \
X                       loc_col(loc)/COLS_PER_SECTOR)
X		       
X#define sector_loc(sector) row_col_loc( \
X		sector_row(sector)*ROWS_PER_SECTOR+ROWS_PER_SECTOR/2, \
X		sector_col(sector)*COLS_PER_SECTOR+COLS_PER_SECTOR/2)
X		
X/* global routines */
X
Xvoid empire();
X
Xvoid attack();
Xvoid comp_move();
Xvoid user_move();
Xvoid edit();
X
X/* map routines */
Xvoid vmap_cont();
Xvoid rmap_cont();
Xvoid vmap_mark_up_cont();
Xscan_counts_t vmap_cont_scan();
Xscan_counts_t rmap_cont_scan();
Xint map_cont_edge();
Xlong vmap_find_aobj();
Xlong vmap_find_wobj();
Xlong vmap_find_lobj();
Xlong vmap_find_lwobj();
Xlong vmap_find_wlobj();
Xlong vmap_find_dest();
Xvoid vmap_prune_explore_locs();
Xvoid vmap_mark_path();
Xvoid vmap_mark_adjacent();
Xvoid vmap_mark_near_path();
Xlong vmap_find_dir();
Xint vmap_count_adjacent();
Xint vmap_shore();
Xint rmap_shore();
Xint vmap_at_sea();
Xint rmap_at_sea();
X
Xvoid kill_display(); /* display routines */
Xvoid sector_change();
Xint cur_sector();
Xlong cur_cursor();
Xvoid display_loc();
Xvoid display_locx();
Xvoid print_sector();
Xint move_cursor();
Xvoid print_zoom();
Xvoid print_pzoom();
Xvoid print_xzoom();
Xvoid display_score();
X
Xvoid init_game(); /* game routines */
Xvoid save_game();
Xint restore_game();
Xvoid save_movie_screen();
Xvoid replay_movie();
X
Xvoid get_str(); /* input routines */
Xvoid get_strq();
Xchar get_chx();
Xint getint();
Xchar get_c();
Xchar get_cq();
Xint getyn();
Xint get_range();
X
Xvoid rndini(); /* math routines */
Xlong irand();
Xint dist();
Xint sqrt();
X
Xint find_nearest_city();
Xcity_info_t *find_city(); /* object routines */
Xpiece_info_t *find_obj();
Xpiece_info_t *find_nfull();
Xlong find_transport();
Xpiece_info_t *find_obj_at_loc();
Xint obj_moves();
Xint obj_capacity();
Xvoid kill_obj();
Xvoid kill_city();
Xvoid produce();
Xvoid move_obj();
Xvoid move_sat();
Xint good_loc();
Xvoid embark();
Xvoid disembark();
Xvoid describe_obj();
Xvoid scan();
Xvoid scan_sat();
Xvoid set_prod();
X
X/* terminal routines */
Xvoid pdebug();
Xvoid topini();
Xvoid clreol();
Xvoid topmsg();
Xvoid prompt();
Xvoid error();
Xvoid info();
Xvoid comment();
Xvoid extra();
Xvoid huh();
Xvoid help();
Xvoid set_need_delay();
X
X/* utility routines */
Xvoid ttinit();
Xvoid redraw();
Xvoid clear_screen();
Xvoid delay();
Xvoid close_disp();
Xvoid pos_str();
Xvoid addprintf();
Xvoid assert();
Xvoid empend();
Xvoid ver();
Xchar upper();
Xvoid tupper();
Xvoid check();
X
X/* randon routines we use */
Xlong time();
Xvoid exit();
Xvoid perror();
Xvoid srand();
Xchar *strcpy();
//E*O*F extern.h//

echo x - attack.c
sed -e 's/^X//' > "attack.c" << '//E*O*F attack.c//'
X/* %W% %G% %U% - (c) Copyright 1987, 1988 Chuck Simmons */
X
X/*
X *    Copyright (C) 1987, 1988 Chuck Simmons
X * 
X * See the file COPYING, distributed with empire, for restriction
X * and warranty information.
X */
X
X/*
Xattack.c -- handle an attack between two pieces.  We do everything from
Xfighting it out between the pieces to notifying the user who won and
Xkilling off the losing object.  Somewhere far above, our caller is
Xresponsible for actually removing the object from its list and actually
Xupdating the player's view of the world.
X
XFind object being attacked.  If it is a city, attacker has 50% chance
Xof taking city.  If successful, give city to attacker.  Otherwise
Xkill attacking piece.  Tell user who won.
X
XIf attacking object is not a city, loop.  On each iteration, select one
Xpiece to throw a blow.  Damage the opponent by the strength of the blow
Xthrower.  Stop looping when one object has 0 or fewer hits.  Kill off 
Xthe dead object.  Tell user who won and how many hits her piece has left,
Xif any.
X*/
X
X#include "empire.h"
X#include "extern.h"
X
Xvoid
Xattack (att_obj, loc)
Xpiece_info_t *att_obj;
Xlong loc;
X{
X	void attack_city();
X	void attack_obj();
X	
X	if (map[loc].contents == '*') /* attacking a city? */
X		attack_city (att_obj, loc);
X	else attack_obj (att_obj, loc); /* attacking a piece */
X}
X
Xvoid
Xattack_city (att_obj, loc)
Xpiece_info_t *att_obj;
Xlong loc;
X{
X	city_info_t *cityp;
X	int att_owner, city_owner;
X
X	cityp = find_city (loc);
X	ASSERT (cityp);
X	
X	att_owner = att_obj->owner;
X	city_owner = cityp->owner;
X
X	if (irand (2) == 0) { /* attack fails? */
X		if (att_owner == USER)
X			comment ("The scum defending the city crushed your attacking blitzkrieger.");
X
X		else if (city_owner == USER) {
X			comment ("Your city at %d is under attack.",
X				cityp->loc);
X		}
X		kill_obj (att_obj, loc);
X	}
X	else { /* attack succeeded */
X		kill_city (cityp);
X		cityp->owner = att_owner;
X		kill_obj (att_obj, loc);
X
X		if (att_owner == USER) {
X			error ("City at %d has been subjugated!",
X				cityp->loc);
X
X			extra ("Your army has been dispersed to enforce control.");
X			set_prod (cityp);
X		}
X		else if (city_owner == USER) {
X			comment ("City at %d has been lost to the enemy!",
X				cityp->loc);
X		}
X	}
X	/* let city owner see all results */
X	if (city_owner != UNOWNED) scan (MAP(city_owner), loc);
X}
X
X/*
XAttack a piece other than a city.  The piece could be anyone's.
XFirst we have to figure out what is being attacked.
X*/
X
Xvoid
Xattack_obj (att_obj, loc)
Xpiece_info_t *att_obj;
Xlong loc;
X{
X	void describe(), survive();
X	
X	piece_info_t *def_obj; /* defender */
X	int owner;
X
X	def_obj = find_obj_at_loc (loc);
X	ASSERT (def_obj != NULL); /* can't find object to attack? */
X	
X	if (def_obj->type == SATELLITE) return; /* can't attack a satellite */
X
X	while (att_obj->hits > 0 && def_obj->hits > 0) {
X		if (irand (2) == 0) /* defender hits? */
X		     att_obj->hits -= piece_attr[def_obj->type].strength;
X		else def_obj->hits -= piece_attr[att_obj->type].strength;
X	}
X
X	if (att_obj->hits > 0) { /* attacker won? */
X		describe (att_obj, def_obj, loc);
X		owner = def_obj->owner;
X		kill_obj (def_obj, loc); /* kill loser */
X		survive (att_obj, loc); /* move attacker */
X	}
X	else { /* defender won */
X		describe (def_obj, att_obj, loc);
X		owner = att_obj->owner;
X		kill_obj (att_obj, loc);
X		survive (def_obj, loc);
X	}
X	/* show results to first killed */
X	scan (MAP(owner), loc);
X}
X
X/*
XHere we look to see if any cargo was killed in the attack.  If
Xa ships contents exceeds its capacity, some of the survivors
Xfall overboard and drown.  We also move the survivor to the given
Xlocation.
X*/
X
Xvoid
Xsurvive (obj, loc)
Xpiece_info_t *obj;
Xlong loc;
X{
X	while (obj_capacity (obj) < obj->count)
X		kill_obj (obj->cargo, loc);
X		
X	move_obj (obj, loc);
X}
X
Xvoid
Xdescribe (win_obj, lose_obj, loc)
Xpiece_info_t *win_obj, *lose_obj;
Xlong loc;
X{
X	char buf[STRSIZE];
X	char buf2[STRSIZE];
X	int diff;
X	
X	*buf = '\0';
X	*buf2 = '\0';
X	
X	if (win_obj->owner != lose_obj->owner) {
X		if (win_obj->owner == USER) {
X			user_score += piece_attr[lose_obj->type].build_time;
X			
X			topmsg (1, "Enemy %s at %d destroyed.",
X				piece_attr[lose_obj->type].name,
X				loc);
X				
X			topmsg (2, "Your %s has %d hits left.",
X			       piece_attr[win_obj->type].name,
X			       win_obj->hits);
X				
X			diff = win_obj->count - obj_capacity (win_obj);
X			if (diff > 0) switch (win_obj->cargo->type) {
X			case ARMY:
X			     topmsg (3,
X				     "%d armies fell overboard and drowned in the assault.",
X				     diff);
X			     break;
X			case FIGHTER:
X			     topmsg (3,
X				     "%d fighters fell overboard and were lost in the assault.",
X				     diff);
X			     break;
X			}
X		}
X		else {
X			comp_score += piece_attr[lose_obj->type].build_time;
X			
X			topmsg (3, "Your %s at %d destroyed.",
X				piece_attr[lose_obj->type].name,
X				loc);
X		}
X		set_need_delay ();
X	}
X}
//E*O*F attack.c//

echo x - math.c
sed -e 's/^X//' > "math.c" << '//E*O*F math.c//'
X/* %W% %G% %U% - (c) Copyright 1987, 1988 Chuck Simmons */
X
X/*
X *    Copyright (C) 1987, 1988 Chuck Simmons
X * 
X * See the file COPYING, distributed with empire, for restriction
X * and warranty information.
X */
X
X/*
Xmath.c -- various mathematical routines.
X
XThis file contains routines used to create random integers.  The
Xinitialization routine 'rndini' should be called at program startup.
XThe flavors of random integers that can be generated are:
X
X    irand(n) -- returns a random integer in the range 0..n-1
X    rndint(a,b) -- returns a random integer in the range a..b
X
XOther routines include:
X
X    dist (a, b) -- returns the straight-line distance between two locations.
X*/
X
X#include "empire.h"
X#include "extern.h"
X
Xvoid rndini()
X{
X	srand((unsigned)(time(0) & 0xFFFF));
X}
X
Xlong irand(high)
Xlong high;
X{
X	if (high < 2) {
X		return (0);
X	}
X	return (rand() % high);
X}
X
Xint rndint(minp, maxp)
Xint minp, maxp;
X{
X	int size;
X
X	size = maxp - minp + 1;
X	return ((rand() % size) + minp);
X}
X
X/*
XReturn the distance between two locations.  This is simply
Xthe max of the absolute differnce between the x and y coordinates.
X*/
X
X#define MIN(a,b) ((a)<(b) ? (a) : (b))
X#define MAX(a,b) ((a)>(b) ? (a) : (b))
X#define ABS(a) ((a) < 0 ? -(a) : (a))
X
Xdist (a, b)
Xlong a, b;
X{
X	int ax, ay, bx, by;
X
X	ax = loc_row (a);
X	ay = loc_col (a);
X	bx = loc_row (b);
X	by = loc_col (b);
X
X	return (MAX (ABS (ax-bx), ABS (ay-by)));
X}
X
X/*
XFind the square root of an integer.  We actually return the floor
Xof the square root using Newton's method.
X*/
X
Xint sqrt (n)
Xint n;
X{
X	int guess;
X	
X	ASSERT (n >= 0); /* can't take sqrt of negative number */
X
X	if (n <= 1) return (n); /* do easy cases and avoid div by zero */
X		
X	guess = 2; /* gotta start somewhere */
X	guess = (guess + n/guess) / 2;
X	guess = (guess + n/guess) / 2;
X	guess = (guess + n/guess) / 2;
X	guess = (guess + n/guess) / 2;
X	guess = (guess + n/guess) / 2;
X	
X	if (guess * guess > n) guess -= 1; /* take floor */
X	return (guess);
X}
//E*O*F math.c//

echo x - makefile
sed -e 's/^X//' > "makefile" << '//E*O*F makefile//'
X# %W% %G% %U% - (c) Copyright 1987, 1988 Chuck Simmons
X
X#
X#    Copyright (C) 1987, 1988 Chuck Simmons
X#
X# See the file COPYING, distributed with empire, for restriction
X# and warranty information.
X
X# Change the line below for your compiler.  You will probably want
X# 'cc'.  ('mcc' is a "merge compiler" that takes errors, merges them
X# with the source, and tosses you into an editor.  I also use various
X# cross compilers on this line.)
X
X#CC = mcc
X#CC = cpccc
XCC = cc
X
X# Change the line below for your system.  If you are on a Sun or Vax,
X# you may want BSD.
X
X#SYS = BSD
XSYS = SYSV
X
X# Use -g to compile the program for debugging.
X
X#DEBUG = -g -DDEBUG
XDEBUG = -O
X
X# Use -p to profile the program.
X#PROFILE = -p -DPROFILE
XPROFILE =
X
X# Define all necessary libraries.  'curses' is necessary.  'termcap'
X# is needed on BSD systems.
XLIBS = -lcurses
X#LIBS = -lcurses -ltermcap
X
X# You shouldn't have to modify anything below this line.
X
XFLAGS = $(DEBUG) $(PROFILE) -c -D$(SYS)
XCCCMD = $(CC) $(FLAGS)
XINS   = /etc/install
X
XFILES = \
X	attack.c \
X	compmove.c \
X	data.c \
X	display.c \
X	edit.c \
X	empire.c \
X	game.c \
X	main.c \
X	map.c \
X	math.c \
X	object.c \
X	term.c \
X	usermove.c \
X	util.c
X
XSHARFILES = COPYING $(FILES) bugs README makefile empire.6 empire.h extern.h
X
XOFILES = \
X	attack.o \
X	compmove.o \
X	data.o \
X	display.o \
X	edit.o \
X	empire.o \
X	game.o \
X	main.o \
X	map.o \
X	math.o \
X	object.o \
X	term.o \
X	usermove.o \
X	util.o
X
Xall: empire
X
Xempire: $(OFILES)
X	$(CC) $(PROFILE) -o empire $(OFILES) $(LIBS)
X
X$(OFILES): extern.h empire.h
X	$(CCCMD) $<
X
Xlint: $(FILES)
X	lint -u -D$(SYS) $(FILES) -lcurses
X
Xclean:
X	rm -f *.o
X
Xclobber: clean
X	rm -f empire
X
Xsharsplit: $(SHARFILES)
X	sharsplit -m -r -o empire $(SHARFILES)
X
Xinstall: empire
X	$(INS) -o -f /usr/local/games empire
X
Xinstallman: empire.6
X	$(INS) -f /usr/local/man/man6 empire.6
//E*O*F makefile//

echo x - MANIFEST
sed -e 's/^X//' > "MANIFEST" << '//E*O*F MANIFEST//'
Xempire1.ar               46987
X     main.c               2090
X     object.c            14016
X     map.c               30881
X
Xempire2.ar               47903
X     empire.c             6282
X     edit.c              11119
X     compmove.c          30502
X
Xempire3.ar               47979
X     empire.h             8117
X     display.c           10953
X     bugs                28909
X
Xempire4.ar               46435
X     game.c              21323
X     usermove.c          25112
X
Xempire5.ar               46430
X     COPYING              7420
X     data.c               7529
X     util.c               7827
X     empire.6            23654
X
Xempire6.ar               28563
X     MANIFEST             1760 (est)
X     makefile             1827
X     math.c               1959
X     attack.c             4813
X     extern.h             5788
X     README               5950
X     term.c               6466
//E*O*F MANIFEST//

echo shar: End of archive 6 \(of 6\).
cp /dev/null ark6isdone
MISSING=""
for I in 1 2 3 4 5 6 ; do
    if test ! -f ark${I}isdone ; then
        MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 6 archives.
    rm -f ark[1-9]*isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0



More information about the Alt.sources mailing list