[comp.sources.games] v01i056: sdi - missle command game for Suns, Part03/06

games-request@tekred.UUCP (06/17/87)

Submitted by: Mark Weiser <weiser.pa@xerox.com>
Comp.sources.games: Volume 1, Issue 56
Archive-name: sdi/Part03



#! /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 3 (of 6)."
# Contents:  argv.c blast.c control_procs.c incoming.c
#   interceptor_picture.h intersect.c makefile save_game.c scores.c
#   sdi.h text.c
# Wrapped by billr@tekred on Wed Jun 17 11:20:45 1987
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f argv.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"argv.c\"
else
echo shar: Extracting \"argv.c\" \(5019 characters\)
sed "s/^X//" >argv.c <<'END_OF_argv.c'
X/******************************************  argv.c  *******************/
X#include <sunwindow/notify.h>
X#include <stdio.h>
X#include "sdi.h"
X
X/*
X * Copyright 1987 by Mark Weiser.
X * Permission to reproduce and use in any manner whatsoever on Suns is granted
X * so long as this copyright and other identifying marks of authorship
X * in the code and the game remain intact and visible.  Use of this code
X * in other products is reserved to me--I'm working on Mac and IBM versions.
X */
X
X/*
X * Handle command line arguments, and do some font fiddling.
X */
X
Xprocess_args(argc, argv)
Xint argc;
Xchar **argv;
X{
X	extern int time_to_play, 
X			starting_icon,
X			starting_icon_time,
X			starting_level,
X			starting_skill,
X			restoring_game;
X	while (--argc > 0) {
X		argv++;
X		if ((*argv)[0] != '-') {
X			fprintf(stderr, "Unrecognizable argument '%s'.\n", *argv);
X			exit(1);
X		} else {
X			switch((*argv)[1]) {
X				case 'b': {
X					/* name of a file with a blast pixrect to use */
X					struct pixrect *pr, *icon_load_mpr();
X					char error_msg[256], *oldv = *argv;
X					argc--; argv++;
X					if (! out_of_args(argc, oldv)) {
X						if ((pr = icon_load_mpr(*argv, error_msg)) == NULL) {
X							printf("Could not get pr '%s'.\n", *argv);
X							printf("%s",error_msg);
X						} else {
X							switch(oldv[2]) {
X		/* cities */			case 'c': change_circ(citykillcircles, pr); break;
X		/* lasers */			case 'l': change_circ(lasercircles, pr); break;
X		/* laser ends */		case 'k': change_circ(laserkillcircles, pr); break;
X		/* missile death */		case 'm': change_circ(blastkillcircles, pr); break;
X		/* interceptors */		case 'b': change_circ(bigblastcircles, pr); break;
X								default: {
X									printf("unrecognized option: '%s'.\n",oldv);
X									exit(1);
X								}
X							}
X						}
X					}
X					break;
X				}
X				case 'c': {
X					/* name of a file with a city pixrect to use */
X					argc--; argv++;
X					if (! out_of_args(argc, "-c")) {
X						init_city_bits(*argv);
X					}
X					break;
X				}	
X				case 'd': {
X					/* delay to use between screen updates */
X					argc--; argv++;
X					if (! out_of_args(argc, "-d")) {
X						blast_delay = atol(*argv);
X					}
X					break;
X				}
X				case 'f': {
X					/* new score file */
X					argc--; argv++;
X					if (! out_of_args(argc, "-f")) {
X						scorefile = *argv;
X					}
X					break;
X				}	
X				case 'g': {
X					extern int gamemaster;
X					/* set gamemaster mode */
X					gamemaster = 1;
X					break;
X				}
X				case 'h': {
X					/* height of playing windows */
X					argc--; argv++;
X					if (! out_of_args(argc, "-h")) {
X						max_y = max(MINWIN, atol(*argv));
X					}
X					break;
X				}	
X				case 'i': {
X					/* starting icon type */
X					argc--; argv++;
X					if (! out_of_args(argc, "-i")) {
X						starting_icon = atol(*argv);
X						starting_icon = min(2, max(0, starting_icon));
X					}
X					/* starting icon time */
X					argc--; argv++;
X					if (! out_of_args(argc, "-i")) {
X						starting_icon_time = atol(*argv);
X						starting_icon_time = min(50, max(1, starting_icon_time));
X					}
X					break;
X				}
X				case 'p': {
X					/* select the pointer style */
X					extern int cursor_type;
X					argc--; argv++;
X					if (! out_of_args(argc, "-p")) {
X						cursor_type = atol(*argv);
X						cursor_type = min(2, max(0, cursor_type));
X					}
X					break;
X				}
X				case 'r': {
X					/* restore a saved game */
X					argc--; argv++;
X					if (! out_of_args(argc, "-r")) {
X						strcpy(save_file_name, *argv);
X						restoring_game = 1;
X					}
X					break;
X				}
X				case 's': {
X					/* starting skill*/
X					argc--; argv++;
X					if (! out_of_args(argc, "-s")) {
X						starting_skill = atol(*argv);
X						starting_skill = min(2, max(0, starting_skill));
X					}
X					break;
X				}
X				case 't': {
X					/* maximum playing time, in seconds */
X					argc--; argv++;
X					if (! out_of_args(argc, "-t")) {
X						time_to_play = atol(*argv);
X					}
X					break;
X				}
X				case 'w': {
X					/* width of playing windows */
X					argc--; argv++;
X					if (! out_of_args(argc, "-w")) {
X						max_x = max(MINWIN, atol(*argv));
X					}
X					break;
X				}	
X				default: {
X					fprintf(stderr, "Unrecognizable argument '%s'.\n", *argv);
X					break;
X				}
X			}
X		}
X	}
X}
X
X
X/* the following kludge is necessary because there seems to be no
X * SunView subroutine which sets the default font for all the windows.
X * WIN_FONT explicitly disclaims doing this.  Only -Wt on the argument
X * claims to....
X */
Xfixup_font(pargc, pargv, font_name)
Xint *pargc;
Xchar ***pargv;
Xchar *font_name;
X{
X	int i;
X	int argc = *pargc;
X	char **argv = *pargv;
X	char **new_argv = (char **)calloc(sizeof(char *), argc+3);
X	for (i = 1; i < argc; i += 1) {
X		new_argv[i+2] = argv[i];
X	}
X	new_argv[0] = argv[0];
X	new_argv[1] = "-Wt";
X	new_argv[2] = font_name;
X	*pargc += 2;
X	*pargv = new_argv;
X}
X
Xopen_our_font(s)
Xchar *s;
X{
X	if ((font = (struct pixfont *)pf_open(s)) == NULL)
X		font = (struct pixfont *)pf_default();
X}
X
Xout_of_args(n, s)
Xchar *s;
X{
X	if (n > 0) {
X		return 0;
X	} else {
X		fprintf(stderr, "Argument '%s' not followed by a value.\n", s);
X		/* return 1; */
X		exit(1);
X	}
X}
END_OF_argv.c
if test 5019 -ne `wc -c <argv.c`; then
    echo shar: \"argv.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f blast.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"blast.c\"
