JSFiddle - React, Tailwind, and code Playground

by Gwyn Milcote

HTML

Cell coats.<br>
<button class='regen'>New map</button> | <button class='simulate'>Another step</button>
<br>
Birth Limit: <input type="number" class="birth" min="1" max="6" value="4"> 
Death Limit: <input type="number" class="death" min="1" max="6" value="3"><br>
Initial Chance: <input type="number" class="chance" min="0" max="1" step="0.1" value="0.4"> 
Number Of Steps: <input type="number" class="steps" min="0" max="6" value="3"><br>
Width: <input type="number" class="width" min="8" max="128" value="64">
Height: <input type="number" class="height" min="8" max="128" value="64"> Tile: <input type="number" class="tile_size" min="1" max="12" value="5"><hr>
Layer 2.  <button class='extra'>Generate</button><br>
Birth: <input type="number" class="e_birth" min="1" max="6" value="4"> 
Death: <input type="number" class="e_death" min="1" max="6" value="3"><br>
Chance: <input type="number" class="e_chance" min="0" max="1" step="0.1" value="0.4"> 
Steps: <input type="number" class="e_steps" min="0" max="6" value="3"><br>

<p>
<div><canvas id="gameCanvas"></canvas></div>
</p>

<button class='export_terrain'>Export Terrain</button> <button class='export_all'>Export All</button>
<br><div class='exported_map'></div>

CSS

input {width: 50px;}

.map_holder {
    font-size: 0px;
}

.map_tile {
    width: 16px;
    height: 16px;
    display: inline-block;
    margin: 0px;
    position: relative;
}

.map_tile img {
    position: absolute;
    top: 0px;
    left: 0px;
    width: 100%;
    height: 100%;
}

/* Textarea where data is exported into. */
.exported_map {
    border: 1px solid black;
    width: 100%;
    resize: none;
    padding: 10px;
    max-height: 200px;
    overflow: auto;
}

JavaScript

// 2D array. Is each tile solid, walkable, or maybe-walkable?
var world = [[]];

var palette_cave = ["#0d0d0d", "#808080", "#2e5cb8", "#4d4d4d"];

// Total size of the map.
var width = 48;
var height = 48;

// Size of a tile in pixels. Only needed for canvas drawing.
var tileWidth = 5;
var tileHeight = 5;


// Chance for each cell to be seeded alive, at first.
var chance = 0.4;
// death limit? how many cells around
var death = 3;
// birth limit? how many cells around
var birth = 4;
// How many 'generations' to run the simulator.
var steps = 3;

// Vars just for generating the 'extra' terrain layer.
// Water, lava, rocks, thick mist... certain species can pass.
// Some biomes need big lakes/seas, others tiny patches/ponds.
var e_chance = 0.4;
var e_death = 3;
var e_birth = 4;
var e_steps = 3;

// Lists of possible items, monsters to pick from.
// For realism, 2 groups depending on terrain.
var ground_items = [1,2,3,4,5];
var water_items = [6,7,8,9];
var ground_monsters = [1,2,3,4,5];
var water_monsters = [6,7,8,9];

// And, how many should be scattered on map?
var item_count = 10;
var monster_count = 10;

// Store the current ones scattered.
var items = [];
var monsters = [];


// Generate random number between 2 numbers.
function randomNumber(min, max){
  return Math.floor(Math.random() * (max - min + 1) + min);
}

// Get a random thing from an array.
function randomArray(array){
    return array[Math.floor(Math.random()*array.length)];
}

// Two ways of exporting. First is simple...
$('.export_terrain').click(function(){
    $('.exported_map').html("2D terrain array:<br>" + JSON.stringify(world) );
});

// Turn 2D array, items and monsters into one object.
$(".export_all").click(function(){
    var object_map = [];
    
    // First, fill with objects, with terrain numbers.
    for(var i = 0; i < world.length; i++){
        // Begin blank row.
        var new_row = [];
        // Fetch current terrain row.
        var row = world[i];
        for(var j = 0; j <...