GMLscripts.com

Discuss and collaborate on GML scripts
Invert

You are not logged in.

#1 2018-07-09 05:35:22

lostdarkwolf
Member
Registered: 2015-11-19
Posts: 19

generate a random boolean cave for a ds_grid (improved)

No required scripts. Enjoy!
EDIT: The last script worked okay, but it took me a while to realize that the generation didn't exactly do what I wanted it to do. This script has been corrected in that regard, and is more flexible.

/// generate_cave(ds_grid, path_repetitions*, expansion_repetitions*, smooth_repetitions*, safe_smoothing*, expansion_size_limit*, tries*, boundary_wall_width*)
// * argument not required
// 
// Turns a ds_grid into a simple boolean cave.
// The bigger the ds_grid is, the better the cave will look.
// 
// ds_grid                 The ds_grid to turn into a data-based cave. real
// path_repetitions        Approximate length of the initial cave path. real
// expansion_repetitions   How many times to randomly expand the cave. real
// smooth_repetitions      How many times to smooth the cave. If this value is -1, the script will then smooth until smoothing becomes redundant. real
// safe_smoothing          If true, smoothing will not create solids, just remove them. real
// expansion_size_limit    upper limit for the expansion radius, the lower limit is 1. real
// tries                   amount of tries for expansion. real
// boundry_wall_width      width of the solid edge around the ds_grid. Use zero for none. real
// 
// Generation avoids using noise.
// If safe_smoothing is on, every open point within the cave should be accessible.
// Expansion does not respect the ds_grid boundaries. Use it respectfully.
// Cell values are either one for solid, or zero for open.
//
/// GMLscripts.com/license

MAV_grid=argument[0];
var var_width; var_width=ds_grid_width(MAV_grid)-1;
var var_height; var_height=ds_grid_height(MAV_grid)-1;

var MAV_repetitions1; MAV_repetitions1=sqr(mean(var_width,var_height));
if argument_count>1 MAV_repetitions1=argument[1];
var MAV_repetitions2; MAV_repetitions2=mean(var_width,var_height);
if argument_count>2 MAV_repetitions2=argument[2];
var MAV_repetitions3; MAV_repetitions3=-1;
if argument_count>3 MAV_repetitions3=argument[3];
var var_safe_smoothing; var_safe_smoothing=1;
if argument_count>4 var_safe_smoothing=argument[4];
var MAV_expansion_size; MAV_expansion_size=floor(mean(var_width,var_height)/50);
if argument_count>5 MAV_expansion_size=argument[5];
var MAV_tries; MAV_tries=max(mean(var_width,var_height),100);
if argument_count>6 MAV_tries=argument[6];
var MAV_renew_boundary_wall_width; MAV_renew_boundary_wall_width=1;
if argument_count>7 MAV_renew_boundary_wall_width=argument[7];

//make the initial cave path
ds_grid_set_region(MAV_grid,0,0,var_width,var_height,1)
var iix, iiy, var_dir;
iix=floor(var_width/2);
iiy=floor(var_height/2);
repeat MAV_repetitions1 {
 ds_grid_set(MAV_grid,iix,iiy,0)
 var_dir=irandom(4);
 switch var_dir {
  case 0:
   iix+=1;
  break;
  case 1:
   iiy-=1;
  break;
  case 2:
   iix-=1;
  break;
  case 3:
   iiy+=1;
  break;
 }
 if iix<var_width*0.1 and irandom(var_width*0.1)=0 iix+=1;
 if iix>var_width*0.9 and irandom(var_width*0.1)=0 iix-=1;
 if iiy<var_height*0.1 and irandom(var_width*0.1)=0 iiy+=1;
 if iiy>var_height*0.9 and irandom(var_width*0.1)=0 iiy-=1;
 iix=median(round(iix),1,var_width-1);
 iiy=median(round(iiy),1,var_height-1);
}

// randomly expand the cave path
var iix, iiy, var_buddy_count;
if MAV_repetitions2>0 {
 var var_source_value, var_expand_way;
 var var_tries; var_tries=0;
 var var_runs_done; var_runs_done=0;
 var var_done; var_done=0;
 while var_done=0 {
  iix=median(2,irandom(var_width),var_width-2);
  iiy=median(2,irandom(var_height),var_width-2);
  var_source_value=ds_grid_get(MAV_grid,iix,iiy)
  if iix=2 or iix=var_width-2 var_source_value=1
  if iiy=2 or iiy=var_height-2 var_source_value=1
  var_buddy_count=ds_grid_get(MAV_grid,iix+1,iiy)+ds_grid_get(MAV_grid,iix,iiy-1)+ds_grid_get(MAV_grid,iix-1,iiy)+ds_grid_get(MAV_grid,iix,iiy+1)
  if not (var_source_value=1 and var_buddy_count=4 or var_source_value=0 and var_buddy_count=0) and var_source_value=0 {
   var_runs_done+=1;
   repeat irandom(2) {
    var_expand_way=irandom(3);
    var_expansion_size=1+random(MAV_expansion_size-1);
    if var_expand_way=0 ds_grid_set_disk(MAV_grid,iix+(var_expansion_size*0.75),iiy,var_expansion_size,var_source_value);
    if var_expand_way=1 ds_grid_set_disk(MAV_grid,iix,iiy-(var_expansion_size*0.75),var_expansion_size,var_source_value);
    if var_expand_way=2 ds_grid_set_disk(MAV_grid,iix-(var_expansion_size*0.75),iiy,var_expansion_size,var_source_value);
    if var_expand_way=3 ds_grid_set_disk(MAV_grid,iix,iiy+(var_expansion_size*0.75),var_expansion_size,var_source_value);
   }
  }
  else {
   var_tries+=1;
  }
  if var_tries>=MAV_tries var_done=1;
  if var_runs_done>=MAV_repetitions2 var_done=1;
 }
}