else
echo shar: Extracting \"blast.c\" \(4553 characters\)
sed "s/^X//" >blast.c <<'END_OF_blast.c'
X/***************************************  blast.c  ********************/
X#include <pixrect/pixrect_hs.h>
X#include <sunwindow/notify.h>
X#include "sdi.h"
X
X/*
X * Copyright 1987 by Mark Weiser.
X * Permission to reproduce and use in any manner whatsoever on Suns is granted
X * so long as this copyright and other identifying marks of authorship
X * in the code and the game remain intact and visible.  Use of this code
X * in other products is reserved to me--I'm working on Mac and IBM versions.
X */
X
X/*
X * Blast-related routines are here and in intersect.c.  Also here is
X * the main dispatch point for display updating called, for historical
X * reasons, 'blast_timer'.
X */
X
Xstatic Notify_value blast_timer();
Xextern int draw_blast(), doto_missiles(), update_missile();
X
X/*
X * Start the main dispatch timer.
X */
Xinit_blast()
X{
X	static char *me = (char *)&me;
X	struct itimerval timer;
X	timer.it_interval.tv_usec = 0;
X	timer.it_interval.tv_sec = 0;
X	timer.it_value.tv_usec = 1;
X	timer.it_value.tv_sec = 0;
X	notify_set_itimer_func(me, blast_timer, ITIMER_REAL, &timer, NULL);
X}
X
X/*
X * Construct a new blast and put it on the display list.
X */
Xstart_blast(x, y, xinc, yinc, pw, circle_type)
Xint x, y;
XPixwin *pw;
Xstruct circ *circle_type;
X{
X	struct blast *bid = (struct blast *)malloc(sizeof(struct blast));
X	bid->pw = pw;
X	bid->next = NULL;
X	bid->circ = 0;
X	bid->x = x;
X	bid->orig_y = bid->y = y;
X	bid->x_inc = xinc;
X	bid->y_inc = yinc;
X	bid->num_circles = circle_type->num_circles;
X	bid->circles = circle_type->circles;
X	bid->masks = circle_type->masks;
X	bid->width = bid->circles[0]->pr_size.x;
X	update_blast_rect(bid);
X	add_blast(bid);
X	draw_blast(bid);
X}
X
X#define INSCRIBING_FUDGE_FACTOR 2
X
X/*
X * Construct a square which approximates the size of the current
X * blast circle.
X */
Xupdate_blast_rect(bid)
Xstruct blast *bid;
X{
X	register int w = bid->width / 2 - INSCRIBING_FUDGE_FACTOR;
X	register int h = bid->width - 2*INSCRIBING_FUDGE_FACTOR;
X	bid->r.r_left = bid->x - w;
X	bid->r.r_top = bid->y - w;
X	bid->r.r_width = h;
X	bid->r.r_height = h;
X}
X
X/*
X * The main dispatch routine.
X * 'blast_timer' is called at fixed intervals, queries routines
X * for launch, missiles, lasers, and blasts for their next update.
X */
Xstatic Notify_value
Xblast_timer(me, which)
Xint *me;
Xint which;
X{
X	extern Panel_item foe_ground_item;
X	Pixwin *pw1 = citypw;
X	Pixwin *pw2 = launchpw;
X	struct itimerval timer;
X	struct rect r;
X	Event event;
X
X	if (!running) return NOTIFY_DONE;
X
X	if (suspended) {
X		suspendor(blast_timer, me, which, 1);
X		return NOTIFY_DONE;
X	}
X
X	if (missile_count <= 0 && blast_count <= 0 &&
X		panel_get_value(ballistic_item) <= 0 &&
X		panel_get_value(foe_ground_item) <= 0)
X			finish_round();
X
X	checkinput();
X
X	timer.it_interval.tv_usec = 0;
X	timer.it_interval.tv_sec = 0;
X	timer.it_value.tv_usec = blast_delay;
X	timer.it_value.tv_sec = 0;
X	notify_set_itimer_func(pw1, blast_timer, ITIMER_REAL, &timer, NULL);
X
X
X	(void) pw_get_region_rect(pw1, &r);
X	pw_batch_on(pw1);
X	pw_lock(pw1, &r);
X	(void) pw_get_region_rect(pw2, &r);
X	pw_batch_on(pw2);
X	pw_lock(pw2, &r);
X
X	if (need_a_bell != NULL) {
X		struct timeval tv;
X		tv.tv_sec = 0;
X		tv.tv_usec = 30000; /* this is the minimal reliable bell length */
X		win_bell(window_get(cityframe, WIN_FD), tv, need_a_bell);
X		need_a_bell = NULL;
X	}
X
X	doto_missiles(update_missile);
X	doto_lasers();
X	doto_blasts(draw_blast);
X	doto_rocks();
X	doto_launch();
X
X	pw_unlock(pw2);
X	pw_batch_off(pw2);
X	pw_unlock(pw1);
X	pw_batch_off(pw1);
X
X	return NOTIFY_DONE;
X}
X
X/*
X * Helper routine passed into 'doto_blasts'.  Updates the
X * blast circle, and frees the blast structure if done.
X */
Xdraw_blast(bid)
Xstruct blast *bid;
X{
X	int old_circ =  bid->circ;
X
X	if (bid->circ < 0 || bid->x_inc || bid->y_inc) {
X		/* shrinking or moving, remove old blast */
X		pw_rop(bid->pw, B_OFFSET_X(bid), B_OFFSET_Y(bid),
X			B_WIDTH(bid), B_HEIGHT(bid),
X			PIX_NOT(PIX_SRC) & PIX_DST,
X			bid->masks[ABS(bid->circ)], 0, 0);
X	}
X
X
X	/* Update the next blast circle.  
X	   Positive values are growing, negative are shrinking
X	 */
X	bid->circ += 1;
X	if (bid->circ >= bid->num_circles) {
X		bid->circ = -bid->num_circles +1;
X	}
X	if (bid->circ) {
X		/* Draw the new blast */
X		bid->x += bid->x_inc;
X		bid->y += bid->y_inc;
X		bid->width = bid->circles[ABS((bid)->circ)]->pr_size.x;
X		pw_rop(bid->pw, B_OFFSET_X(bid), B_OFFSET_Y(bid),
X			B_WIDTH(bid), B_HEIGHT(bid),
X			PIX_SRC | PIX_DST, bid->circles[ABS(bid->circ)], 0, 0);
X	}
X	if (old_circ == -1) {
X		remove_blast(bid);
X		free(bid);
X	} 
X	bid->width = bid->circles[ABS((bid)->circ)]->pr_size.x;
X	update_blast_rect(bid);
X}
END_OF_blast.c
if test 4553 -ne `wc -c <blast.c`; then
    echo shar: \"blast.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f control_procs.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"control_procs.c\"
