DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T c

⟦b6a91e293⟧ TextFile

    Length: 7166 (0x1bfe)
    Types: TextFile
    Names: »cities.c«

Derivation

└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
    └─⟦this⟧ »EUUGD18/Sun/Sdi/cities.c« 

TextFile

/**********************************  cities.c  ************************/
#include <pixrect/pixrect_hs.h>
#include <stdio.h>
#include "sdi.h"
#include <sunwindow/notify.h>

/*
 * Copyright 1987 by Mark Weiser.
 * Permission to reproduce and use in any manner whatsoever on Suns is granted
 * so long as this copyright and other identifying marks of authorship
 * in the code and the game remain intact and visible.  Use of this code
 * in other products is reserved to me--I'm working on Mac and IBM versions.
 */

/*
 * Code to do things to cities.  Much of the code here consists of
 * passing a routine into doto_cities, which then calls that routine
 * on each city.  See the comment for doto_cities (near the end of the file)
 * for more information.
 */

static short default_city_data[] = {
#include "default_city.h"
};
mpr_static(default_city_pr, 64, 64, 1, default_city_data);

static struct pixrect *city_pr_ptr = &default_city_pr;
static colormap_t city_colormap, *city_colormap_ptr = NULL;

static short melted_city_data[] = {
#include "melt.h"
};
mpr_static(melted_city_pr, 64, 64, 1, melted_city_data);


#define MIN_SPACE 4
#define MAX_CITIES 40

static int city_space, excess, global_count;
static long bits_in_city;

static int do_update(), do_count(), do_placement(), do_kill(), 
	   do_update_all(), do_grow(), do_update_cities(), do_melt_all(); 

static int cities_inited = 0;
static short cities[MAX_CITIES];


static int growcount;	/* ugh, another weird global.
						 * set by do_update_cities, used only by 'do_grow'.
						 */

/*
 * Read a new city pixrect from a file.
 */
init_city_bits(filename)
char *filename;
{
	/* this routine is only called if there is non-default city. */
	if (filename != NULL) {
			char error_msg[256];
			struct pixrect *tmp,*icon_load_mpr();
			if ((tmp = icon_load_mpr(filename, error_msg)) == NULL) {
				printf("Could not get pr '%s'.\n", filename);
				printf("%s",error_msg);
				printf("Using default cities.\n");
			} else {
				city_pr_ptr = tmp;
			}
	}
}

/*
 * Compute the positions of all the cities based on current screen size,
 * and declare all the cities to be unmelted.
 */
init_cities()
{
	int i, old_num_cities = num_cities;
	bits_in_city = count_bits(city_pr_ptr);
	num_cities = ((max_x - MARGIN)/64) + 1;	/* bigger than possible */
	city_space = 0;

	while (city_space < MIN_SPACE) {
		num_cities -= 1;
		city_space = ((max_x - MARGIN) - (num_cities * 64))/(num_cities-1);
	};
	
	excess = max_x - (MARGIN + 64*num_cities + city_space*(num_cities-1));
	for (i=old_num_cities; i<num_cities; i++) {
		cities[i] = 1;
	}	
	cities_inited = 1;
}

/*
 * display the cities, melted or otherwise.
 */
place_cities(pw)
Pixwin *pw;
{
	pw_writebackground(pw, 0, max_y-8, max_x, max_y, PIX_NOT(PIX_SRC));
	doto_cities(pw, do_placement, city_pr_ptr, 0);
	doto_cities(pw, do_placement, &melted_city_pr, 1);
}

/* helper for 'place_cities', passed into 'doto_cities' */
static int
do_placement(pr, city_pr)
struct pixrect *pr, *city_pr;
{
	pr_rop(pr, 0, 0, 64, 64, PIX_SRC, city_pr, 0, 0);
	return 1;	/* this forces the new city back into the pixwin */
}

/*
 * Pop a new city onto the display at a random empty position.
 */
new_city(pw)
Pixwin *pw;
{
	int pick, num_gone = 0, i;
	for (i=0; i < num_cities; i += 1) {
		if (!cities[i])
			num_gone += 1;
	}
	if (num_gone == 0)
		return;
	pick = (random() % num_gone) + 1;
	for (i=0; i < num_cities; i += 1) {
		if (!cities[i] && !--pick)
			break;
	}
	/* restore a random melted city */
	cities[i] = 1;
	do_update_cities(pw, 1, do_grow);
}

