A WIP Roguelike game by Adekto, VonBednat, Trelemar and Wuuff made for CGAJam in spring 2017
Dependencies: PokittoLib
Fork of Arcade by
mapgen.c
- Committer:
- Pokitto
- Date:
- 2018-05-21
- Revision:
- 15:67fb7b0c1149
- Parent:
- 10:590a26231903
File content as of revision 15:67fb7b0c1149:
#include <stdio.h> #include <stdlib.h> #define MAPSIZE 64 #define ID_FLOOR 0 #define ID_WALL_TOP 1 #define ID_WALL 2 #define ID_WALL_SKULL 3 #define ID_WALL_FLAME 4 #define ID_WALL_HOLE 5 #define ID_WALL_SHIELD 6 #define ID_COLUMN_TOP_SQUARE_1 7 #define ID_COLUMN_TOP_SQUARE_2 9 #define ID_COLUMN_TOP_SQUARE_3 10 #define ID_COLUMN_TOP_ROUND_1 11 #define ID_COLUMN_TOP_ROUND_2 13 #define ID_COLUMN_BOTTOM_SQUARE_1 8 #define ID_COLUMN_BOTTOM_ROUND_1 12 #define ID_COLUMN_BOTTOM_ROUND_2 14 #define ID_COFFIN_CLOSED_TOP 15 #define ID_COFFIN_CLOSED_BOTTOM 16 #define ID_COFFIN_OPEN_TOP 17 #define ID_COFFIN_OPEN_BOTTOM 18 #define ID_COBWEB 33 void mapinit(char map[][MAPSIZE], int width, int height); void mapgen(char map[][MAPSIZE], int mapwidth, int mapheight, int startx, int starty, int endx, int endy); void mapprint(char map[][MAPSIZE], int width, int height); void mapinit(char map[][MAPSIZE], int width, int height){ int i,j; //Fill with empty space for( i = 0; i < width; i++ ){ for( j = 0; j < height; j++ ){ map[j][i] = 0; } } //Generate walls around the edges for( i = 0; i < width; i++ ){ map[0][i] = 1; map[height-1][i] = 1; } for( j = 0; j < height; j++ ){ map[j][0] = 1; map[j][width-1] = 1; } } #define HORIZONTAL 0 #define VERTICAL 1 #define MIN_WIDTH 6 #define MIN_HEIGHT 8 #define HALL_CHANCE 40 #define MIN_HALL_WIDTH 8 #define MIN_HALL_HEIGHT 10 #define MAX_HALL_WIDTH 18 #define MAX_HALL_HEIGHT 20 #define EXTRA_DOOR 10 #define REM_WALL_CHANCE 25 #define MAX_REM_WALL 10 void mapgen(char map[][MAPSIZE], int mapwidth, int mapheight, int startx, int starty, int endx, int endy){ int i,j,orientation,position,door,door2,doorcount,hall,colspacex,colspacey,remwall; int width = endx-startx; int height = endy-starty; if( width < MIN_WIDTH && height < MIN_HEIGHT ){ return; } //Determine whether to generate a big hall with pillars or not. //The size of the room determines the column spacing for now if( width >= MIN_HALL_WIDTH && height >= MIN_HALL_HEIGHT && width < MAX_HALL_WIDTH && height < MAX_HALL_HEIGHT ){ hall = rand()%100;//Percent chance out of 100 if( HALL_CHANCE > hall ){ hall = rand()%3;//Choose type of hall; square columns, round columns, or coffins //Place room columns as densely as the room supports //IF you can divide the room into columns evenly //but make sure there is greater than one space between columns colspacex = width; if( colspacex%2 != 0 ){ colspacex--; } while( colspacex%2 == 0 && colspacex > 4 ) colspacex /= 2; colspacey = height; if( colspacey%4 != 0 ) { while( colspacey%4 != 0 ) colspacey++; } while( colspacey%4 == 0 && colspacey > 4 ) colspacey /= 4; for( i = startx+colspacex; i < startx + width - 1; i+=colspacex ){ for( j = starty+colspacey; j < starty + height - 2; j+=colspacey ){ if( hall == 0 ){//Square columns switch( rand()%3 ){ case 0: map[j][i] = ID_COLUMN_TOP_SQUARE_1; break; case 1: map[j][i] = ID_COLUMN_TOP_SQUARE_2; break; case 2: map[j][i] = ID_COLUMN_TOP_SQUARE_3; break; } map[j+1][i] = ID_COLUMN_BOTTOM_SQUARE_1; }else if( hall == 1 ){//Round columns switch( rand()%2 ){ case 0: map[j][i] = ID_COLUMN_TOP_ROUND_1; break; case 1: map[j][i] = ID_COLUMN_TOP_ROUND_2; break; } switch( rand()%2 ){ case 0: map[j+1][i] = ID_COLUMN_BOTTOM_ROUND_1; break; case 1: map[j+1][i] = ID_COLUMN_BOTTOM_ROUND_2; break; } }else{//Coffins switch( rand()%2 ){ case 0: map[j][i] = ID_COFFIN_CLOSED_TOP; map[j+1][i] = ID_COFFIN_CLOSED_BOTTOM; break; case 1: map[j][i] = ID_COFFIN_OPEN_TOP; map[j+1][i] = ID_COFFIN_OPEN_BOTTOM; break; } } } } return;//Do not subdivide; return immediately } } //Determine whether we will split the space //horizontally or vertically by choosing whichever //orientation is larger (this avoids extremely long rooms) if( width >= height ){ //If there is a door (or more than one door!) into a small room, //we may not be able to generate a wall in any location! //so abort if room is min + number of horiz door tiles doorcount = 0; for( i = startx; i < endx; i++ ){ if( map[starty][i] == 0 ) doorcount++; if( map[endy][i] == 0 ) doorcount++; } if( width < MIN_WIDTH + doorcount ){ return; } orientation = VERTICAL; //puts("Trying vertical"); }else{ //If there is a door (or more than one door!) into a small room, //we may not be able to generate a wall in any location! //so abort if room is min + number of vert door tiles doorcount = 0; for( i = starty; i < endy; i++ ){ if( map[i][startx] == 0 ) doorcount++; if( map[i][endx] == 0 ) doorcount++; } if( height < MIN_HEIGHT + doorcount ){ return; } orientation = HORIZONTAL; //puts("Trying horizontal"); } //printf("startx %d, starty %d\n",startx,starty); //mapprint(map,MAPSIZE,MAPSIZE); position = -1; if( orientation == HORIZONTAL ){ //Make sure the position is valid: //1. It must have generated at least one number //2. It must not be too close to existing walls //3. It must not be over a door while( position == -1 || position < starty + (MIN_HEIGHT/2) || position > endy - (MIN_HEIGHT/2) || map[position][startx] == 0 || map[position][endx] == 0 ){ position = starty + (rand()%height); } //Generate a door at a random position door = startx + 1 + (rand()%(width-1)); //Generate an extra door if wall is long enough. //Doors may overlap or be next to each other because such //doors shouldn't be a problem and it might result in interesting maps. //If it is not long enough set to -1 so it won't interfere door2 = width >= EXTRA_DOOR ? startx + 1 + (rand()%(width-1)) : -1; //printf("HORIZ %d\n",position); for( i = startx+1; i < startx + width; i++ ){ if( i != door && i != door2 ) map[position][i] = 1; } //Determine whether or not we will remove a wall. //We can't remove bottom and right walls because the regions beyond them //haven't been generated yet, so we only try to remove top and left walls. //If we are not on the map edges if( startx > 0 && endx < mapwidth-1 ){ //If the new space is taller than it is wide //and the wall is short enough if( /*position - starty > width &&*/ position - starty < MAX_REM_WALL ){ remwall = 1; //Check if there is no wall touching the wall we want to remove. //If not, we can remove the wall for( i = starty+1; i < position; i++ ){ if( map[i][startx-1] != 0 ){ remwall = 0; break; } } if( remwall && REM_WALL_CHANCE > (rand()%100) ){ for( i = starty+1; i < position; i++ ){ map[i][startx] = 0;//2;//Clear left side of upper half } } } //If the new space is taller than it is wide //and the wall is short enough if( /*endy - position > width &&*/ endy - position < MAX_REM_WALL ){ remwall = 1; //Check if there is no wall touching the wall we want to remove. //If not, we can remove the wall for( i = position+1; i < endy; i++ ){ if( map[i][startx+1] != 0 ){ remwall = 0; break; } } if( remwall && REM_WALL_CHANCE > (rand()%100) ){ for( i = position+1; i < endy; i++ ){ map[i][startx] = 0;//4;//Clear left side of lower half } } } } //Recursively call to fill the two new spaces we generated mapgen(map, mapwidth, mapheight, startx, starty, endx,position); mapgen(map, mapwidth, mapheight, startx, position, endx, endy); }else if( orientation == VERTICAL ){ //Make sure the position is valid: //1. It must have generated at least one number //2. It must not be too close to existing walls //3. It must not be over a door while( position == -1 || position < startx + (MIN_WIDTH/2) || position > endx - (MIN_WIDTH/2) || map[starty][position] == 0 || map[endy][position] == 0 ){ position = startx + (rand()%width); } //Generate a door at a random position //(allocating space for it to be 2 high) door = starty + 1 + (rand()%(height-2)); //Generate an extra door if wall is long enough. //Doors may overlap or be next to each other because such //doors shouldn't be a problem and it might result in interesting maps. //If it is not long enough set to -1 so it won't interfere door2 = height >= EXTRA_DOOR ? starty + 1 + (rand()%(height-2)) : -1; //printf("VERT %d\n",position); for( i = starty+1; i < starty + height; i++ ){ if( i != door && i != door+1 && i != door2 && i != door2+1 ) map[i][position] = 1; } //Determine whether or not we will remove a wall. //We can't remove bottom and right walls because the regions beyond them //haven't been generated yet, so we only try to remove top and left walls. //If we are not on the map edges if( starty > 0 && endy < mapheight-1 ){ //If the new space is wider than it is tall //and the wall is short enough if( /*position - startx > height &&*/ position - startx < MAX_REM_WALL ){ remwall = 1; //Check if there is no wall touching the wall we want to remove. //If not, we can remove the wall for( i = startx+1; i < position; i++ ){ if( map[starty-1][i] != 0 ){ remwall = 0; break; } } if( remwall && REM_WALL_CHANCE > (rand()%100) ){ for( i = startx+1; i < position; i++ ){ map[starty][i] = 0;//3;//Clear top side of left half } } } //If the new space is wider than it is tall //and the wall is short enough if( /*endx - position > height &&*/ endx - position < MAX_REM_WALL ){ remwall = 1; //Check if there is no wall touching the wall we want to remove. //If not, we can remove the wall for( i = position+1; i < endx; i++ ){ if( map[starty-1][i] != 0 ){ remwall = 0; break; } } if( remwall && REM_WALL_CHANCE > (rand()%100) ){ for( i = position+1; i < endx; i++ ){ map[starty][i] = 0;//5;//Clear top side of right half } } } } //Recursively call to fill the two new spaces we generated mapgen(map, mapwidth, mapheight, startx, starty, position,endy); mapgen(map, mapwidth, mapheight, position, starty, endx, endy); } } void mapprint(char map[][MAPSIZE], int width, int height){ int i,j; for( i = 0; i < height; i++ ){ for( j = 0; j < width; j++ ){ if( map[i][j] == 0 ){ printf("0"); }else if( map[i][j] == 1 ){ printf("1"); } } puts(""); } } void mappretty(char map[][MAPSIZE],int width, int height){ int i,j,v; for (i=0; i < height-1; i++) { for (j=0;j<width-1;j++){ if (map[i][j]==1 && map[i+1][j]==0){ v = rand()%25 + 3; //If v is any of the random wall variations if( v <= ID_WALL_SHIELD ){ map[i+1][j] = v; }else { map[i+1][j]=ID_WALL; } } if (map[i][j]==0 && map[i+1][j]==1 && map[i][j-1]==1 && rand()%10 <=1) { map[i][j]=ID_COBWEB; } } } } //char map[MAPSIZE][MAPSIZE]; /* int main(int argc, char** argv){ srand(42);//Can choose the seed to get the same map every time mapinit(map,MAPSIZE,MAPSIZE); mapgen(map,MAPSIZE,MAPSIZE,0,0,MAPSIZE-1,MAPSIZE-1); mapprint(map,MAPSIZE,MAPSIZE); } */