else
echo shar: Extracting \"control_procs.c\" \(6150 characters\)
sed "s/^X//" >control_procs.c <<'END_OF_control_procs.c'
X/*****************************  control_procs.c  ******************************/
X#include <sunwindow/notify.h>
X#include "sdi.h"
X
X/*
X * Copyright 1987 by Mark Weiser.
X * Permission to reproduce and use in any manner whatsoever on Suns is granted
X * so long as this copyright and other identifying marks of authorship
X * in the code and the game remain intact and visible.  Use of this code
X * in other products is reserved to me--I'm working on Mac and IBM versions.
X */
X
X/*
X * All the notification procs for the control panel are here.
X * Other control panel-related code is in control.c, helpers.c, and main.c.
X */
X
Xextern Panel_item timeout_item, rock_item;
Xvoid suspend_proc(), resume_proc();
X
X/*
X * Proc called when changing the slider for basic update time of the game display
X */
Xvoid
Xcycle_time_proc(item, value, event)
XPanel_item item;
XEvent *event;
X{
X	blast_delay = value*1000;
X}
X
X/*
X * Proc called when changing the slider for ballistic flight delay.
X */
Xvoid
Xballistic_time_proc(item, value, event)
XPanel_item item;
XEvent *event;
X{
X	extern int ballistic_delay;
X	ballistic_delay = value;
X}
X
X/*
X * Proc called for the 'quit' button.  Tries to completely exit the game.
X */
Xvoid
Xquit_proc(item, event)
XPanel_item item;
XEvent *event;
X{
X	update_scores();
X	suspend_proc();
X	window_done(controlframe);
X	do_with_delay(resume_proc, 2, 0); /* in case the quit is refused. */
X}
X
X/*
X * Proc called to skip to the next round in response to the 'next round' button.
X */
Xvoid
Xnext_round_proc()
X{
X	extern void init_blast(), start_running_proc();
X	running = 0;
X	free_all_blasts();
X	free_all_missiles();
X	put_text(75, "Click to start next round.");
X}
X
X/*
X * Proc called to start a new game, usually in response to the 'new game' button.
X */
Xvoid
Xnew_game_proc()
X{
X	extern Panel_item foe_ground_item;
X	extern int restoring_game;
X	extern int time_to_play;
X	void restore_proc();
X	running = 0;
X	if (restoring_game) {
X		restore_proc();
X	} else {
X		update_scores();
X		panel_set_value(level_item, "0");
X		panel_set_value(score_item, "0");
X		panel_set_value(interceptor_item, 0);
X		panel_set_value(laser_item, 0);
X		panel_set_value(foe_ground_item, 0);
X		panel_set_value(foe_item, 0);
X		panel_set_value(total_foe_item, "0");
X		panel_set_value(rock_item, 0);
X		panel_set_value(ballistic_item, 0);
X		
X	}
X
X	while (suspended)
X		resume_proc();
X	free_all_blasts();
X	free_all_missiles();
X	init_intersect();
X
X	num_cities = 0;
X	total_cities_lost = 0;
X	draw_background();
X	init_cities();
X	panel_set(skill_item, PANEL_EVENT_PROC, panel_default_handle_event, 0);
X	panel_set(next_round_item, PANEL_SHOW_ITEM, TRUE, 0);
X
X	put_text(75, "Click to start a new game.");
X	if (time_to_play) {
X		panel_set_value(timeout_item, time_to_play);
X	}
X}
X
X/*
X * Proc called to temporarily suspend a game, usually from the 'suspend' button.
X */
Xvoid
Xsuspend_proc()
X{
X	if (! suspended) {
X		panel_set(suspend_item, PANEL_SHOW_ITEM, FALSE, 0);
X		panel_set(resume_item, PANEL_SHOW_ITEM, TRUE, 0);
X	}
X	suspended += 1;
X}
X
X/*
X * Proc called to resume a suspended game, usually called via the 'resume' button,
X * which is only displayed after a 'suspend'.
X */
Xvoid
Xresume_proc()
X{
X	if (suspended) {
X		suspended -= 1;
X		if (! suspended) {
X			panel_set(resume_item, PANEL_SHOW_ITEM, FALSE, 0);
X			panel_set(suspend_item, PANEL_SHOW_ITEM, TRUE, 0);
X		}
X	}
X}
X
X/*
X * Proc called to display the scores from the score file in a popup window.
X */
Xvoid
Xscores_proc(item, value, event)
XPanel_item item;
XEvent *event;
X{
X	Menu m;
X	int id = event_id(event);
X	char *a;
X	a = (char *)build_scores();
X	easy_pop(a);
X}
X
X/*
X * Proc called to melt all the cities and then end the game, thus forcing all normal
X * end-of-game actions.  Usually called via the 'melt' button.
X */
Xvoid
Xend_proc(item, event)
XPanel_item item;
XEvent event;
X{
X	free_all_blasts();
X	free_all_missiles();
X	panel_set_value(ballistic_item, 0);
X	melt_all_cities(citypw, 1);
X	finish_round();
X}
X
X/*
X * Toggle the write-ability of important panel items in response
X * to the 'gamemaster' toggle (only visible in gamemaster mode.)
X */
Xvoid
Xmaster_proc(item, value, event)
XPanel_item item;
XEvent *event;
X{
X	extern Panel_item foe_ground_item;
X	if (value) {
X		panel_set(level_item, PANEL_EVENT_PROC, panel_default_handle_event, 0); 
X		panel_set(score_item, PANEL_EVENT_PROC, panel_default_handle_event, 0); 
X		panel_set(interceptor_item, PANEL_EVENT_PROC, panel_default_handle_event, 0); 
X		panel_set(foe_ground_item, PANEL_EVENT_PROC, panel_default_handle_event, 0); 
X		panel_set(foe_item, PANEL_EVENT_PROC, panel_default_handle_event, 0); 
X		panel_set(laser_item, PANEL_EVENT_PROC, panel_default_handle_event, 0); 
X		panel_set(rock_item, PANEL_EVENT_PROC, panel_default_handle_event, 0); 
X	} else {
X		panel_set(level_item, PANEL_EVENT_PROC, (char *)no_events, 0); 
X		panel_set(score_item, PANEL_EVENT_PROC, (char *)no_events, 0); 
X		panel_set(interceptor_item, PANEL_EVENT_PROC, (char *)no_events, 0); 
X		panel_set(foe_ground_item, PANEL_EVENT_PROC, (char *)no_events, 0);
X		panel_set(foe_item, PANEL_EVENT_PROC, (char *)no_events, 0);
X		panel_set(laser_item, PANEL_EVENT_PROC, (char *)no_events, 0);
X		panel_set(rock_item, PANEL_EVENT_PROC, (char *)no_events, 0);
X	}
X}
X
Xvoid
Xrestore_proc()
X{
X	void restore_timer_proc();
X	if (running) {
X		easy_pop("Can only save or restore between rounds.");
X		return;
X	}
X	restoring_game = 1;
X	restore_game();
X
X	/*
X	 * the kludge below puts us to sleep for a moment, and then turns
X	 * off a control variable.  This helps manage an infinite regress
X	 * which can start if the 'restore_game' call above resizes windows.
X	 *
X	 * What I really need are genuine light-weight processes.
X	 */
X	do_with_delay(restore_timer_proc, 0, 500000);
X}
X
Xvoid
Xrestore_timer_proc()
X{
X	extern int restoring_game;
X	restoring_game = 0;
X}
X
Xvoid
Xsave_proc()
X{
X	if (running) {
X		easy_pop("Can only save or restore between rounds.");
X	} else {
X		save_game();
X	}
X}
X
Xvoid
Xcursor_notify_proc(item, value, event)
XPanel_item item;
XEvent *event;
X{
X	extern int cursor_type;
X	cursor_type = value;
X	init_cursor();
X	update_cursor();
X}
X
Xvoid
Xnon_stop_notify_proc(item, value, event)
XPanel_item item;
XEvent *event;
X{
X	extern int continuous;
X	continuous = value;
X}
END_OF_control_procs.c
if test 6150 -ne `wc -c <control_procs.c`; then
    echo shar: \"control_procs.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f incoming.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"incoming.c\"
