diff planets.c @ 3:5a977ccbc7a9 default tip

Empty changelog
author darius
date Sat, 06 Dec 1997 05:41:29 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/planets.c	Sat Dec 06 05:41:29 1997 +0000
@@ -0,0 +1,481 @@
+/* $Id: planets.c,v 1.1.1.1 1997/12/06 05:41:30 darius Exp $ */
+
+/*
+ * planets.c
+ *
+ * Kevin P. Smith  2/21/89
+ *
+ * This file contains the galaxy definition as well as some support for
+ *  determining when parts of the galactic map need to be redrawn.
+ */
+#include "copyright2.h"
+
+#include <stdio.h>
+#include <math.h>
+#include "Wlib.h"
+#include "defs.h"
+#include "struct.h"
+#include "data.h"
+#include "proto.h"
+
+/* define to get profiling info, to better set DEPTH and DETAIL [BDyess] */
+/*#define PROFILE1		/* maxdepth printed */
+/*#define PROFILE2		/* every PLREDRAW setting printed (VERBOSE) */
+
+/* Note:  DETAIL * MUST * be a factor of GWIDTH. */
+#define DETAIL 80		/* Size of redraw array */
+#define RADIUS 2		/* number of adjacent cells to register in */
+#define SIZE 2500
+#define DEPTH 8
+#ifdef PROFILE1
+#define ADDPLANET(i,j,k) { \
+    for(z=0;z<DEPTH;z++) { \
+	if(redraws[i][j][z] == (char)-1) { \
+	    redraws[i][j][z] = k; \
+	    break; \
+	} \
+    }  z++; \
+    if(z > maxdepth) maxdepth = z; \
+}
+#else				/* not PROFILEing */
+#define ADDPLANET(i,j,k) { \
+    for(z=0;z<DEPTH;z++) { \
+	if(redraws[i][j][z] == (char)-1) { \
+	    redraws[i][j][z]=k; \
+	    break; \
+	} \
+    } \
+}
+#endif				/* PROFILE1 */
+
+#define LEFT 	1		/* position flags for corner guessing */
+#define RIGHT 	2
+#define TOP 	4
+#define BOTTOM	8
+
+struct _star {
+    int     s_x, s_y;
+    int     s_color;
+};
+
+static void redrawStarSector P((struct _star star_sector[16]));
+
+/*
+   planets may be on top of each other or very close, so more than one planet
+   can exist in a given block.  The 3rd dimension is for a list of planets.
+   [BDyess]
+*/
+char    redraws[DETAIL][DETAIL][DEPTH];
+static int initialized = 0;
+
+/*
+   since planets may be moved, the redraw matrix must be updated.  This
+   function is for updating just one planet.  This should help the moving
+   planet efficiency problems quite a bit.  [BDyess]
+*/
+void
+initOnePlanet(pl)
+    struct planet *pl;
+{
+}
+
+/*
+   rewritten to repair UNBELIEVABLE inefficiencies in the original [BDyess]
+*/
+void
+initPlanets()
+{
+    register int i, j, k, x, y, z, r, s;
+    struct planet *pl;
+#ifdef PROFILE1
+    int     maxdepth = 0;
+#endif				/* PROFILE1 */
+
+    /* initialize lookup array */
+    for (i = 0; i < DETAIL; i++) {
+	for (j = 0; j < DETAIL; j++) {
+	    for (k = 0; k < DEPTH; k++) {
+		redraws[i][j][k] = -1;
+	    }
+	}
+    }
+
+    /*
+       check all the planets.  If part of the planet falls inside a box in
+       the lookup array, add it to the refresh list for that box.  [BDyess]
+    */
+    for (k = 0, pl = planets; k < nplanets; k++, pl++) {
+	x = pl->pl_x;
+	y = pl->pl_y;
+	i = x / SIZE - 3;
+	j = y / SIZE - 2;
+	/*
+	   fill cells around the target cell with the planetnum like so: ****
+	
+	**
+	
+	x** ****
+	
+	**
+	
+	**	taller than wide because of text ****
+	
+	[BDyess]
+	*/
+	for (r = 0; r < 5; r++) {
+	    i++;
+	    if (i <= 0)
+		continue;
+	    if (i >= DETAIL)
+		break;
+	    for (s = 0; s < 7; s++) {
+		j += s;
+		if (j <= 0)
+		    continue;
+		if (j >= DETAIL)
+		    break;
+		ADDPLANET(i, j, k)
+		    j -= s;
+	    }
+	}
+#if 0				/* this works, and allows the radius around
+				   the hot spot to be changed. It's disabled
+				   because a less-flexible piece of code
+				   (above) is a bit faster.  Plus, it's hard
+				   to generalize about that extra added
+				   lines.  [BDyess] */
+	ADDPLANET(i, j, k)
+	    for (r = 1; r <= RADIUS; r++) {
+	    /* draw box sides in all four directions */
+	    /* bottom */
+	    i += r;
+	    ADDPLANET(i, j, k)
+		for (s = 1; s <= r; s++) {
+		j += s;
+		ADDPLANET(i, j, k)
+		    j -= 2 * s;
+		ADDPLANET(i, j, k)
+		    j += s;
+	    }
+	    /* top */
+	    i -= 2 * r;
+	    ADDPLANET(i, j, k)
+		for (s = 1; s <= r; s++) {
+		j += s;
+		ADDPLANET(i, j, k)
+		    j -= 2 * s;
+		ADDPLANET(i, j, k)
+		    j += s;
+	    }
+	    /* left */
+	    i += r;
+	    j += r;
+	    ADDPLANET(i, j, k)
+		for (s = 1; s < r; s++) {
+		i += s;
+		ADDPLANET(i, j, k)
+		    i -= 2 * s;
+		ADDPLANET(i, j, k)
+		    i += s;
+	    }
+	    /* right */
+	    j -= 2 * r;
+	    ADDPLANET(i, j, k)
+		for (s = 1; s < r; s++) {
+		i += s;
+		ADDPLANET(i, j, k)
+		    i -= 2 * s;
+		ADDPLANET(i, j, k)
+		    i += s;
+	    }
+	}
+#endif				/* 0 */
+    }
+    initialized = 1;
+#ifdef PROFILE1
+    printf("max depth = %d\n", maxdepth);
+#endif				/* PROFILE1 */
+}
+
+void
+checkRedraw(x, y)
+    int     x, y;
+{
+    int     j;
+    char    i;
+
+    if (!initialized || x < 0 || y < 0 || x >= blk_gwidth || y >= blk_gwidth)
+	return;
+    x /= SIZE;
+    y /= SIZE;
+    for (j = 0; j < DEPTH; j++) {
+	i = redraws[x][y][j];
+	if (i == (char) -1)
+	    return;
+	planets[i].pl_flags |= PLREDRAW;
+#ifdef PROFILE2
+	printf("setting PLREDRAW flag for %s\n", planets[i].pl_name);
+#endif				/* PROFILE2 */
+    }
+}
+
+
+/* NOTE: this has been rewritten -- see below */
+
+#define NUMSTARS 1600
+
+static int starsX[NUMSTARS];
+static int starsY[NUMSTARS];
+
+void
+_initStars()
+{
+    register int i;
+
+    for (i = 0; i < NUMSTARS; i++) {
+	starsX[i] = (i % 40) * 5000 + random() % 5000;
+	starsY[i] = (i / 40) * 5000 + random() % 5000;
+    }
+}
+
+void
+_drawStars()
+{
+    int     i;
+    int     x, y;
+
+    for (i = 0; i < NUMSTARS; i++) {
+	x = starsX[i] - me->p_x;
+	y = starsY[i] - me->p_y;
+	if (ABS(x) < 10000 && ABS(y) < 10000) {
+	    x = x / SCALE + WINSIDE / 2;
+	    y = y / SCALE + WINSIDE / 2;
+	    W_DrawPoint(w, x, y, W_White);
+	    W_CacheClearArea(w, x, y, 1, 1);
+	}
+    }
+}
+
+/*
+ *  This rewrite improves drawStars() by a factor of about 30 (according to
+ *  gprof)
+ */
+
+/* blk_gwidth/(WINSIDE * SCALE) == 10 for blk_gwidth == 200000 */
+static struct _star stars[10][10][16];
+
+void
+initStars()
+{
+    register int i, j, k;
+
+    for (i = 0; i < 10; i++) {
+	for (j = 0; j < 10; j++) {
+	    for (k = 0; k < 16; k++) {
+		stars[i][j][k].s_x = i * (WINSIDE * SCALE) + random() % (WINSIDE * SCALE);
+		stars[i][j][k].s_y = j * (WINSIDE * SCALE) + random() % (WINSIDE * SCALE);
+		stars[i][j][k].s_color = randcolor();
+	    }
+	}
+    }
+}
+
+int
+randcolor()
+{
+    switch (random() % 10) {
+	case 0:return W_Yellow;
+    case 1:
+	return W_Red;
+    case 2:
+	return W_Green;
+    case 3:
+	return W_Cyan;
+    default:
+	return W_White;
+    }
+}
+
+void
+drawStars()
+{
+    /*
+       note: cpp symbols in expressions (WINSIDE*SCALE) will be precalculated
+       by any C optimizer
+    */
+    int     sectorx = me->p_x / (WINSIDE * SCALE), sectory = me->p_y / (WINSIDE * SCALE);
+    int     sector_offx = me->p_x - sectorx * (WINSIDE * SCALE), sector_offy = me->p_y - sectory * (WINSIDE * SCALE);
+    int     l = 0, r = 0, t = 0, b = 0;
+
+    if (sector_offx < 0) {	/* goddamn rounding towards 0 */
+	sectorx--;
+	sector_offx += WINSIDE * SCALE;
+    }
+    if (sector_offy < 0) {	/* goddamn rounding towards 0 */
+	sectory--;
+	sector_offy += WINSIDE * SCALE;
+    }
+#define	MAXSECTOR	(blk_gwidth/(WINSIDE*SCALE))
+
+    /* at worst we have to redraw 4 star sectors */
+
+    /* draw the one we're in */
+    /*
+       check first to make sure it's valid.  This is mainly important for if
+       it tries to redraw and we're already dead
+    */
+    if (sectorx < 0 || sectory < 0)
+	return;
+
+    l = sector_offx < (WINSIDE * SCALE) / 2 && sectorx > 0;
+    r = sector_offx > (WINSIDE * SCALE) / 2 && sectorx + 1 < MAXSECTOR;
+    t = sector_offy < (WINSIDE * SCALE) / 2 && sectory > 0;
+    b = sector_offy > (WINSIDE * SCALE) / 2 && sectory + 1 < MAXSECTOR;
+
+    if (t) {
+	if (l)			/* redraw upper-left sector */
+	    redrawStarSector(stars[sectorx - 1][sectory - 1]);
+
+	/* redraw upper sector */
+	redrawStarSector(stars[sectorx][sectory - 1]);
+
+	if (r)			/* redraw upper-right sector */
+	    redrawStarSector(stars[sectorx + 1][sectory - 1]);
+    }
+    if (l)			/* redraw left sector */
+	redrawStarSector(stars[sectorx - 1][sectory]);
+
+    /* redraw center sector */
+    redrawStarSector(stars[sectorx][sectory]);
+
+    if (r)			/* redraw right sector */
+	redrawStarSector(stars[sectorx + 1][sectory]);
+
+    if (b) {
+	if (l)			/* redraw bottom-left sector */
+	    redrawStarSector(stars[sectorx - 1][sectory + 1]);
+
+	/* redraw bottom sector */
+	redrawStarSector(stars[sectorx][sectory + 1]);
+
+	if (r)			/* redraw bottom-right sector */
+	    redrawStarSector(stars[sectorx + 1][sectory + 1]);
+    }
+    W_FlushPointCaches(w);
+}
+
+static void
+redrawStarSector(star_sector)
+    struct _star star_sector[16];
+{
+    register i, dx, dy, dxx, dyy;
+    register struct _star *s;
+    static int warpflag = 0;	/* assume starting out not in warp */
+    static int streaksOn = 0, lastspeed = 0, lastsubspeed = 0, updates = 0;
+    static int streaklength = 1;
+
+    if (warpStreaks) {
+	if (warpflag != (me->p_flags & PFWARP)) {	/* change in warp state */
+	    streaksOn = 1;
+	    warpflag = (me->p_flags & PFWARP);
+	}
+	if (streaksOn) {
+	    if (warpflag && (me->p_speed < lastspeed ||
+	    (me->p_speed == lastspeed && me->p_subspeed <= lastsubspeed))) {
+		/* finished accelerating */
+		updates++;
+		if (updates > 5) {
+		    lastspeed = me->p_speed;
+		    lastsubspeed = me->p_subspeed;
+		    updates = 0;
+		    streaksOn = 0;
+		    redrawStarSector(star_sector);
+		    return;
+		}
+	    } else if (streaklength == 1 || (!warpflag && ((me->p_speed > lastspeed) ||
+	    (me->p_speed == lastspeed && me->p_subspeed >= lastsubspeed)))) {
+		/* finished decelerating */
+		updates++;
+		if (updates > 5) {
+		    lastspeed = me->p_speed;
+		    lastsubspeed = me->p_subspeed;
+		    updates = 0;
+		    streaksOn = 0;
+		    streaklength = 1;
+		    redrawStarSector(star_sector);
+		    return;
+		}
+	    } else
+		updates = 0;
+	    lastspeed = me->p_speed;
+	    lastsubspeed = me->p_subspeed;
+	    /* draw the streaks */
+	    if (warpflag)
+		streaklength += 3;
+	    else
+		streaklength--;
+	    dxx = (int) (Cos[me->p_dir] * streaklength);
+	    dyy = (int) (Sin[me->p_dir] * streaklength);
+	    for (i = 0, s = star_sector; i < 16; i++, s++) {
+		dx = s->s_x - me->p_x;
+		dy = s->s_y - me->p_y;
+		if (ABS(dx) > (SCALE * WINSIDE / 2) || ABS(dy) > (SCALE * WINSIDE / 2))
+		    continue;
+
+		dx = dx / SCALE + WINSIDE / 2;
+		dy = dy / SCALE + WINSIDE / 2;
+		W_CacheLine(w, dx, dy, dx - dxx, dy - dyy, s->s_color);
+
+		clearline[0][clearlcount] = dx;
+		clearline[1][clearlcount] = dy;
+		clearline[2][clearlcount] = dx - dxx;
+		clearline[3][clearlcount] = dy - dyy;
+		clearlcount++;
+	    }
+	    return;
+	}
+    }
+    for (i = 0, s = star_sector; i < 16; i++, s++) {
+	dx = s->s_x - me->p_x;
+	dy = s->s_y - me->p_y;
+	if (ABS(dx) > (SCALE * WINSIDE / 2) || ABS(dy) > (SCALE * WINSIDE / 2))
+	    continue;
+
+	dx = dx / SCALE + WINSIDE / 2;
+	dy = dy / SCALE + WINSIDE / 2;
+	W_CachePoint(w, dx, dy, s->s_color);
+#ifndef AMIGA
+	/*
+	   this is a minor kludge: as long as there are less then 128 stars
+	   in a sector these cached requests will not actually be written to
+	   the X server until the next redraw cycle begins.
+	*/
+	W_CacheClearArea(w, dx, dy, 1, 1);
+#else
+	clearline[0][clearlcount] = dx;
+	clearline[1][clearlcount] = dy;
+	clearline[2][clearlcount] = dx;
+	clearline[3][clearlcount] = dy;
+	clearlcount++;
+#endif
+    }
+}
+
+#if 0
+void
+clearStars()
+{
+    int     i;
+    int     x, y;
+
+    for (i = 0; i < NUMSTARS; i++) {
+	x = starsX[i] - me->p_x;
+	y = starsY[i] - me->p_y;
+	if (ABS(x) < 10000 && ABS(y) < 10000) {
+	    x = x / SCALE + WINSIDE / 2;
+	    y = y / SCALE + WINSIDE / 2;
+	    W_CacheClearArea(w, x, y, 1, 1);
+	}
+    }
+}
+#endif