//smooth the cave
repeat max(MAV_repetitions3,0) {
 for (iix=var_width-1; iix>=1; iix-=1;) {
  for (iiy=var_height-1; iiy>=1; iiy-=1;) {
   var_buddy_count = ds_grid_get(MAV_grid,iix+1,iiy)+
                     ds_grid_get(MAV_grid,iix,iiy-1)+
                     ds_grid_get(MAV_grid,iix-1,iiy)+
                     ds_grid_get(MAV_grid,iix,iiy+1)+
                     ds_grid_get(MAV_grid,iix+1,iiy-1)+
                     ds_grid_get(MAV_grid,iix-1,iiy-1)+
                     ds_grid_get(MAV_grid,iix-1,iiy+1)+
                     ds_grid_get(MAV_grid,iix+1,iiy+1);
   if var_buddy_count<4 ds_grid_set(MAV_grid,iix,iiy,0)
   if var_buddy_count>5 and var_safe_smoothing=false ds_grid_set(MAV_grid,iix,iiy,1)
  }
 }
}
if MAV_repetitions3=-1 {
 var var_orig_val;
 var var_changes;
 var_changes=1;
 while var_changes>0 {
  var_changes=0;
  for (iix=var_width-1; iix>=1; iix-=1;) {
   for (iiy=var_height-1; iiy>=1; iiy-=1;) {
    var_buddy_count = ds_grid_get(MAV_grid,iix+1,iiy)+
                      ds_grid_get(MAV_grid,iix,iiy-1)+
                      ds_grid_get(MAV_grid,iix-1,iiy)+
                      ds_grid_get(MAV_grid,iix,iiy+1)+
                      ds_grid_get(MAV_grid,iix+1,iiy-1)+
                      ds_grid_get(MAV_grid,iix-1,iiy-1)+
                      ds_grid_get(MAV_grid,iix-1,iiy+1)+
                      ds_grid_get(MAV_grid,iix+1,iiy+1);
    if var_buddy_count<4 {
     var_orig_val=ds_grid_get(MAV_grid,iix,iiy);
     if var_orig_val!=0 {
      ds_grid_set(MAV_grid,iix,iiy,0)
      var_changes+=1;
     }
    }
    if var_buddy_count>5 and var_safe_smoothing=false {
     var_orig_val=ds_grid_get(MAV_grid,iix,iiy);
     if var_orig_val!=1 {
      ds_grid_set(MAV_grid,iix,iiy,1)
      var_changes+=1;
     }
    }
   }
  }
 }
}

// renew boundary wall
if MAV_renew_boundary_wall_width>0 {
 var var_line_number; var_line_number=0;
 repeat MAV_renew_boundary_wall_width {
  for (iix=var_width-1-var_line_number; iix>=1+var_line_number; iix-=1;) {
   ds_grid_set(MAV_grid,iix,var_line_number,1)
   ds_grid_set(MAV_grid,iix,var_height-1-var_line_number,1)
  }
  for (iiy=var_height-1-var_line_number; iiy>=1+var_line_number; iiy-=1;) {
   ds_grid_set(MAV_grid,var_line_number,iiy,1)
   ds_grid_set(MAV_grid,var_width-1-var_line_number,iiy,1)
  }
  var_line_number+=1;
 }
 for (iix=var_width-1-var_line_number; iix>=1+var_line_number; iix-=1;) {
  if irandom(1) ds_grid_set(MAV_grid,iix,var_line_number,1)
  if irandom(1) ds_grid_set(MAV_grid,iix,var_height-1-var_line_number,1)
 }
 for (iiy=var_height-1-var_line_number; iiy>=1+var_line_number; iiy-=1;) {
  if irandom(1) ds_grid_set(MAV_grid,var_line_number,iiy,1)
  if irandom(1) ds_grid_set(MAV_grid,var_width-1-var_line_number,iiy,1)
 }
}

Last edited by lostdarkwolf (2018-08-01 14:07:40)

Offline

Board footer

Powered by FluxBB