else
echo shar: Extracting \"incoming.c\" \(6261 characters\)
sed "s/^X//" >incoming.c <<'END_OF_incoming.c'
X/*********************************  incoming.c  ****************************/
X#include <pixrect/pixrect_hs.h>
X#include <sunwindow/notify.h>
X#include "sdi.h"
X
X/*
X * Copyright 1987 by Mark Weiser.
X * Permission to reproduce and use in any manner whatsoever on Suns is granted
X * so long as this copyright and other identifying marks of authorship
X * in the code and the game remain intact and visible.  Use of this code
X * in other products is reserved to me--I'm working on Mac and IBM versions.
X */
X
X/*
X * This file contains routines for lauching 'foe' missiles.  Since
X * a round is over when all the foes are gone, end-of-round work
X * is done here as well.  And since the game is over when there are
X * no cities left at the end of the round, end-of-game computations
X * are mostly done here too. And, since the only difference between
X * different skills is the difficulty of foe missiles, skill adjustment
X * is also done in here.  Why not just do everything here?  Wouldn't fit.
X */
X
X/* The following two constants determine launch rates. */
X#define MAX_TIME_FOR_A_ROUND	45000000
X#define AVG_DELAY_BETWEEN_MISSILES 1000000
X
Xstatic short *missiles_to_launch = NULL;
Xstatic int next_missile_launch = 0;
Xstatic int num_launch_intervals;
X
Xstatic bonus_threshold = 5000;
X
X/*
X * Increase the game level by one, within reason.
X */
X#define MAX_LEVEL 49
X
Xint
Xbump_level()
X{
X	int level;
X	char buf[32];
X	level = atol((int)panel_get_value(level_item)) + 1;
X	if (level > MAX_LEVEL) {
X		level = MAX_LEVEL;
X		panel_set(next_round_item, PANEL_SHOW_ITEM, FALSE, 0);
X	}
X	sprintf(buf,"%d", level);
X	panel_set_value(level_item, buf);
X	return level;
X}
X
X/*
X * Compute the skill differentials, get the missiles ready to launch,
X * and set the 'running' switch on.  Normally 'init_incoming' is the last
X * thing called when a round is started, and setting the 'running' switch
X * immediately releases various notifications so the game really begins.
X */
Xinit_incoming()
X{
X	extern Panel_item rock_item, foe_ground_item;
X	int foe_val, friend_val, laser_val, rocks_val, level, skill, count, range;
X	int base = 2;
X	char buf[128];
X	if (running)
X		return;
X
X	skill = (int)panel_get_value(skill_item);
X	switch (skill) {
X		case 0: /* novice */
X			carryover_divisor = 1.0;
X			foe_divisor = 2.0;
X			min_missile_speed = 5;
X			max_missile_speed = 15;
X			foe_factor = 2;
X			break;
X		case 1: /* occasional */
X			carryover_divisor = 1.3;
X			foe_divisor = 2.5;
X			min_missile_speed = 10;
X			max_missile_speed = 20;
X			foe_factor = 4;
X			break;
X		case 2: /* expert */
X			carryover_divisor = 1.6;
X			foe_divisor = 3.0;
X			min_missile_speed = 15;
X			max_missile_speed = 25;
X			foe_factor = 6;
X			break;
X	}
X
X	level = bump_level();
X
X	foe_val = foe_factor * level;
X	panel_set(foe_ground_item, PANEL_MAX_VALUE, foe_val, PANEL_VALUE, foe_val, 0);
X	panel_set(foe_item, PANEL_MAX_VALUE, foe_val*3, 0);
X
X	laser_val = (int)panel_get_value(laser_item);
X	laser_val = ((int)((float)foe_val/foe_divisor)) + laser_val/carryover_divisor;
X	laser_val += base;
X	panel_set(laser_item, PANEL_MAX_VALUE, laser_val, PANEL_VALUE, laser_val,
X		0);
X	panel_set(ballistic_item, PANEL_MAX_VALUE, foe_val, 0);
X
X	friend_val = (int)panel_get_value(interceptor_item);
X	friend_val = ((int)((float)foe_val/foe_divisor)) + friend_val/carryover_divisor; 
X	friend_val += base;
X	panel_set(interceptor_item, PANEL_MAX_VALUE, friend_val, PANEL_VALUE, friend_val,
X		0);
X
X	rocks_val = (int)panel_get_value(rock_item);
X	rocks_val = ((int)((float)foe_val/foe_divisor)) + rocks_val/carryover_divisor; 
X	rocks_val += base;
X	panel_set(rock_item, PANEL_MAX_VALUE, rocks_val, PANEL_VALUE, rocks_val,
X		0);
X
X	if (missiles_to_launch != NULL)
X		free(missiles_to_launch);
X	num_launch_intervals = MAX_TIME_FOR_A_ROUND/blast_delay + 2;
X	missiles_to_launch = (short *)calloc(sizeof(short), num_launch_intervals);
X	next_missile_launch = 0;
X	count = (int)panel_get_value(foe_ground_item);
X	range = min( MAX_TIME_FOR_A_ROUND, AVG_DELAY_BETWEEN_MISSILES*count);
X	while (count--) {
X		missiles_to_launch[(random() % range) / blast_delay] += 1;
X	}
X	new_score();
X	if (level <= 1)
X		bonus_threshold = 5000;
X
X}
X
X/*
X * Called at each display update timestep, this routine launches
X * any missiles which have come due.
X */
Xdoto_launch()
X{
X	int level;
X	int num_missiles; 
X
X	if (!suspended) {
X		int x;
X		if (next_missile_launch >= num_launch_intervals)
X			return;	
X		num_missiles = missiles_to_launch[next_missile_launch++];
X		if (num_missiles) {
X			panel_set_value(foe_ground_item, 
X				panel_get_value(foe_ground_item) - num_missiles);
X			level = atol((char *)panel_get_value(level_item));
X			while (num_missiles--) {
X				x = random() % max_x;
X				start_missile(x, UP,
X					min(max(normal(min_missile_speed+level/2,level/2),
X						min_missile_speed),
X						max_missile_speed), launchpw);
X			}
X		}
X	}
X}
X
X/*
X * Compute which cites are still left, bonus scores, and end-of-game.
X * Get ready for the next round.
X */
Xfinish_round()
X{
X	char buf[128], score_buf[32];
X	int cities_lost = compute_cities(citypw);
X	extern int continuous;
X	int level = atol((char *)panel_get_value(level_item));
X	int score = atol((char *)panel_get_value(score_item));
X	int bonus, extra_city = 0;
X
X	running = 0;
X	put_text(25, "Round Over");
X	total_cities_lost += cities_lost;
X	bonus =  level*10*(num_cities-total_cities_lost);
X	update_cities(citypw, 1);
X	if ((score+bonus) >= bonus_threshold && total_cities_lost > 0) {
X		extra_city = 1;
X		total_cities_lost -= 1;
X		bonus_threshold += bonus_threshold;
X	}
X	bonus =  level*10*(num_cities-total_cities_lost);
X	sprintf(buf, "You have %d cities left, for %d bonus points.",num_cities-total_cities_lost, bonus);
X	panel_set_value(score_item, sprintf(score_buf, "%d", score+bonus));
X	if(total_cities_lost >= num_cities) {
X		panel_set(skill_item, PANEL_EVENT_PROC, panel_default_handle_event, 0);
X		if (!continuous)
X			do_game_over();
X		update_scores();
X		new_game_proc();
X	} else {
X		put_text(50, buf);
X		if (extra_city) {
X			put_text(0, "BONUS CITY");
X			new_city(citypw);
X		}
X		next_round_proc();
X		if (continuous) {
X			sleep(1);
X			start_next_round();
X		}
X	}
X}
X
X/*
X * this keeps any more missiles from being launched.  Actually freeing
X * of allocated structures happens on the next 'init_incoming' call.
X */
Xfree_foe()
X{
X	num_launch_intervals = 0;
X}
END_OF_incoming.c
if test 6261 -ne `wc -c <incoming.c`; then
    echo shar: \"incoming.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f interceptor_picture.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"interceptor_picture.h\"
else
echo shar: Extracting \"interceptor_picture.h\" \(193 characters\)
sed "s/^X//" >interceptor_picture.h <<'END_OF_interceptor_picture.h'
X/* Format_version=1, Width=16, Height=16, Depth=1, Valid_bits_per_item=16
X */
X	0x0000,0x07C0,0x0FE0,0x1FF0,0x3FF8,0x3FF8,0x3F88,0x3F38,
X	0x3E7C,0x1EFE,0x0EFE,0x07FE,0x007C,0x0038,0x0000,0x0000
END_OF_interceptor_picture.h
if test 193 -ne `wc -c <interceptor_picture.h`; then
    echo shar: \"interceptor_picture.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f intersect.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"intersect.c\"
else
echo shar: Extracting \"intersect.c\" \(5338 characters\)
sed "s/^X//" >intersect.c <<'END_OF_intersect.c'
X/************************************  intersect.c  ******************/
X#include "sdi.h"
X
X/*
X * Copyright 1987 by Mark Weiser.
X * Permission to reproduce and use in any manner whatsoever on Suns is granted
X * so long as this copyright and other identifying marks of authorship
X * in the code and the game remain intact and visible.  Use of this code
X * in other products is reserved to me--I'm working on Mac and IBM versions.
X */
X
X/*
X * The code to intersect blasts, missiles, and lasers is in here,
X * as well as some blast-specific code.
X */
X
X#define LINE_GRAIN 20
X
X/* each 'line' is the head of a linked list of current blasts */
Xstatic struct blast *lines_launch[MAX_LINES/LINE_GRAIN + 1], *lines_city[MAX_LINES/LINE_GRAIN + 1];
Xstatic struct blast **init_line_from_bid(), **init_line_from_mid();
X
X/*
X * Clear out data structures which keep track of blasts. 
X */
Xinit_intersect()
X{
X	int i;
X	for (i=0; i<(MAX_LINES/LINE_GRAIN +1); i++) {
X		lines_launch[i] = NULL;
X		lines_city[i] = NULL;
X	}
X}
X
X/*
X * Register a blast for later display.  After this call the blast will
X * automatically be incremented and decremented in size, and will be checked
X * for intersection with missiles.
X */
Xadd_blast(bid)
Xregister struct blast *bid;
X{
X	/* for now don't sort, just stick at the head */
X	register int pos = bid->orig_y / LINE_GRAIN;
X	struct blast **lines;
X	if (pos < 0 || pos >= MAX_LINES/LINE_GRAIN + 1) {
X		return;
X	}
X	lines = init_line_from_bid(bid);
X	bid->next = lines[pos];
X	lines[pos] = bid;
X	blast_count++;		
X}
X
X/*
X * Remove a blast from the display list.  The blast will no longer
X * intersect missiles, change in size, or be displayed. The blast must
X * have already been cleared from the display elsewhere. The storage
X * is not freed here, in case the blast is statically allocated.
X */
Xremove_blast(bid)
Xregister struct blast *bid;
X{	
X	struct blast **lines = init_line_from_bid(bid);
X	register struct blast *ptr = lines[bid->orig_y / LINE_GRAIN];
X	if (ptr == bid) {
X		/* head is special case */
X		lines[bid->orig_y / LINE_GRAIN] = bid->next;
X	} else {
X		while ( ptr != NULL && ptr->next != bid ) 
X			ptr = ptr->next;
X		if (ptr != NULL) 
X			ptr->next = bid->next;
X	}
X	blast_count--;
X}
X
X/*
X * See if the missile 'mid' has run into any blasts.
X */
Xintersect(mid)
Xstruct missile *mid;
X{
X	int start = max((mid->y - (MAX_CIRCLE >> 1) - 1) / LINE_GRAIN, 0);
X	int end = min((mid->y + (MAX_CIRCLE >> 1) + 1) / LINE_GRAIN, max_y);
X	register int i;
X	register struct blast *ptr;
X	struct blast **lines = init_line_from_mid(mid);
X	for (i=start; i <= end; i++) {
X		ptr = lines[i];
X		while (ptr != NULL) {
X			if (single_intersect(ptr, mid))
X				return TRUE;
X			ptr = ptr->next;
X		}
X	}
X	return FALSE;
X}
X
X/*
X * See if the missile 'mid' is passing through blast 'bid'.  This routine
X * is also used for laser initialization, with a fake 'bid' to simulate
X * the laser range.  For purposes of computing intersection, the circular
X * blast is considerd to be a rectangle with the same center and approximately
X * the same area.  An intersection has occured if the missile passed
X * through the blast between its last update and now, even if both endpoints
X * are outside the blast.
X */
Xsingle_intersect(bid,mid)
Xstruct missile *mid;
Xstruct blast *bid;
X{
X	int x0 = mid->old_x, y0 = mid->old_y, x1 = mid->x, y1 = mid->y;
X	return rect_clipvector(&bid->r, &x0, &y0, &x1, &y1);
X}
X
X/*
X * Procedure 'func' is called for every blast on the display lists.
X */
Xdoto_blasts(func)
Xint (*func)();
X{
X	int i;
X	struct blast *bid, *next;
X	struct blast **lines;
X	lines = lines_launch;
X	for (i=0; i< (MAX_LINES/LINE_GRAIN + 1); i++) {
X		bid = lines[i];
X		while (bid != NULL) {
X			next = bid->next; /* in case func destroys it */
X			(*func)(bid);
X			bid = next;
X		}
X	}
X	lines = lines_city;
X	for (i=0; i<(MAX_LINES/LINE_GRAIN + 1); i++) {
X		bid = lines[i];
X		while (bid != NULL) {
X			next = bid->next; /* in case func destroys it */
X			(*func)(bid);
X			bid = next;
X		}
X	}
X}
X
X/*
X * Given a blast, return the proper display on which it will be found.
X */
Xstatic struct blast **
Xinit_line_from_bid(bid)
Xstruct blast *bid;
X{
X	if (bid->pw == launchpw) {
X		return lines_launch;
X	} else {
X		return lines_city;
X	}
X}
X
X/*
X * Given a missile, return the proper display list on which intersecting
X * blasts will be found.
X */
Xstatic struct blast **
Xinit_line_from_mid(mid)
Xstruct missile *mid;
X{
X	if (mid->pw == launchpw) {
X		return lines_launch;
X	} else {
X		return lines_city;
X	}
X}
X
X/*
X * Remove all blasts from the display lists and free their storage.
X * Nothing is done here about getting them off the display.
X */
Xstatic struct blast **line_list[] = {lines_launch, lines_city};
Xfree_all_blasts()
X{
X	int i, l;
X	struct blast *bid, *nextbid, **lines;
X	for (l=0; l < 2; l++) {
X		lines = line_list[l];
X			for (i=0; i<(MAX_LINES/LINE_GRAIN + 1); i++) {
X			bid = lines[i];
X			lines[i] = NULL;
X			while (bid != NULL) {
X				nextbid = bid->next;
X				free(bid);
X				bid = nextbid;
X			}
X		}
X	}
X	blast_count = 0;
X}
X
X/*
X	This is the old style, now commented out.  It would let a fast
X	moving missile pass right through, but did consider blasts to 
X    be real circles.
X
Xsingle_intersect(bid, mid)
Xstruct blast *bid;
Xstruct missile *mid;
X{
X	register short offx = B_WIDTH(bid)/2;
X	register short x = bid->x - mid->x;
X	register short y = bid->y - mid->y;
X	return (x*x + y*y) < (offx*offx);
X}
X*/
X
END_OF_intersect.c
if test 5338 -ne `wc -c <intersect.c`; then
    echo shar: \"intersect.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f makefile -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"makefile\"
