Evolutionary Symmetry

In this example below you will see how to do a Evolutionary Symmetry with some HTML / CSS and Javascript

Thumbnail
This awesome code was written by danthedev, you can see more from this user in the personal repository.
You can find the original code on Codepen.io
Copyright danthedev ©
  • HTML
  • CSS
  • JavaScript
    <label>Width:</label>
<input type="number" id="width" value="5">
<br />

<label>Height:</label>
<input type="number" id="height" value="5">
<br />

<label>Pixel Size:</label>
<input type="number" id="px" value="10">
<br />

<canvas id="canvas"></canvas>

<hr />
<span id="iterations">0</span> /
<span id="tries">0</span>

/*Downloaded from https://www.codeseek.co/danthedev/evolutionary-symmetry-oxMrwp */
    


/*Downloaded from https://www.codeseek.co/danthedev/evolutionary-symmetry-oxMrwp */
    var colors = [
  hsl(Math.random() * 360, 10, 100),
  hsl(Math.random() * 360, 10, 30),
  hsl(Math.random() * 360, 50, 40),
  hsl(Math.random() * 360, 50, 50),
  hsl(Math.random() * 360, 50, 60)
];

function hsl(h, s, l) {
  return 'hsl(' + h + ', ' + s + '%,' + l + '%)'; 
}

function fitness(pixels) {
  var width = pixels.length;
  var height = pixels[0].length;
  var fitness = 0;
  
  for(var x = 0; x < (width / 2); x++) {
    for(var y = 0; y < height; y++) {
      if(pixels[x][y] == pixels[width - 1 - x][y]) {
        fitness += 1;
      }
    }
  }

  return fitness;
}

function generate(width, height) {
  var pixels = [];
  for(var x = 0; x < width; x++) {
    pixels[x] = [];
    for(var y = 0; y < height; y++) {
      if(Math.random() > 0.4) {
        pixels[x][y] = Math.floor(Math.random() * colors.length);
      } else {
        pixels[x][y] = 0;
      }
    }
  }

  return pixels;
}

function mutate(pixels) {
  var width = pixels.length;
  var height = pixels[0].length;

  var rx = Math.floor(Math.random() * width);
  var ry = Math.floor(Math.random() * height);
  
  return pixels.map(function(row, x) {
    return row.map(function(pixel, y) {
      if(x == rx && y == ry) {
        return Math.floor(Math.random() * colors.length);
      } else {
        return pixel
      }
    });
  });
}

function render(pixels, context, px) {
  var width = pixels.length;
  var height = pixels[0].length;
  
  for(var x = 0; x < width; x++) {
    for(var y = 0; y < height; y++) {
      context.fillStyle = colors[pixels[x][y] % colors.length];
      context.fillRect(x * px, y * px, px, px);
    }
  }
}

function init() {
  var iterations = 0;
  var generations = 0;
  var width = Number(document.getElementById('width').value || 10);
  var height = Number(document.getElementById('height').value || 10);
  var px = Number(document.getElementById('px').value || 10);
  var count = document.getElementById('iterations');
  var tries = document.getElementById('tries');

  var canvas = document.getElementById('canvas');
  canvas.width = width * px;
  canvas.height = height * px;

  var c = canvas.getContext('2d');

  var pixels = generate(width, height);

  function evolve() {
    requestAnimationFrame(evolve);
    var mutation = mutate(pixels);

    var f1 = fitness(pixels);
    var f2 = fitness(mutation);
    
    var fScore = f2 / ((width * height) / 2);

    if(f2 > f1) {
      pixels = mutation;
      generations += 1;
      count.innerHTML = generations;
      tries.innerHTML = fScore + '%';
    }
    iterations += 1;
    render(pixels, c, px);
  }

  evolve();
  
}

init();

window.addEventListener('keydown', function(e) {
  if(e.which == 13) {
    init();
  }
  colors = [
    hsl(Math.random() * 360, 10, 100),
    hsl(Math.random() * 360, 10, 30),
    hsl(Math.random() * 360, 50, 40),
    hsl(Math.random() * 360, 50, 50),
    hsl(Math.random() * 360, 50, 60),
    hsl(Math.random() * 360, 50, 70)
  ];
})

Comments