Simple cave map generator

From RogueBasin
Revision as of 16:07, 14 March 2013 by Rsaarelm (talk | contribs) (Create page)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

A cave map generator by Ray Dillinger from rec.games.roguelike.development:

Message-Id: <48d8aa27$0$33580$742ec2ed@news.sonic.net>

Here, have a cave generator.  I wrote this, anybody can use it.
/* a simple program for generating caves. */

#include <stdio.h>
#include <stdlib.h>

#define X 60
#define XCENTER 30
#define Y 30
#define YCENTER 15

char map[X][Y];

int dieroll (int min, int max){
  int randomnum;
  int range = (max + 1 - min);
  int divisor = RAND_MAX / range;  
  for (randomnum = random();
       RAND_MAX-randomnum < RAND_MAX % range;
       randomnum = random());
  randomnum /= divisor;
  return(randomnum + min);
}


void cavegen(){
  int adjfloor;
  int adjwall;
  int uncommittedcount = X * Y - 1;
  int wallcount = 0;
  int floorcount = 1;
  int x;
  int y;
  int xmin = XCENTER - 1;
  int ymin = YCENTER - 1;
  int xmax = XCENTER + 1;
  int ymax = YCENTER + 1;
  int iterationlimit = 0;
  /* initialize to all uncommitted. */
  for (x = 0; x < X; x++){
    for (y = 0; y < Y; y++){
      map[x][y]='?';
    }
  }
  /* clear a center starting point. */
  map[XCENTER][YCENTER] = '.';

  do{
    iterationlimit++;
    x = dieroll (xmin, xmax);
    y = dieroll (ymin, ymax);
    if (map[x][y] == '?' || dieroll(1,100) == 1){
      if (x == xmin && x > 1) xmin--;
      if (x == xmax && x < X-2) xmax++;
      if (y == ymin && y > 1) ymin--;
      if (y == ymax && y < Y-2) ymax++;
      adjfloor = 0;
      if (map[x-1][y] == '.') adjfloor++;
      if (map[x+1][y] == '.') adjfloor++;
      if (map[x][y-1] == '.') adjfloor++;
      if (map[x][y+1] == '.') adjfloor++;
      adjwall = 0;
      if (map[x-1][y] == '#') adjwall++;
      if (map[x+1][y] == '#') adjwall++;
      if (map[x][y-1] == '#') adjwall++;
      if (map[x][y+1] == '#') adjwall++;

      if (adjfloor){
        if (uncommittedcount + floorcount > X * Y / 2 && 
            (adjwall > adjfloor || wallcount * 3 < floorcount * 2)){
          if (map[x][y] == '?')uncommittedcount--;
          if (map[x][y] == '.') floorcount--;
          if (map[x][y] != '#') wallcount++;
          map[x][y]='#';
        }
        else {
          if (map[x][y] == '?' ) uncommittedcount--;
          if (map[x][y] == '#' ) wallcount--;
          if (map[x][y] != '.' ) floorcount++;
          map[x][y] = '.';
        }
      }
    }
  }while (iterationlimit < X * Y * 500 && floorcount < X * Y / 3);
  for (x = 1; x < X-1; x++){
    for (y = 1; y < Y-1; y++){
      adjfloor = 0;
      if (map[x-1][y] == '.') adjfloor++;
      if (map[x+1][y] == '.') adjfloor++;
      if (map[x][y-1] == '.') adjfloor++;
      if (map[x][y+1] == '.') adjfloor++;
      
      if (adjfloor && map[x][y] == '?') map[x][y] = '#';
      if (adjfloor == 4) map[x][y] = '.';
      if (!adjfloor) map[x][y] = ' ';    
    }
  }
}

int main()
/* just a testing harness: hit spacebar to quit. */
{
  int x;
  int y;
  do{
    cavegen();
    for (y = 1; y < Y-1; y++){
      for (x = 1; x < X-1; x++){
        printf("%c", map[x][y]);
      }
      printf("\n");
    }
  } while (getchar() != ' ');
  return(0);
}