Cellular automata generator
Interesting cave systems can be created using ROT.Map.Cellular
, a generator which simulates a cellular automaton. Using this generator is a bit more complex,
because it offers richer features and is more configurable.
Apart from the traditional width and height arguments, ROT.Map.Cellular
accepts also a configuration object with the following optional keys:
born
– array of neighbor counts; when an empty cell has this number of neighbors, a new cell is born
survive
– array of neighbor counts; when an existing cell has this number of neighbors, it will survive into next iteration
topology
– how are neighbors defined: a cell can have four, six or eight neighbors. Six neighbors correspond to the "hex" layouting algorithm
of ROT.Display.
It is also possible to initialize/set values for the first generation of cells. Two methods are provided:
set(x, y, value)
to directly set a cell
randomize(probability)
set all cells to "alive" with a given probability (0 = no cells, 1 = all cells)
It is possible (and desirable) to call the create
method repeatedly: every call will create a new generation. There is no need to specify a callback,
if you only want to advance into next generation, without actually retrieving the current map data. By default, the born and survive options
are set according to this Roguebasin article.
ROT.Map.Cellular
uses the following callback values:
var w = 80, h = 40;
var map = new ROT.Map.Cellular(w, h);
/* cells with 1/2 probability */
map.randomize(0.5);
/* generate and show four generations */
for (var i=0; i<4; i++) {
var display = new ROT.Display({width:w, height:h, fontSize:4});
SHOW(display.getContainer());
map.create(display.DEBUG);
}
var w = 100, h = 60;
var display = new ROT.Display({width:w, height:h, fontSize:6});
SHOW(display.getContainer());
/* custom born/survive rules */
var map = new ROT.Map.Cellular(w, h, {
born: [4, 5, 6, 7, 8],
survive: [2, 3, 4, 5]
});
map.randomize(0.9);
/* generate fifty iterations, show the last one */
for (var i=49; i>=0; i--) {
map.create(i ? null : display.DEBUG);
}
Once the map has been created, you can optionally call connect() to connect every free space. This way the player can traverse every part of the maze. You might have to refresh this page a few times to spot the differences.
var w = 80, h = 40;
/* create a map */
var map = new ROT.Map.Cellular(w, h);
/* cells with 1/2 probability */
map.randomize(0.5);
/* make a few generations */
for (var i=0; i<4; i++) map.create();
/* display only the final map */
var display = new ROT.Display({width:w, height:h, fontSize:4});
SHOW(display.getContainer());
map.create(display.DEBUG);
/* now connect the maze so the player can reach all non-wall sections */
var display = new ROT.Display({width:w, height:h, fontSize:4});
SHOW(display.getContainer());
map.connect(display.DEBUG);
You can also connect walls instead of empty space by specifying the map value that should be connected. See the second parameter of the connect() call below:
var w = 80, h = 40;
/* create a map */
var map = new ROT.Map.Cellular(w, h);
/* cells with 1/2 probability */
map.randomize(0.5);
/* make a few generations */
for (var i=0; i<4; i++) map.create();
/* display only the final map */
var display = new ROT.Display({width:w, height:h, fontSize:4});
SHOW(display.getContainer());
map.create(display.DEBUG);
/* now connect the maze so the player can reach all non-wall sections */
var display = new ROT.Display({width:w, height:h, fontSize:4});
SHOW(display.getContainer());
map.connect(display.DEBUG, 1);
Finally, you can be optionally notified when connect creates a new connection between formerly separate regions.
var w = 80, h = 40;
/* create a map */
var map = new ROT.Map.Cellular(w, h);
/* cells with 1/2 probability */
map.randomize(0.5);
/* make a few generations */
for (var i=0; i<4; i++) map.create();
/* display only the final map */
var display = new ROT.Display({width:w, height:h, fontSize:4});
SHOW(display.getContainer());
map.create(display.DEBUG);
/* now connect the maze */
var display = new ROT.Display({width:w, height:h, fontSize:4});
SHOW(display.getContainer());
map.connect(display.DEBUG, 0, function(from, to) {
SHOW("Connection was made " + from + " to " + to);
});