06Apr
Grid, gradient and one cell organism
Grid, gradient and one cell organism

Infusoria slipper

The topic of artificial intelligence is very popular right now. I am not familiar with neural networks and the like, but I do have experience programming in JavaScript, so I will use that, even though it may not be the best choice for machine learning. I set a research goal for myself: to understand the most optimal decision-making algorithms at each level of task-setting, and to move from simpler solutions to more and more complex ones as the external environment becomes more complicated.

For the starting point, I decided to take the behavior of the Infusoria slipper. If there is light, it moves towards the light; if there is no light, it stays still. With such behavior, the main task will be very simple: find the shortest path to the center of the light source.

Environmental conditions

A field of cells, like a chessboard, through which the light and the organism will move. There is one light source with a configurable gradient radius and center coordinates.

Single-celled organism

As long as the gradient does not reach the organism, it does not see it. When it does, the organism begins to move towards its center. The time interval is 0.5 seconds.

Implementation

Repository: https://github.com/brnikita/Cellular-Automata/tree/Step1.-Infusoria-slipper

I will only describe the main ideas; the full code can be found at the link above.

Gradient (source of excitation)

scripts/gradient.js

applyGradient(index) {
    const cells = this.container.children;

    for (let i = 0; i < this.cellsNumber; i++) {
      const xDistance = (index % this.numberOfColumns) - (i % this.numberOfColumns);
      const yDistance = Math.floor(index / this.numberOfColumns) - Math.floor(i / this.numberOfColumns);
      const distance = Math.sqrt(Math.pow(xDistance, 2) + Math.pow(yDistance, 2));

      const intensity = Math.max(0, this.selectedIntensity - distance);
      const bgColor = `rgba(${hexToRgb(this.selectedColor)}, ${intensity / 9})`;
      cells[i].style.backgroundColor = bgColor;
      createIntensityMap(i, intensity, this.numberOfColumns, this.intensityMap);
    }
  }
Field's cells are arranged in a row like a long snake
Field’s cells are arranged in a row like a long snake

In my implementation, the field cells are arranged in a row in order and are moved to a new line due to styles, like a long snake. Therefore, to calculate the gradient coordinates, we need to consider the length of one line. I store the gradient of each field cell in an array called createIntensityMap, and when drawing the field, I take the data for the color of each cell from it.

Cell’s brain

scripts/oneCellorganism.js

brain(thisX, thisY) {
    let newX = thisX;
    let newY = thisY;
    let newXY = {};
    let maxIntensity = 0;

    const neighbors = [
      [-1, -1], [-1, 0], [-1, 1],
      [0, -1], [0, 0], [0, 1],
      [1, -1], [1, 0], [1, 1],
    ];

    for (const [dx, dy] of neighbors) {
      const x = thisX + dx;
      const y = thisY + dy;

      if (x < 0 || x >= this.numberOfColumns || y < 0 || y >= Math.floor(this.cellsNumber / this.numberOfColumns)) {
        //checking field's borders
        continue;
      }

    const intensity = this.intensityMap[y][x];

    if (intensity > maxIntensity) {
      maxIntensity = intensity;
      newX = x;
      newY = y;
    }
  }

  newXY.x= newX;
  newXY.y= newY;
  return newXY;
}

I put the decision-making algorithm for the cell in a separate function. The logic is as follows: the cell collects gradient data around it, in a loop, selects the cell with the highest gradient, and moves to it.

How to play

Download the project at https://github.com/brnikita/Cellular-Automata/tree/Step1.-Infusoria-slipper

Open the index.html file in a browser. Enjoy the game!

Leave a Reply