else
echo shar: Extracting \"makefile\" \(4377 characters\)
sed "s/^X//" >makefile <<'END_OF_makefile'
XSCOREFILENAME = /tmp/sdi_scores
XSCOREFILE = "${SCOREFILENAME}"
X
X# The breakdown into SRC 1, 2 and 3 is purely for shar purposes.
XSRC1 = main.c helpers.c missile.c cursor.c scores.c save_game.c text.c piemenu_track.c
X
XSRC2 = control.c blast.c circles.c laser.c rocks.c input.c notify.c control_procs.c  menu.c
X
XSRC3 = intersect.c random.c incoming.c cities.c pr_helpers.c game_over.c argv.c global.c icons.c 
X
XSRC = ${SRC1} ${SRC2} ${SRC3}
X
XH1 = melt.h default_city.h cursor.h laser.h mushroom.h laserkill.h \
X	missilekill.h city_icon1.h \
X	city_icon2.h city_icon3.h city_icon4.h city_icon5.h city_icon6.h \
X	city_icon7.h city_icon8.h rocks.h dynacursor.h foe_picture.h \
X	laser_picture.h interceptor_picture.h rock_picture.h dyna_picture.h \
X	silly_picture.h cross_picture.h foe_ground_picture.h \
X	fancy_icon1.h fancy_icon2.h fancy_icon3.h 
X
XH2 = fancy_icon4.h fancy_icon5.h \
X	fancy_icon6.h fancy_icon7.h fancy_icon8.h fancy_icon9.h fancy_icon10.h \
X	fancy_icon11.h fancy_icon12.h fancy_icon13.h fancy_icon14.h \
X	fancy_icon15.h fancy_icon16.h fancy_icon17.h fancy_icon18.h \
X	fancy_icon19.h fancy_icon20.h fancy_icon21.h fancy_icon22.h \
X	fancy_icon23.h fancy_icon24.h walkmenu_impl.h image_impl.h center.h \
X	incoming_picture.h pie_generic_cursor.h
X
XH = ${H1} ${H2}
X
XADMIN = README sdi.man HISTORY.nr NOTES TODO makefile genmessage.c \
X	makehistory.awk editall source_converter.c longfile.nr sdi.h \
X	lookup.h gameover.h icon.h talkingmark.h makeman.sed novice_advice.h \
X	occasional_advice.h expert_advice.h about_msg.h instructions.h \
X	piemenu.h makeversion version.c
X
XALLFILES = ${ADMIN} ${SRC} ${H}
X
XOBJ = main.o circles.o blast.o missile.o intersect.o random.o incoming.o \
X	cities.o pr_helpers.o control.o game_over.o helpers.o argv.o global.o \
X	laser.o icons.o scores.o save_game.o rocks.o notify.o input.o \
X	control_procs.o cursor.o text.o menu.o piemenu_track.o \
X	sourcecode.o history.o man.o version.o
X
X#If you are running SUNOS 3.0, use this: CLAGS = -DSUNOS3_0
X
XCFLAGS = -DSUNOS3_0
X
XLIBS = -lsuntool -lsunwindow -lpixrect -lm
X
Xall: sdi
X
Xsdi: ${OBJ}
X	cc ${CFLAGS} -o sdi ${OBJ} ${LIBS}
X
Xversion.o: ${SRC} ${H} ${ADMIN}
X	makeversion version.c
X	cc ${CFLAGS} -c version.c
X
Xfastsdi:
X	/bin/rm -f sdi
X	touch sourcecode.o
X	make sdi
X	sdi
X
Xsrc:
X	cat ${SRC} | expand -4 >src
X
Xsourcecode.o: ${SRC} source_converter
X	cat ${SRC} | expand -4 | source_converter source_code > /tmp/sourcecode.s
X	cc -c /tmp/sourcecode.s
X	/bin/rm -rf /tmp/sourcecode.s
X
Xhistory.o: HISTORY.nr source_converter
X	cat longfile.nr HISTORY.nr | tbl | nroff -me | col | awk -f makehistory.awk | source_converter history_text >/tmp/history.s
X	cc -c /tmp/history.s
X	/bin/rm -rf /tmp/history.s
X
Xman.o: sdi.man source_converter makeman.sed
X	nroff -man longfile.nr sdi.man | sed -f makeman.sed | col | source_converter man_text >/tmp/man.s
X	cc -c /tmp/man.s
X	/bin/rm -rf /tmp/man.s
X
Xgrind:
X	cat ${SRC} | expand -4 | vgrind -t -h SDI >source.grind
X
Xtextedit:
X	editall ${SRC} ${ADMIN}
Xsize:
X	wc ${SRC}
X	wc ${ADMIN}
X	wc ${H}
X
Xclean:
X	/bin/rm -f sdi bigmessage.h genmessage *.o *shar
X
Xshar:
X	/bin/rm -f sdi.shar
X	makescript -o sdi.shar ${ALLFILES}
X
XZ: shar
X	/bin/rm -f sdi.shar.Z
X	compress sdi.shar
X
Xsplitshar:
X	makescript -o sdi1.shar ${ADMIN}
X	makescript -o sdi2.shar ${SRC1}
X	makescript -o sdi3.shar ${SRC2}
X	makescript -o sdi4.shar ${SRC3}
X	makescript -o sdi5.shar ${H1}
X	makescript -o sdi6.shar ${H2}
X	ls -l sdi1.shar sdi2.shar sdi3.shar sdi4.shar sdi5.shar sdi6.shar
X
X#
X# ORIGSIZE for game and the constant for bigmessage.h
X# are related by a factor of 64.
X#
Xgame_over.o: bigmessage.h game_over.c
X	cc ${CFLAGS} -c game_over.c -DORIGSIZE=256
X
Xscores.o: scores.c
X	cc ${CFLAGS} -c scores.c '-DSCOREFILE=${SCOREFILE}' 
X
Xbigmessage.h: genmessage talkingmark.h
X	genmessage talkingmark.h 4 >bigmessage.h
X
Xgenmessage: genmessage.c
X	cc ${CFLAGS} -o genmessage genmessage.c ${LIBS}
X
Xtestrandom: random.o testrandom.o
X	cc ${CFLAGS} -o testrandom testrandom.o random.o
X
Xvectortest: vectortest.o
X	cc ${CFLAGS} -o vectortest vectortest.o ${LIBS}
X
Xwormtest: wormtest.o
X	cc ${CFLAGS} -o wormtest wormtest.o ${LIBS}
X
Xicontest: icontest.o
X	cc ${CFLAGS} -o icontest icontest.o ${LIBS}
X
Xkeytest: keytest.o
X	cc ${CFLAGS} -o keytest keytest.o ${LIBS}
X
Xinvert: invert.o
X	cc ${CFLAGS} -o invert invert.o ${LIBS}
X
Xicons.o: city_icon1.h city_icon2.h city_icon3.h city_icon4.h city_icon5.h city_icon6.h city_icon7.h city_icon8.h
END_OF_makefile
if test 4377 -ne `wc -c <makefile`; then
    echo shar: \"makefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f save_game.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"save_game.c\"
