Simple cave map generator

From RogueBasin
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

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.

Creates caves like this:

                 #.# ##.##        #.....#..# #..........#
                #..##.....#      ######....# #..#...#..# 
               #..##....### #  ##..##...#..##..##...##..#
              #.#......##..#.##...###.###..#...##..#  ## 
              #.#......##....#....#....# #...## #...#    
     #  #     #........# #.......##.....#.....# #...#    
    #.##.#    #........# ###...## #.........#.# #..#     
    #..#.#     ##...##.##.# #..# ##.........##   ##      
     #....##    #....###...##...#.##........#            
     #......#####.....##....#...#..#.....##..#           
    #.#####.#......###  #.#...#.##...##.# #.#            
  # #.#..#....##..##.####.#.######..###.###..#           
 #.#..............##......#.##...####...#.##.#           
##.#.#..#..........#.##..##.#....# #..#...# #            
#....#..#.............#...## #...##..##...#              
##...####...##..##.##...##  #...## ##  #..#              
  #...# #...##..###.....# ###.....###  ##..#             
   ##..#..#..#....#.#..# #...........##.....#            
  #....##.###.......##..###.##....###  ##.#..#           
   #......##...##.......#...##.....#  ###.##..#          
   #....#.........####......##.#..## #.....#..#          
   #..#.##..#....####.......# ##....# #.### ##           
    ## # #.###......##......# #..##..# #                 
        #............###.....# ###....#                  
        #...#.....#.......##.#####.#..#                  
        #...##....##..###....#....##..#                  
        #.##  ###.#...# #..###....##.#                   
        #..#    #......# #...##....#..#   

Annotated Javascript port available at http://jsfiddle.net/JesterBLUE/tfk9eo28/

/* 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);
}