/* helper for do_update_cites, grow a city. */
static int
do_grow(pr, speed)
struct pixrect *pr;
{
	grow(pr, city_pr_ptr, growcount+16);
	return 1;
}

/* return how many died */
static int global_citycount;
compute_cities(pw)
Pixwin *pw;
{
	global_citycount = 0;
	doto_cities(pw, do_count, 0, 0);
	return global_citycount;
}

/* helper for 'compute_cities', passed into 'doto_cities' */
static int
do_count(pr, client)
struct pixrect *pr;
int *client;
{
	if (city_dead(pr)) {
		global_citycount += 1;
	}
	return 0;	/* avoids pw_write in doto_cities */
}

/*
 * Melt or grow each city, as appropriate.
 */
update_cities(pw, speed)
{
	do_update_cities(pw, speed, do_update);
	doto_cities(pw, do_kill, 0, 0);
}

/* helper for 'update_cities', passed to 'do_update_cities', grows or melts. */
static int
do_update(pr, speed)
struct pixrect *pr;
int speed;
{
	if (city_dead(pr)) {
		melt(pr, &melted_city_pr, speed);
		return 1;	
	} else {
		grow(pr, city_pr_ptr, growcount+16);
		return 1;   
	}
}

/* Helper for 'update_cities', passed into doto_cities, computes dead cities. */
static int
do_kill(pr, tmp)
struct pixrect *pr;
{
	if (city_dead(pr))
		cities[global_count] = 0;
	return 0;
}

/* Do what it says. */
melt_all_cities(pw, speed)
{
	do_update_cities(pw, speed, do_melt_all);
}


/* helper for 'melt_all_cities', passed into 'do_update_cities' */
static int
do_melt_all(pr, speed)
struct pixrect *pr;
int speed;
{
	melt(pr, &melted_city_pr, speed);
	return 1;	/* forces writing out the melted city in doto_cities */
}

/*
 * Call function 'helper' numerous times on each city, thus causing
 * growing or melting (or both), depending upon 'helper'.
 */
static int
do_update_cities(pw, speed, helper)
int (*helper)();
{
	int i;
	int count = (64 / speed) + 1;
	for (growcount = 1; growcount < count; growcount += 1) {
		/* we might plausibly batch here, but the melt looks better without */
		doto_cities(pw, helper, speed, 0);
	}
}

/*
   Cities are a kind of abstract datatype.  To do something to all
   cities, pass a function and a piece of client data to 'doto_cities',
   and the function will be called once for each city still in
   existence (or if 'non-cities' is non-zero, once for each city NOT
   still in existence.)  The calling sequence for the passed in
   function will be:
		func(pr, client_data);
   where 'pr' is a 64x64 pixrect of a city.  If 'func' returns 0 then
   'pr' is assumed to be unchanged, otherwise 'pr' is written back into
   the pixwin so the change is visible. Global_count is set before the
   call to the ordinal number of the city currently being operated on.

   Init_cities must be called before any city operations.
 */

static char tmp_image_place[512];
mpr_static(tmpcity_pr, 64, 64, 1, tmp_image_place);

doto_cities(pw, func, client_data, non_cities)
Pixwin *pw;
int (*func)();
int *client_data;
{
	int x = MARGIN/2 + excess/2, stop_x = max_x - MARGIN/2 - 64;
	int y = max_y - 64;
	if (! cities_inited) {
		/* no return from here */
		printf("'doto_cities called before 'init_cities'.\n");
		abort();
	}
	global_count = 0;
	while (x <= stop_x) {
		if ((!non_cities && cities[global_count]) ||
				(non_cities && !cities[global_count])) {
			pw_read(&tmpcity_pr, 0, 0, 64, 64, PIX_SRC, pw, x, y);
			if (func(&tmpcity_pr, client_data))
				pw_write(pw, x, y, 64, 64, PIX_SRC, &tmpcity_pr, 0, 0);
		}
		global_count += 1;
		x += 64 + city_space;
	}
}

/*
 * See if a city is dead.  It is if 2/3's of its pixels are clobbered.
 */
city_dead(pr)
struct pixrect *pr;
{
	long bitcount = count_bits(pr);
	if (bitcount < 2*bits_in_city/3)
		return 1;
	else return 0;
}