Simple cave map generator

From RogueBasin
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.

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