Automata in nature
Simple automata can be found in the least expected places. At the beginning
of the 1950's, Alan Turing started working on
mathematical models that could explain how antagonistic chemical reactions could help explain the
patterns
and shapes observed in the skin pigmentation of some animals and plants. This was later called the
reaction-diffusion algorithm.
But some examples of cellular automata are less discrete. We will try to
implement the waving behavior
observed in wild colonies of bees. This behavior is relatively common in social arthropods, and it's
intended as a deterrent for predators that may get scared when looking at a colony as a single, bigger,
and more aggressive
organism.
The basic unit of information in the bee-wave system is a bee. A bee can have
its wings open or closed,
and can be receptive to the stimulus of its neighbors, or not. A bee that is receptive, and doesn't have
its wings open reacts to any of the neighbors in its vicinity that may have raised their wings by
doing it too, propagating the behavior throughout the colony. After reacting, the bee takes a couple of
seconds to rest, preventing it to backpropagate the signal and enter an infinite loop.
The parameters of the Algorithm
- RES: int - tile size
- DIMS: (int,int) - Number of columns and rows of tiles that make the grid
- SCREEN: (int,int) - Dimensions of the screen in pixels
- FPS: int - Frames per second of animation
- TIME_BEE_REST: float - amount of time the bee will remain in state 0 before being able to change state
- TIME_BEE_ACTIVE: float - amount of time the bee will remain in state 1
- TILE: Tile() - Class Tile that represent the basic unit of information in the system
- GRID: [[TILE, ..., n=DIMS[0]], ..., n = DIMS[1]] - a 2D matrix of TILE with dimensions given by the columns and rows of DIMS
# MODULE import pygame import random # DD DIMS = (32,32) RES = 16 SCREEN = (DIMS[0]*RES, DIMS[1]*RES) display = pygame.display.set_mode(SCREEN) FPS = 10 TIME_BEE_REST = 1 TIME_BEE_ACTIVE = 0.1 # DD. TILE # tile = Tile() # interp. a tile in the grid class Tile: def __init__(self,c,r): self.c = c self.r = r self.x = self.c * RES self.y = self.r * RES self.state = 0 self.nextState = 0 # attr. related to waiting periods of activity self.timerInState1 = 0 #Time the bee stays in a state 1 self.resetTimerInState1 = TIME_BEE_ACTIVE self.recoilTimer = 0 #Time the bee rests before activating it again self.resetrecoilTimer = TIME_BEE_REST # attr. related to pixel rendering and collision detection self.rect = pygame.Rect(self.x, self.y, RES, RES) def draw(self): pygame.draw.rect(display,self.getColor(),self.rect) def getColor(self): if self.state == 0: return ("white") return "black" # DD. GRID # grid = [[TILE, ..., n=DIMS[0]], ..., n=DIMS[1]] # interp. a 2D array of tiles arranged in a grid grid = [] for r in range(DIMS[1]): row = [] for c in range(DIMS[0]): tile = Tile(c,r) row.append(tile) grid.append(row) # TEMPLATE FOR GRID # for row in grid: # for tile in row: # ... tile
The Algorithm
- For every tile in the system:
- If the tile has state 0
- T: Does the tile have any neighbors with state 1? Is the tile ready to change to state 1?
- make the NEXT state 1
- F: reduce the timer resting timer and make it closer to 0
- else: tile has state 1
- Is it time for the state 1 to end?
- T: make the NEXT state 0 and reset all timers to TIME_BEE_ACTIVE and TIME_BEE_REST, respectively
- F: reduce the time the tile has left being active, with state 1
- For every tile in the system:
- Make NEXT state the CURRENT state