else
echo shar: Extracting \"save_game.c\" \(5019 characters\)
sed "s/^X//" >save_game.c <<'END_OF_save_game.c'
X/*****************************  save_game.c  ******************************/
X#include <sunwindow/notify.h>
X#include <stdio.h>
X#include "sdi.h"
X
X/*
X * Copyright 1987 by Mark Weiser.
X * Permission to reproduce and use in any manner whatsoever on Suns is granted
X * so long as this copyright and other identifying marks of authorship
X * in the code and the game remain intact and visible.  Use of this code
X * in other products is reserved to me--I'm working on Mac and IBM versions.
X */
X
X/*
X * Code to save and restore games.
X */
X
X/* If the save format is changed, change the version number. */
X#define SAVE_VERSION 6
X
Xextern int time_to_play, gamemaster, cursor_type;
Xextern char save_file_name[];
Xextern Panel_item cursor_item, cycle_time_item;
Xextern char *strcpy();
X
Xvoid
Xsave_game() {
X	char tmpbuf[128];
X	int control_x, control_y;
X	FILE *Savefile;
X
X	if ((Savefile = fopen(SAVE_FILE_NAME, "r")) != NULL) {
X		sprintf(tmpbuf, "Save file '%s' already exists.  Overwrite?", SAVE_FILE_NAME);
X		if (! easy_warn(tmpbuf))
X			return;
X		fclose(Savefile);
X	}
X
X	if ((Savefile = fopen(SAVE_FILE_NAME, "w")) == NULL) {
X		sprintf(tmpbuf, "Cannot open save file '%s'.", SAVE_FILE_NAME);
X		easy_pop(tmpbuf);
X	}
X
X
X	fprintf(Savefile, "version = %d\n", SAVE_VERSION);
X
X	fprintf(Savefile, "level = %s\n",(char *)panel_get_value(level_item));
X
X	fprintf(Savefile, "skill = %d\n", panel_get_value(skill_item));
X
X	fprintf(Savefile, "interceptor_val = %d\n", panel_get_value(interceptor_item));
X
X	fprintf(Savefile, "laser_val = %d\n", panel_get_value(laser_item));
X
X	fprintf(Savefile, "rock_val = %d\n", panel_get_value(rock_item));
X
X	fprintf(Savefile, "game_master = %d\n", gamemaster);
X
X	fprintf(Savefile, "score = %s\n", panel_get_value(score_item));
X
X	fprintf(Savefile, "name = '%s'\n", USER_NAME);
X
X	fprintf(Savefile, "playing field size = %d, %d\n", 
X		window_get(cityframe, WIN_WIDTH), 
X		window_get(cityframe, WIN_HEIGHT));
X
X	fprintf(Savefile, "control panel position = %d, %d\n",
X		(control_x = (int)window_get(controlframe, WIN_X)), 
X		(control_y = (int)window_get(controlframe, WIN_Y)));
X
X	/*
X	 * Kludge around a "feature" of Sunview in which negative
X	 * positions are ignored.
X	 */
X	window_set(controlframe, WIN_X, 0, WIN_Y, 0, 0);
X
X	fprintf(Savefile, "city field position = %d, %d\n",
X		window_get(cityframe, WIN_X), 
X		window_get(cityframe, WIN_Y));
X
X	fprintf(Savefile, "launch field position = %d, %d\n",
X		window_get(launchframe, WIN_X), 
X		window_get(launchframe, WIN_Y));
X
X	window_set(controlframe, WIN_X, control_x, WIN_Y, control_y, 0);
X
X	fprintf(Savefile, "blast_delay = %d\n", blast_delay);
X
X	fprintf(Savefile, "cursor_type = %d\n", cursor_type);
X
X	fclose(Savefile);
X}
X
Xvoid
Xrestore_game() {
X	int version;
X	int tmpint, w, h, x, y;
X	int control_x, control_y;
X	char tmpbuf[256];
X	FILE *Savefile;
X	if ((Savefile = fopen(SAVE_FILE_NAME, "r")) == NULL) {
X		sprintf(tmpbuf, "Can't open restore file '%s'.", SAVE_FILE_NAME);
X		easy_pop(tmpbuf);
X		return;
X	}
X
X	fscanf(Savefile, "version = %d\n", &version);
X	if (version != SAVE_VERSION) {
X		easy_pop("The save file has the wrong version.");
X		return;
X	}
X
X	fscanf(Savefile, "level = %s\n", tmpbuf);
X	panel_set_value(level_item, tmpbuf);
X
X	fscanf(Savefile, "skill = %d\n", &tmpint);
X	panel_set_value(skill_item, tmpint);
X
X	fscanf(Savefile, "interceptor_val = %d\n", &tmpint);
X	panel_set(interceptor_item, PANEL_VALUE, tmpint,
X		PANEL_MAX_VALUE, tmpint,
X		0);
X
X	fscanf(Savefile, "laser_val = %d\n", &tmpint);
X	panel_set(laser_item, PANEL_VALUE, tmpint,
X		PANEL_MAX_VALUE, tmpint,
X		0);
X
X	fscanf(Savefile, "rock_val = %d\n", &tmpint);
X	panel_set(rock_item, PANEL_VALUE, tmpint,
X		PANEL_MAX_VALUE, tmpint,
X		0);
X
X	fscanf(Savefile, "game_master = %d\n", &gamemaster);
X
X	fscanf(Savefile, "score = %s\n", tmpbuf);
X	panel_set_value(score_item, tmpbuf);
X
X	fscanf(Savefile, "name = '%[^']'\n", tmpbuf);
X	if (user_name[0] == '\0')
X		panel_set_value(user_name_item, tmpbuf);
X	strcpy(user_name, tmpbuf);
X
X	fscanf(Savefile, "playing field size = %d, %d\n", &w, &h);
X	/* Only set one, they track each other. */
X	window_set(cityframe, WIN_WIDTH, w, WIN_HEIGHT, h, 0);
X
X	fscanf(Savefile, "control panel position = %d, %d\n",&control_x,&control_y);
X	/*
X	 * Kludge around a "feature" of Sunview in which negative
X	 * positions are ignored.
X	 */
X	window_set(controlframe, WIN_X, 0, WIN_Y, 0, 0);
X
X	fscanf(Savefile, "city field position = %d, %d\n",&x,&y);
X	window_set(cityframe, WIN_X, x, WIN_Y, y, 0);
X
X	fscanf(Savefile, "launch field position = %d, %d\n",&x,&y);
X	window_set(launchframe, WIN_X, x, WIN_Y, y, 0);
X
X	window_set(controlframe, WIN_X, control_x, WIN_Y, control_y, 0);
X
X	fscanf(Savefile, "blast_delay = %d\n", &blast_delay);
X	panel_set_value(cycle_time_item, blast_delay);
X
X	fscanf(Savefile, "cursor_type = %d\n", &tmpint);
X	cursor_type = tmpint;
X
X	fclose(Savefile);
X}
X
XFILE *
Xgetsavefile(s)
Xchar *s;
X{
X	char *filename;
X	FILE *stream;
X	Event event;
X	filename = SAVE_FILE_NAME;
X	if (((stream = fopen(filename, s)) == NULL)) {
X		easy_pop("Can't open the save file.");
X	}
X	return stream;
X}
END_OF_save_game.c
if test 5019 -ne `wc -c <save_game.c`; then
    echo shar: \"save_game.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f scores.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"scores.c\"
