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