diff src/terrain.c @ 8:0836fb919dfa

First entry of Paradise Server 2.9 patch 10 Beta
author darius
date Sat, 06 Dec 1997 04:37:05 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/terrain.c	Sat Dec 06 04:37:05 1997 +0000
@@ -0,0 +1,365 @@
+/*--------------------------------------------------------------------------
+NETREK II -- Paradise
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any NON-COMMERCIAL purpose (following the terms of
+the GNU General Public License (read the file 'COPYING')) and without
+fee is hereby granted, provided that this copyright notice appear in all
+copies.  No representations are made about the suitability of this
+software for any purpose.  This software is provided "as is" without
+express or implied warranty.
+
+    Xtrek Copyright 1986                            Chris Guthrie
+    Netrek (Xtrek II) Copyright 1989                Kevin P. Smith
+                                                    Scott Silvey
+    Paradise II (Netrek II) Copyright 1993          Larry Denys
+                                                    Kurt Olsen
+                                                    Brandon Gillespie
+
+    Comprehensive credits are available in the file "CREDITS"
+--------------------------------------------------------------------------*/
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include "struct.h"
+#include "data.h"
+#include "shmem.h"
+#include "terrain.h"
+
+#define MAXALTITUDE 255
+#define MAXSTARS 20
+#define X 0
+#define Y 1
+
+void 
+generate_terrain()
+/*
+ * Generates terrain based on specs in the system configuration. Places a
+ * number of "seeds" into the terrain grid, and then generates an "altitude"
+ * map based on those seeds' positions (which correspond to star positions).
+ * Place_nebula generates another altitude map for nebulae -- the first map
+ * is used for asteroids and generating the second map.
+ * 
+ * This function is called within the galaxy generation stuff.
+ * 
+ * 10/26/94 MM
+ */
+{
+  int i, j, k;			/* counters */
+  int x, y;			/* more counters, different purpose */
+  double dist, val;		/* for distance calculations */
+  int num_seeds = 0;
+  int seed_xy[MAXSTARS][2];
+  int qx[4] = {-1, 1, -1, 1}, qy[4] = {1, 1, -1, -1};	/* quadrant multipliers */
+
+  /*
+   * place seeds -- this would be easy to change if you just had a number of
+   * seeds you wanted to place, instead of basing it on stars.  I won't
+   * bother doing it, even though it might be cool to see it work in a bronco
+   * game...  MM
+   */
+
+  for (i = 0; i < NUMPLANETS; i++)
+    if (PL_TYPE(planets[i]) == PLSTAR)
+    {
+      terrain_grid[(planets[i].pl_x / TGRID_GRANULARITY) * TGRID_SIZE +
+		   planets[i].pl_y / TGRID_GRANULARITY].alt1 = MAXALTITUDE;
+
+      seed_xy[num_seeds][X] = planets[i].pl_x / TGRID_GRANULARITY;
+      seed_xy[num_seeds][Y] = planets[i].pl_y / TGRID_GRANULARITY;
+      num_seeds++;
+    }
+
+  /* generate terrain -- simple, stupid version. */
+
+
+  for (x = 0; x < TGRID_SIZE; x++)
+    for (y = 0; y < TGRID_SIZE; y++)
+      if (terrain_grid[x * TGRID_SIZE + y].alt1 != MAXALTITUDE)
+      {
+	val = 0.0;
+	for (i = 0; i < num_seeds; i++)
+	{
+	  dist = (double) MAXALTITUDE -
+	    sqrt((double) ((x - seed_xy[i][X]) * (x - seed_xy[i][X]) +
+			   (y - seed_xy[i][Y]) * (y - seed_xy[i][Y])));
+	  if (dist > val)
+	    val = dist;
+	}
+	/* reset any previous terrain values */
+	terrain_grid[x * TGRID_SIZE + y].types = 0x00;
+
+	terrain_grid[x * TGRID_SIZE + y].alt1 = (int) val;
+	terrain_grid[x * TGRID_SIZE + y].alt2 = 0;
+      }
+
+  /* place nebula */
+  if (num_nebula)
+    place_nebula(*num_nebula, *nebula_subclouds, *nebula_density);
+  /* place asteroids */
+  if (num_asteroid)
+    place_asteroids(MAXALTITUDE - (*asteroid_radius));
+}
+
+void 
+place_nebula(int num_nebula, int num_seeds, int minalt)
+/*
+ * Values inbetween MAXALTITUDE and minalt are considered nebulous terrain.
+ * Tries to cluster seeds in groups based on num_nebula and num_seeds. ...the
+ * number of seeds per nebula being num_seeds. 10/26/94 MM
+ */
+{
+  int i = 0, j = 0, x, y, dx, dy, dist, lowdist = 2 * TGRID_SIZE;
+  int *seeds1, *seeds2;
+
+  seeds1 = (int *) malloc(num_nebula * sizeof(int));
+  if (num_seeds)
+    seeds2 = (int *) malloc(num_seeds * sizeof(int) * num_nebula);
+
+  /* find a local minimum, and place a "seed" */
+  while (i < num_nebula)
+  {
+    j = (int) lrand48() % (TGRID_SIZE * TGRID_SIZE);
+    if (j == 0)
+      j = 1;
+    while ((j < (TGRID_SIZE * TGRID_SIZE)) &&
+	   ((terrain_grid[j - 1].alt1 < terrain_grid[j].alt1) ||
+	    (terrain_grid[j + 1].alt1 < terrain_grid[j].alt1)))
+      j++;
+    seeds1[i] = j;
+    terrain_grid[seeds1[i]].alt2 = MAXALTITUDE;
+    i++;
+  }
+  /* group num_seeds more "sub seeds" around each seed */
+  /*
+   * (there are a couple bugs in this algorithm yet -- theres a wierd
+   * wraparound occasionally.  MDM, 8/23/95)
+   */
+
+  for (i = 0; i < num_nebula; i++)
+    for (j = 0; j < num_seeds; j++)
+    {
+      dx = (int) (lrand48() % ((MAXALTITUDE - minalt) * 3)) -
+	(int) (lrand48() % (int) ((MAXALTITUDE - minalt) * (1.5)));
+      dy = (int) (lrand48() % ((MAXALTITUDE - minalt) * 3)) -
+	(int) (lrand48() % (int) ((MAXALTITUDE - minalt) * (1.5)));
+      if (seeds1[i] / TGRID_SIZE + dx < 0)
+	dx -= (seeds1[i] / TGRID_SIZE + dx);
+      if (seeds1[i] / TGRID_SIZE + dx >= TGRID_SIZE)
+	dx -= (seeds1[i] / TGRID_SIZE + dx) - (TGRID_SIZE - 1);
+      if (seeds1[i] / TGRID_SIZE + dy < 0)
+	dy -= (seeds1[i] / TGRID_SIZE + dy);
+      if (seeds1[i] / TGRID_SIZE + dy >= TGRID_SIZE)
+	dy -= (seeds1[i] / TGRID_SIZE + dy) - (TGRID_SIZE - 1);
+      seeds2[i * num_seeds + j] = (seeds1[i] / TGRID_SIZE + dx) * TGRID_SIZE +
+	(seeds1[i] % TGRID_SIZE + dy);
+      terrain_grid[seeds2[i * num_seeds + j]].alt2 = MAXALTITUDE;
+    }
+
+  /*
+   * assign random-ish values, from a distance-from-seed base value (density
+   * is the randomness -- low density values are smooth, high are rough)
+   */
+  /* randomness NYI */
+  /*
+   * these values could be used in combination with the alt1 values to do
+   * other funky terrain "shapes, but I'm putting in the ABS() speedup stuff
+   * in for now anyway.  It'll result in alt2 values of 0 for any spot
+   * outside a nebulous radius -- MDM
+   */
+  for (x = 0; x < TGRID_SIZE; x++)
+    for (y = 0; y < TGRID_SIZE; y++)
+    {
+      for (i = 0; i < num_nebula; i++)
+      {
+	dx = (seeds1[i] / TGRID_SIZE) - x;
+	dy = (seeds1[i] % TGRID_SIZE) - y;
+	/* loop speedup */
+	if ((ABS(dx) <= MAXALTITUDE - minalt) &&
+	    (ABS(dy) <= MAXALTITUDE - minalt))
+	{
+	  dist = (int) sqrt(dx * dx + dy * dy);
+	  if (dist < lowdist)
+	    lowdist = dist;
+	}
+	if (num_seeds)
+	  for (j = 0; j < num_seeds; j++)
+	  {
+	    dx = seeds2[i * num_seeds + j] / TGRID_SIZE - x;
+	    dy = seeds2[i * num_seeds + j] % TGRID_SIZE - y;
+	    /* loop speedup */
+	    if ((ABS(dx) <= MAXALTITUDE - minalt) &&
+		(ABS(dy) <= MAXALTITUDE - minalt))
+	    {
+	      dist = (int) sqrt(dx * dx + dy * dy);
+	      if (dist < lowdist)
+		lowdist = dist;
+	    }
+	  }
+      }
+      terrain_grid[x * TGRID_SIZE + y].alt2 = MAXALTITUDE - lowdist;
+      lowdist = 2 * TGRID_SIZE;
+    }
+
+  /* give each spot with a high enuf alt value the nebulous terrain flag. */
+  for (i = 0; i < TGRID_SIZE; i++)
+    for (j = 0; j < TGRID_SIZE; j++)
+      if (terrain_grid[i * TGRID_SIZE + j].alt2 >= minalt)
+	terrain_grid[i * TGRID_SIZE + j].types |= T_NEBULA;
+
+  free(seeds1);
+  free(seeds2);
+}
+
+void 
+place_asteroids(int altitude)
+/*
+ * Marks terrain grid locations within density of altitude as asteroid
+ * fields.  I may make the chance of such a grid location becoming a field
+ * random (like 90% or something), so that fields will appear less uniform,
+ * and holes may exist in them.  Makes for interesting terrain, IMO. 10/26/94
+ * MM
+ */
+{
+  int x, y, i, j, numstars = 0, attempts = 0;
+  int *systems_with_asteroids;
+  int *star_numbers;
+  int *varied_rad;
+  int *varied_dens;
+  float *varied_thick;
+	
+  printf("placing asteroids\n");
+  star_numbers = (int *) malloc((NUMPLANETS) * sizeof(int));
+  for (i = 0; i < NUMPLANETS; i++)
+    if (PL_TYPE(planets[i]) == PLSTAR)
+    {
+      star_numbers[numstars] = i;
+      numstars++;
+    }
+  systems_with_asteroids = (int *) malloc(numstars * sizeof(int));
+  varied_rad = (int *) malloc(numstars * sizeof(int));
+  varied_dens = (int *) malloc(numstars * sizeof(int));
+  varied_thick = (float *) malloc(numstars * sizeof(float));
+  for (i = 0; i < numstars; i++)
+    systems_with_asteroids[i] = 0;
+	
+  /*
+   * assign what stars have asteroid belts -- I could just start with system
+   * #1, since systems are placed randomly, but I might as well pick a random
+   * system to start with.  The only prereq is that the system does NOT
+   * belong to a race. (prereq NYI)
+   */
+  if (*num_asteroid > (numstars - 4))
+    *num_asteroid = numstars - 4;
+
+  i = 0;
+  while (i < *num_asteroid)
+  {
+    j = lrand48() % numstars;
+   
+		if (((planets[j].pl_system < 1) || (planets[j].pl_system > 4))
+				&& (systems_with_asteroids[j] == 0))
+      systems_with_asteroids[j] = 1;
+		else
+			continue;
+		
+    i++;
+		
+    if ((*asteroid_rad_variance) == 0)
+      varied_rad[j] = altitude;
+    else
+      varied_rad[j] = altitude - ((*asteroid_rad_variance) / 2) +
+			lrand48() % (*asteroid_rad_variance);
+		
+    if ((*asteroid_dens_variance) == 0)
+      varied_dens[j] = *asteroid_density;
+    else
+      varied_dens[j] = (*asteroid_density) - ((*asteroid_dens_variance) / 2) +
+			lrand48() % (*asteroid_dens_variance);
+		
+    varied_thick[j] = (*asteroid_thickness) - ((*asteroid_thick_variance) / 2.0)
+		+ drand48() * (*asteroid_thick_variance);
+
+    attempts++;
+		
+    if (attempts > 1000)
+    {
+      printf("Too many attempts - giving up\n");
+      break;
+    }
+  }
+	
+	for (i = 0; i < numstars; i++)
+		if (systems_with_asteroids[i])
+			printf("System %s has an asteroid belt\n", planets[star_numbers[i]].pl_name);
+	
+	for (x = 0; x < TGRID_SIZE; x++)
+	{
+		for (y = 0; y < TGRID_SIZE; y++)
+		{
+      for (i = 0; i < numstars; i++)
+      {
+				/*
+				 * if the tgrid locale is within a certain distance of a system that
+				 * is supposed to have an asteroid belt, then, AST_CHANCE percent of
+				 * the time, mark that locale as having asteroids
+				 */
+				if (systems_with_asteroids[i] &&
+						terrain_grid[x * TGRID_SIZE + y].alt1 >= varied_rad[i] - 
+						(varied_thick[i]) && terrain_grid[x * TGRID_SIZE + y].alt1 
+						<= varied_rad[i] + (varied_thick[i]) &&	(ABS(x * TGRID_GRANULARITY - 
+																												 planets[star_numbers[i]].pl_x) <
+																										 (MAXALTITUDE - (varied_rad[i] - 
+																																		 (varied_thick[i] + 1.0)))
+																										 * TGRID_GRANULARITY) &&
+						(ABS(y * TGRID_GRANULARITY - planets[star_numbers[i]].pl_y) <
+						 (MAXALTITUDE - (varied_rad[i] - (varied_thick[i] + 1.0))) * TGRID_GRANULARITY) &&
+						lrand48() % 100 < varied_dens[i])
+				{
+					printf("terrain grid %d has asteroids\n", x * TGRID_SIZE + y);
+					terrain_grid[x * TGRID_SIZE + y].types |= T_ASTEROIDS;
+				}
+      }
+		}
+	}
+}
+
+void 
+doTerrainEffects()
+/*
+ * apply terrain effects to players
+ * 
+ * I REALLY wish I could add a "skill" element to many of the effects, but its
+ * tough. Asteroid damage is the most notable example where skill *should* be
+ * a factor, but isn't. MDM
+ */
+{
+  struct player *p;
+  int i, j, dam;
+
+  for (i = 0; i < MAXPLAYER; i++)
+  {
+    p = &(players[i]);
+    if (p->p_status != PALIVE)
+      continue;
+    if (TERRAIN_TYPE((p->p_x) / TGRID_GRANULARITY, (p->p_y) / TGRID_GRANULARITY) &
+	T_ASTEROIDS)
+    {
+      j = lrand48() % 100;
+      /* the player is in an asteroid location */
+      if (p->p_speed != 0)
+      {
+	if (ast_effect[SS_IMPULSE] &&
+	    (j < (100 - ((p->p_ship.s_turns / (p->p_speed * p->p_speed)) / 200)) ||
+	     (j < MIN_AST_HIT)))
+	{
+	  dam = lrand48() % (VAR_AST_DAMAGE * p->p_speed) + MIN_AST_DAMAGE;
+	  if (inflict_damage(0, 0, p, dam, KASTEROID) == 1)
+	    p->p_whydead = KASTEROID;
+	}
+      }
+    }
+  }
+}