Cellular Automata Cave
see below links:
http://roguebasin.roguelikedevelopment.org/index.php?title=Cellular_Automata_Method_for_Generating_Random_Cave-Like_Levels
http://codiecollinge.wordpress.com/2012/08/24/simple_2d_cave-like_generation/
http://jeremykun.com/2012/07/29/the-cellular-automaton-method-for-cave-generation/
I used B678/S345678 rule.
B678 : if (tile == wall) tile's neighbor num of road == 6 ~ 8, tile = road, else tile = wall
S345678 : if(tile == road) tile's neighbor num of road == 3~8, tile = road, else tile = wall
/**
* Copyright greentec ( http://wonderfl.net/user/greentec )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/sBNk
*/
package {
import flash.display.Sprite;
import com.bit101.components.Label;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import com.bit101.components.PushButton;
import com.bit101.components.NumericStepper;
[SWF(width=465, height=465, backgroundColor=0x292929, frameRate=60)]
public class FlashTest extends Sprite {
public var mapData:Vector.<Vector.<Boolean>>;
public var mapWidth:int = 100;
public var mapHeight:int = 100;
public var mapCellWidth:int = 4;
public var mapCellHeight:int = 4;
public var mapFullWidth:int = 400;
public var mapFullHeight:int = 400;
public var mapBitmapData:BitmapData;
public var mapBitmap:Bitmap;
public var mapSprite:Sprite;
public var wallColor:uint = 0xff212121;
public var roadColor:uint = 0xffFDECC0;
public var roadProb:Number = 0.5;
public var initMapButton:PushButton;
public var stepMapButton:PushButton;
public var generationLabel:Label;
public var generationNo:int = 0;
public var changeLabel:Label;
public var mapWidthLabel:Label;
public var mapWidthNumericStepper:NumericStepper;
public var mapHeightLabel:Label;
public var mapHeightNumericStepper:NumericStepper;
public function FlashTest() {
// write as3 code here..
mapBitmapData = new BitmapData(465, 465, true, 0x00ffffff);
mapBitmap = new Bitmap(mapBitmapData);
mapBitmap.x = 10;
mapBitmap.y = 10;
addChild(mapBitmap);
mapSprite = new Sprite();
initMapButton = new PushButton(this, 10, mapFullHeight + mapBitmap.y + 10, "Init Map", initMap);
stepMapButton = new PushButton(this, initMapButton.x + initMapButton.width, initMapButton.y, "Next Step", stepMap);
generationLabel = new Label(this, stepMapButton.x + stepMapButton.width + 5, stepMapButton.y, "Generation 0");
//drawMap();
changeLabel = new Label(this, 300, generationLabel.y, "0 cell Changed");
mapWidthLabel = new Label(this, 10, initMapButton.y + initMapButton.height + 5, "mapWidth");
mapWidthNumericStepper = new NumericStepper(this, mapWidthLabel.x + mapWidthLabel.width + 10, mapWidthLabel.y, null);
mapWidthNumericStepper.value = mapWidth;
mapWidthNumericStepper.minimum = 10;
mapWidthNumericStepper.maximum = 200;
mapHeightLabel = new Label(this, mapWidthNumericStepper.x + mapWidthNumericStepper.width + 10, mapWidthNumericStepper.y, "mapHeight");
mapHeightNumericStepper = new NumericStepper(this, mapHeightLabel.x + mapHeightLabel.width + 10, mapHeightLabel.y, null);
mapHeightNumericStepper.value = mapHeight;
mapHeightNumericStepper.minimum = 10;
mapHeightNumericStepper.maximum = 200;
initMap(new Event(MouseEvent.CLICK));
}
private function drawMap():void
{
var i:int;
var j:int;
mapWidth = mapWidthNumericStepper.value;
mapHeight = mapHeightNumericStepper.value;
mapCellWidth = mapFullWidth / mapWidth;
mapCellHeight = mapFullHeight / mapHeight;
mapCellWidth = Math.min(mapCellWidth, mapCellHeight);
mapCellHeight = mapCellWidth;
mapBitmapData.fillRect(mapBitmapData.rect, 0x00ffffff);
mapSprite.graphics.clear();
//mapSprite.graphics.lineStyle(0, 0xcccccc);
for (i = 0; i < mapData.length; i += 1)
{
for (j = 0; j < mapData[i].length; j += 1)
{
if (mapData[i][j] == true)
{
mapSprite.graphics.beginFill(roadColor);
}
else
{
mapSprite.graphics.beginFill(wallColor);
}
mapSprite.graphics.drawRect(i * mapCellWidth, j * mapCellHeight, mapCellWidth, mapCellHeight);
mapSprite.graphics.endFill();
}
}
mapBitmapData.draw(mapSprite);
generationLabel.text = "Generation " + String(generationNo);
}
private function stepMap(e:Event):void
{
var i:int;
var j:int;
var change:int = 0;
for (i = 0; i < mapData.length; i += 1)
{
for (j = 0; j < mapData[i].length; j += 1)
{
var numWall:int = 0;
if (i > 0 && j > 0)// LU
{
if (mapData[i - 1][j - 1] == false)
{
numWall += 1;
}
}
else //border == wall
{
numWall += 1;
}
if (j > 0) // U
{
if (mapData[i][j - 1] == false)
{
numWall += 1;
}
}
else
{
numWall += 1;
}
if (i<mapWidth - 1 && j > 0)// RU
{
if (mapData[i + 1][j - 1] == false)
{
numWall += 1;
}
}
else
{
numWall += 1;
}
if (i > 0)// L
{
if (mapData[i - 1][j] == false)
{
numWall += 1;
}
}
else
{
numWall += 1;
}
if (i < mapWidth - 1) // R
{
if (mapData[i + 1][j] == false)
{
numWall += 1;
}
}
else
{
numWall += 1;
}
if (i > 0 && j < mapHeight - 1) // LD
{
if (mapData[i -1][j + 1] == false)
{
numWall += 1;
}
}
else
{
numWall += 1;
}
if (j < mapHeight - 1) // D
{
if (mapData[i][j + 1] == false)
{
numWall += 1;
}
}
else
{
numWall += 1;
}
if (i < mapWidth - 1 && j < mapHeight - 1)// RD
{
if (mapData[i + 1][j + 1] == false)
{
numWall += 1;
}
}
else
{
numWall += 1;
}
//if (mapData[i][j] == false)//self
//{
//numWall += 1;
//}
if (mapData[i][j] == false) //B678
{
if (numWall <= 2)
{
mapData[i][j] = true; // birth
change += 1;
}
}
else //S345678
{
if (numWall >= 6)
{
mapData[i][j] = false; // can't survive - die
change += 1;
}
}
}
}
generationNo += 1;
changeLabel.text = String(change) + " cell(s) changed";
drawMap();
}
private function initMap(e:Event):void
{
var i:int;
var j:int;
mapData = new Vector.<Vector.<Boolean>>(mapWidth);
for (i = 0; i < mapData.length; i += 1)
{
mapData[i] = new Vector.<Boolean>(mapHeight);
for (j = 0; j < mapData[i].length; j += 1)
{
if (Math.random() < roadProb)
{
mapData[i][j] = true;
}
else
{
mapData[i][j] = false;
}
}
}
generationNo = 0;
drawMap();
}
}
}