else
echo shar: Extracting \"scores.c\" \(4859 characters\)
sed "s/^X//" >scores.c <<'END_OF_scores.c'
X/**********************************  scores.c  **********************/
X#include <pwd.h>
X#include <stdio.h>
X#include "sdi.h"
X
X/*
X * Copyright 1987 by Mark Weiser.
X * Permission to reproduce and use in any manner whatsoever on Suns is granted
X * so long as this copyright and other identifying marks of authorship
X * in the code and the game remain intact and visible.  Use of this code
X * in other products is reserved to me--I'm working on Mac and IBM versions.
X */
X
X/*
X * This code is responsible 
X * reading, updating, and displaying the score file.
X */
X
X#ifndef SCOREFILE
X#define SCOREFILE "/usr/games/lib/sdi_scores"
X#endif
X
Xstruct scores *get_scores();
X
X/* Already updated is used to prevent rewriting the score file more than
X * once per game.
X */
Xstatic int already_updated = 0;
X
X/*
X * This routine is called whenever there is absolutely positively a new
X * game beginning, and so if it ever gets anywhere it is ok to update
X * the score file.
X */
Xnew_score()
X{
X	already_updated = 0;
X}
X
X/*
X * Read in the old scores and insert the current game score into the file
X * if it is within the top ten.  No scores are recorded in gamemaster mode.
X */
Xupdate_scores()
X{
X	extern int gamemaster;
X	struct scores *scp, *new_pos = NULL;
X	int i;
X	int score = atol((char *)panel_get_value(score_item));
X	int level = atol((char *)panel_get_value(level_item));
X	int skill = (int)panel_get_value(skill_item);
X	if (already_updated || gamemaster)
X		return;
X	if ((scp = get_scores()) == NULL)
X		return;
X	while (scp->score > score) {
X		scp += 1;
X	}
X	if (scp->score >= 0) {
X		struct scores *new_sc = sc_end;
X		while (--new_sc > scp) {
X			strcpy(new_sc->name, (new_sc-1)->name);
X			new_sc->score = (new_sc-1)->score;
X			new_sc->level = (new_sc-1)->level;
X			new_sc->skill = (new_sc-1)->skill;
X		}
X		strcpy(scp->name, USER_NAME);
X		scp->score = score;
X		scp->level = level;
X		scp->skill = skill;
X	}
X	if (! put_scores(sc)) {
X		printf("Could not write to score file '%s'.\n",scorefile);
X	}
X	already_updated = 1;
X}
X
X/*
X * Get the name of the current user.
X */
Xchar *
Xget_name()
X{
X	char *s;
X	struct passwd *p;
X	if (s = (char *)getlogin())
X		return s;
X	p = (struct passwd *)getpwuid(getuid());
X	return p->pw_name;
X}
X
X/*
X * Read the score file.  The format is obvious.  Exactly 11 scores are always
X * returned.  The 11th is a sentinal with score '-1'.  If the score file did
X * not have 10, then the extras are for user '(nobody)', score 0.
X * A user name may not contain a "'".  The result of get_scores is an array
X * of score structures, statically allocated.
X */
Xstruct scores *
Xget_scores()
X{
X	struct scores *scp;
X	char *tmpfile, *getenv();
X	FILE *f;
X	if (scorefile) {
X		tmpfile = scorefile;
X	} else if ((tmpfile = getenv("SDI_SCORES")) == NULL) {
X			tmpfile = scorefile;
X	} else {
X		tmpfile = "/usr/games/lib/sdi_scores";
X	}
X	/* Try hard to open some kind of score file */
X	if (((f = fopen(tmpfile, "r+")) == NULL)) {
X		tmpfile = SCOREFILE;
X		if (((f = fopen(tmpfile, "r+")) == NULL)) {
X			tmpfile = "/usr/games/lib/sdi_scores";
X			if ((f = fopen("/usr/games/lib/sdi_scores", "r+")) == NULL)
X				return NULL;
X		}
X	}
X	scorefile = tmpfile;
X
X	/* read entries */
X	scp = sc;
X	while (scp < sc_end &&
X		(fscanf(f, " '%[^']' %d %d %d", scp->name, &scp->score, &scp->level, &scp->skill) == 4) &&
X		scp->score > 0) {
X		scp += 1;
X	}
X	while (scp < sc_end) {
X		strcpy(scp->name, "(nobody)");
X		scp->score = 0;
X		scp->level = 0;
X		scp->skill = 0;
X		scp += 1;
X	}
X	scp->score = -1;
X	fclose(f);
X	return sc;
X}
X
X/*
X * Write a list of scores to the score file.  Never called directly, except
X * by update_scores.
X */
Xput_scores(scp)
Xstruct scores *scp;
X{
X	FILE *f;
X	if ((f = fopen(scorefile, "w")) == NULL)
X		return 0;
X	/* write entries */
X	while (scp->score > 0) {
X		fprintf(f, "'%s' %d %d %d\n", scp->name, scp->score, scp->level, scp->skill);
X		scp += 1;
X	}
X	fclose(f);
X	return 1;
X}
X
X/*
X * This routine formats the score file for display when the 'scores'
X * button is pressed.
X */
Xstatic char string_for_build_scores[1024];
X
Xchar *
Xbuild_scores()
X{
X	char *sp = string_for_build_scores;
X	struct scores *scp;
X	char *type_of_skill;
X	scp = (struct scores *)get_scores();
X	if (scp == NULL) {
X		strcpy(sp, "Could not find a score file.");
X	} else {
X		strcpy(sp, "No scores yet: play some games.");
X		while (scp->score > 0) {
X			switch(scp->skill) {
X				case 0:
X					type_of_skill = " novice";
X					break;
X				case 1:
X					type_of_skill = "n occasional user";
X					break;
X				case 2:
X					type_of_skill = "n expert";
X					break;
X			}
X			sprintf(sp,
X				"%s, playing as a%s, melted with score %d at level %d.\n",
X				scp->name, type_of_skill, scp->score, scp->level);
X			scp += 1;
X			sp += strlen(sp);
X		}
X	}
X	return string_for_build_scores;
X}
X
X/*
X * Free the result of a call to build_scores.
X */
Xfree_scores(a)
Xchar **a;
X{
X/* Oh, how I long for garbage collection. */
X	while (*++a) 
X		free(*a);
X}
X
END_OF_scores.c
if test 4859 -ne `wc -c <scores.c`; then
    echo shar: \"scores.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f sdi.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"sdi.h\"
