void initmap(void) { int xi, yi; grid = (int**)malloc(sizeof(int*) * size_y); grid2 = (int**)malloc(sizeof(int*) * size_y); for(yi=0; yi<size_y; yi++) { grid [yi] = (int*)malloc(sizeof(int) * size_x); grid2[yi] = (int*)malloc(sizeof(int) * size_x); } for(yi=1; yi<size_y-1; yi++) for(xi=1; xi<size_x-1; xi++) grid[yi][xi] = randpick(); for(yi=0; yi<size_y; yi++) for(xi=0; xi<size_x; xi++) grid2[yi][xi] = TILE_WALL; for(yi=0; yi<size_y; yi++) grid[yi][0] = grid[yi][size_x-1] = TILE_WALL; for(xi=0; xi<size_x; xi++) grid[0][xi] = grid[size_y-1][xi] = TILE_WALL; }
bool cave_generate_map(struct dm_map *map, struct random *r, enum dm_dungeon_type type, coord_t *ul, coord_t *dr) { FIX_UNUSED(type); /* initialise cellular automata */ coord_t size = { .x = dr->x - ul->x, .y = dr->y - ul->y, }; struct ca_map *cmap = ca_init(&size); /* fill the map randomly with floors */ coord_t p; for (p.y = 0; p.y < size.y; p.y++) { for (p.x = 0; p.x < size.x; p.x++) { ca_set_coord(cmap, &p, randpick(r, 45) ); } } /* Fill the map with large caves */ for (int i = 0; i < 4; i++) { ca_generation(cmap, 16, 8, 2); } /* Do a few passes to make them less smooth */ for (int i = 0; i < 2; i++) { int ri = (random_int32(r) % 4) +2; ca_generation(cmap, 5, ri, 1); } /* translate the ca_map to the real map */ for(p.y = 0; p.y < size.y; p.y++) { for(p.x = 0; p.x < size.x; p.x++) { coord_t c = cd_add(ul, &p); /* check if the cell is alive or dead */ if (ca_get_coord(cmap, &p) == CA_ALIVE) { /* fill the tile with the specified type */ if(random_int32(r)%100 < 1) { dm_get_map_me(&c,map)->tile = ts_get_tile_specific(TILE_ID_MAD_CAP_FUNGUS); } else dm_get_map_me(&c,map)->tile = ts_get_tile_specific(TILE_ID_CONCRETE_FLOOR); } } } /* cleanup and return */ ca_free(cmap); return true; }
void Level::Generate() { // allocate memory for levels Tile** new_map = new Tile* [_h]; Tile** flooded_map = new Tile* [_h]; for(uint i = 0; i < _h; i++) { new_map[i] = new Tile [_w]; flooded_map[i] = new Tile [_w]; } while(1) { // randomly fill starting level for(uint y = 1; y < _h -1; y++) { for(uint x = 1; x < _w; x++) { _map[y][x] = tiles[randpick()]; } } // fill temp level with walls for(uint y = 0; y < _h; y++) { for(uint x = 0; x < _w; x++) { new_map[y][x] = tiles[MAP_WALL]; } } // ensure the level has outer walls for(uint y = 0; y < _h; y++) { _map[y][0] = _map[y][_w-1] = tiles[MAP_WALL]; } for(uint x = 0; x < _w; x++) { _map[0][x] = _map[_h-1][x] = tiles[MAP_WALL]; } // run cellular autonoma algorithm for(uint y = 1; y < _h - 1; y++) { for(uint x = 1; x < _w - 1; x++) { int adjcount_r1 = 0, adjcount_r2 = 0; for(int i = -1; i <= 1; i++) { for(int j = -1; j <= 1; j++) { if(_map[y+i][x+j].type != MAP_FLOOR) adjcount_r1++; } } for(uint i = y - 2; i <= y + 2; i++) { for(uint j = x - 2; j <= x + 2; j++) { if(abs(i-y) == 2 && abs(j-x) == 2) continue; if(i >= _h || j >= _w) continue; if(_map[i][j].type != MAP_FLOOR) adjcount_r2++; } } // select new tile for this position if(adjcount_r1 >= _r1_cutoff || adjcount_r2 <= _r2_cutoff) { new_map[y][x] = tiles[MAP_WALL]; } else { new_map[y][x] = tiles[MAP_FLOOR]; } } } // flood map from random floor cell int rnd_x, rnd_y; while(1) { rnd_x = rand() % _w; rnd_y = rand() % _h; if(new_map[rnd_y][rnd_x].type == MAP_FLOOR) break; } for(uint y = 0; y < _h; y++) { for(uint x = 0; x < _w; x++) { flooded_map[y][x] = tiles[MAP_WALL]; } } floodmap(new_map, flooded_map, rnd_x, rnd_y); // ensure that at least 1/2 of the map is floor uint floorcount = 0; for(uint y = 0; y < _h; y++) { for(uint x = 0; x < _w; x++) { if(flooded_map[y][x].type == MAP_FLOOR) floorcount++; } } if(floorcount > (_w*_h)/2) break; } // place stairs int rnd_x, rnd_y; while(1) { rnd_x = rand() % _w; rnd_y = rand() % _h; if(flooded_map[rnd_y][rnd_x].type == MAP_FLOOR) { flooded_map[rnd_y][rnd_x] = tiles[MAP_STAIR_DOWN]; _stairDown.x = rnd_x; _stairDown.y = rnd_y; break; } } while(1) { rnd_x = rand() % _w; rnd_y = rand() % _h; if(flooded_map[rnd_y][rnd_x].type == MAP_FLOOR) { flooded_map[rnd_y][rnd_x] = tiles[MAP_STAIR_UP]; _stairUp.x = rnd_x; _stairUp.y = rnd_y; break; } } // replace map with new one for(uint y = 1; y < _h - 1; y++) { for(uint x = 1; x < _w -1; x++) { _map[y][x] = flooded_map[y][x]; } } // free memory used up by temporary maps for(uint i = 0; i < _h; i++) { delete [] new_map[i]; delete [] flooded_map[i]; } delete [] new_map; delete [] flooded_map; // scatter items around level for(uint i = 0; i < LEVEL_HEIGHT / 2; i++) { Die tmp = {1, _h-1, 0}; uint y = DieRoll::Roll(tmp); tmp.Set(1, _w-1, 0); uint x = DieRoll::Roll(tmp); if(_map[y][x].type == MAP_FLOOR) _map[y][x].items.push_back(Item::Generate()); } }