else
echo shar: Extracting \"sdi.h\" \(3256 characters\)
sed "s/^X//" >sdi.h <<'END_OF_sdi.h'
X/*
X * Copyright 1987 by Mark Weiser.
X * Permission to reproduce and use in any manner whatsoever is granted
X * so long as this copyright and other identifying marks of authorship
X * in the code and the game remain intact and visible.
X */
X/* includes needed by definitions in here, and so may as well put here */
X#include <suntool/sunview.h>
X#include <suntool/canvas.h>
X#include <suntool/panel.h>
X
X/* General Definitions */
X#undef min
X#undef max
X#define ABS(x) (((x) < 0) ? -(x) : (x))
X#define DOWN 1
X#define UP -1
X#define TRUE 1
X#define FALSE 0
X#define FIELD_MARGIN field_margin
X
X#define USER_NAME (user_name[0] == '\0' ? panel_get_value(user_name_item) : user_name)
X#define SAVE_FILE_NAME (save_file_name[0] == '\0' ? panel_get_value(save_file_item) : save_file_name)
X
X/* space to leave on either side of row of cities. */
X#define MARGIN 30
X
X/* minimum window size */
X#define MINWIN 128+(MARGIN*2)+(FIELD_MARGIN*2)
X
X/* Definitions affecting blasts */
Xextern struct circ {
X	int num_circles;
X	struct pixrect **circles;
X	struct pixrect **masks
X}	*lasercircles,
X	*laserkillcircles,
X	*bigblastcircles,
X	*littleblastcircles,
X	*blastkillcircles,
X	*citykillcircles,
X	*littlerockcircles,
X	*bigrockcircles,
X	*init_circ();
Xextern struct pixrect **blankcircles;
Xextern int blast_count;
Xstruct blast {
X	Pixwin *pw;
X	short x, y, circ, width;
X	short orig_y;		/* used only for hashing */
X	short x_inc, y_inc;
X	short num_circles;
X	struct pixrect **circles;
X	struct pixrect **masks;
X	struct blast *next;
X	Rect r;
X	};
X#define MAX_LINES	1024
X#define MAX_NUM_CIRCLES 8
X#define MAX_CIRCLE 64
X#define CIRCLE_SIZE_INC (MAX_CIRCLE/(MAX_NUM_CIRCLES+1))
X#define B_WIDTH(bid) ((bid)->width)
X#define B_HEIGHT(bid) ((bid)->width)
X#define B_OFFSET_X(bid) ((bid)->x-(B_WIDTH(bid)/2))
X#define B_OFFSET_Y(bid) ((bid)->y-(B_HEIGHT(bid)/2))
X
X/* Definitions affecting missiles */
Xextern int missile_count, burst_distance;
Xstruct missile {
X	Pixwin *pw;
X    short start_x, start_y,
X		old_x, old_y,
X		x, y, inc_x, inc_y,
X		slip_cnt, slip, speed, refs, destroyed;
X	struct missile *next;
X	};
X#define BALLISTIC_DELAY 5
X
X
X/* Definitions affecting everybody */
Xextern int suspended;
Xextern long blast_delay;
Xextern Pixwin *citypw, *launchpw;
Xextern int max_x, max_y;
Xextern int foe_value, running;
Xextern Panel_item level_item, interceptor_item, foe_item, score_item,
X	ballistic_item, btime_item, next_round_item, new_game_item, skill_item,
X	resume_item, suspend_item, laser_item, non_stop_item, name_item, 
X	rock_item, user_name_item, save_file_item;
Xextern char user_name[], save_file_name[];
Xextern int city_fd;
Xextern int launch_fd;
Xextern Canvas citycanvas;
Xextern Frame cityframe, controlframe, launchframe;
Xextern char *panel_common[];
Xstruct pixrect *make_circle();
Xextern Canvas launchcanvas;
Xextern int launch_delay;
Xextern int num_cities;
Xvoid no_events();
Xextern int total_cities_lost;
X#define NUM_SCORES 10
Xextern struct scores {
X	char name[64];
X	int score, level, skill;
X	} sc[], *sc_end;
Xextern float carryover_divisor, foe_divisor;
Xextern int foe_factor;
Xextern int min_missile_speed, max_missile_speed;
Xextern char *scorefile;
Xextern struct pixfont *font;	/* struct used for 3.0 compatibility */
Xextern Pixwin *need_a_bell;
Xextern int field_margin;
Xextern Panel_item total_foe_item;
END_OF_sdi.h
if test 3256 -ne `wc -c <sdi.h`; then
    echo shar: \"sdi.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f text.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"text.c\"
else
echo shar: Extracting \"text.c\" \(4472 characters\)
sed "s/^X//" >text.c <<'END_OF_text.c'
X/*****************************  text.c  ******************************/
X#include "sdi.h"
X#define PIES
X#ifdef PIES
X#include "piemenu.h"
X#endif
X
X/*
X * Copyright 1987 by Mark Weiser.
X * Permission to reproduce and use in any manner whatsoever on Suns is granted
X * so long as this copyright and other identifying marks of authorship
X * in the code and the game remain intact and visible.  Use of this code
X * in other products is reserved to me--I'm working on Mac and IBM versions.
X */
X
X/*
X * Find the size of the longest line in a string of lines separated by newlines
X */
Xmax_line(s)
Xchar *s;
X{
X	int max = 0, count = 0;
X	while (*s) {
X		if (*s++ == '\n') {
X			if (count > max)
X				max = count;
X			count = 0;
X			continue;
X		}
X		count += 1;
X	}
X	if (count > max)
X		max = count;
X	return max;
X}
X
X/*
X * Count the number of lines in a string of lines separated by newlines.
X */
Xcount_lines(s)
Xchar *s;
X{
X	int count = 0;
X	while (*s) {
X		if (*s++ == '\n')
X			count += 1;
X	}
X	return count+1;
X}
X
Xstatic char *help_msg[] = {
X#include "novice_advice.h"
X	,
X#include "occasional_advice.h"
X	,
X#include "expert_advice.h"
X	};
X
X/*
X * Display a brief message of advice appropriate to the current skill level.
X */
Xvoid
Xhelp_proc(item, event)
XPanel_item item;
XEvent *event;
X{
X	int skill = (int)panel_get_value(skill_item);
X	popup_msg(controlframe, event, help_msg[skill]);
X}
X
Xstatic char *about_msg = 
X#include "about_msg.h"
X	;
X/*
X * Display a brief informative message about the game.
X */
Xvoid
Xabout_proc(item, event)
XPanel_item item;
XEvent *event;
X{
X	popup_msg(controlframe, event, about_msg);
X}
X
Xstatic char *art_msg = "This space reserved for Marcel Duchamp";
X/*
X * Display a brief informative message about art.
X */
Xvoid
Xart_proc(item, event)
XPanel_item item;
XEvent *event;
X{
X	popup_msg(controlframe, event, art_msg);
X}
X
X/*
X * Display the complete source code of the game in a popup window.
X * The external variable 'source code' must be properly filled elsewhere.
X * (See the sdi makefile for one way.)
X */
Xvoid
Xsource_proc(item, event)
XPanel_item item;
XEvent *event;
X{
X	extern char *source_code;
X	popup_msg(controlframe, event, source_code);
X}
X
X/*
X * Display the history of the game's development in a popup window.
X * The external variable 'history_text' must be properly filled elsewhere.
X * (See the sdi makefile for one way.)
X */
Xvoid
Xhistory_proc(item, event)
XPanel_item item;
XEvent *event;
X{
X	extern char *history_text;
X	popup_msg(controlframe, event, history_text);
X}
X
X/*
X * Display the man entry in a popup (sort of) window.
X * The external variable 'man_text' must be properly filled elsewhere.
X * (See the sdi makefile for one way.)
X */
Xvoid
Xman_proc(item, event)
XPanel_item item;
XEvent *event;
X{
X	extern char *man_text;
X	popup_msg(controlframe, event, man_text);
X}
X
Xvoid
Xinstructions_proc()
X{
X	easy_pop(
X#include "instructions.h"
X		);
X}
X
Xvoid
Xversion_proc()
X{
X	extern char *version;
X	easy_pop(version);
X
X}
X
Xtext_options_proc(item, event)
XPanel_item item;
XEvent *event;
X{
X	extern scores_proc();
X	extern struct pixfont *buttonfont; /* use 'struct pixfont' for 3.0 compatiblity */
X	Menu_item mi;
X	Menu menu, menu_create();
X	int (*selection)();
X	suspend_proc();
X	menu = menu_create(MENU_NOTIFY_PROC, menu_return_item, 0);
X	menu_set(menu, MENU_APPEND_ITEM, menu_create_item(MENU_STRING, "Source", MENU_CLIENT_DATA, source_proc, 0), 0);
X	menu_set(menu, MENU_APPEND_ITEM, menu_create_item(MENU_STRING, "History", MENU_CLIENT_DATA, history_proc, 0), 0);
X	menu_set(menu, MENU_APPEND_ITEM, menu_create_item(MENU_STRING, "Man", MENU_CLIENT_DATA, man_proc, 0), 0);
X	menu_set(menu, MENU_APPEND_ITEM, menu_create_item(MENU_STRING, "Scores", MENU_CLIENT_DATA, scores_proc, 0), 0);
X	menu_set(menu, MENU_APPEND_ITEM, menu_create_item(MENU_STRING, "About", MENU_CLIENT_DATA, about_proc, 0), 0);
X	menu_set(menu, MENU_APPEND_ITEM, menu_create_item(MENU_STRING, "Art", MENU_CLIENT_DATA, art_proc, 0), 0);
X	menu_set(menu, MENU_APPEND_ITEM, menu_create_item(MENU_STRING, "Advice", MENU_CLIENT_DATA, help_proc, 0), 0);
X	menu_set(menu, MENU_APPEND_ITEM, menu_create_item(MENU_STRING, "Version", MENU_CLIENT_DATA, version_proc, 0), 0);
X	special_menu_show(menu, event);
X}
X
Xspecial_menu_show(menu, event)
X{
X	int notify_me();
X	pie_menu_show(menu, controlframe, event, notify_me, "Things To Read ('pie' form)");
X}
X
Xnotify_me(mi, event)
XMenu_item mi;
X{
X	int (*selection)();
X	if (mi != NULL){
X		(caddr_t)selection = (caddr_t)menu_item_get(mi, MENU_CLIENT_DATA);
X		(*selection)(0, event);
X	}
X	resume_proc();
X}
END_OF_text.c
if test 4472 -ne `wc -c <text.c`; then
    echo shar: \"text.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 3 \(of 6\).
cp /dev/null ark3isdone
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