Traditional 2D-grid systems are probably the most famous forms of cellular automata. Pioneered by John
von Neumann
in the late 40's, cellular automata became famous in the 70's with the implementation of "Conway's Game
of Life". However, there a
multiple forms of cellular automata, some of which are not restricted to grids anymore.
The world of automata is vast and diverse. If you're interested in this family of algorithms I recommend
to you:
Langton's ant
This algorithm is a very simple form of cellular automata. A 2D grid system is made of tiles that
can be white or black. An agent is placed at a particular row and column in the grid. If the agent
lands in a white tile, the agent turns 90 deg. in a clockwise direction, changes the tile's color to
black, then moving forward. The same goes for black tiles, except the rotation is counter-clockwise.
Let's take a look at how the algorithm works
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
- 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
- CURRENT_ANT: TILE - A position in the grid, considered the ant
- DIRECTION: [int, int, int, int] - current direction of the ant as one hot vector with the order of directions: Right, Down, Left, Up
# MODULES import pygame import random import math # DATA DEFS RES = 4 DIMS = [160,160] SCREEN = (RES*DIMS[0],RES*DIMS[1]) display = pygame.display.set_mode(SCREEN) FPS = 120 # DD. TILE # tile = Tile(int, int,int) # interp. a tile to be stepped on by an ant class Tile(): def __init__(self,x,y): self.x = x * RES self.y = y * RES self.c = x self.r = y self.rect = pygame.Rect(self.x, self.y, RES, RES) self.rect.topleft = (self.x, self.y) self.state = 0 def drawSquare(self): pygame.draw.rect(display,self.getColor(),self.rect) def getColor(self): if self.state == 0: return "white" return "black" # tile = Tile(0,0) #stub # DD. TILEROW # tileRow = [TILE, ..., n=DIMS[0]] # interp. a row of tiles in the system tileRow = [] for c in range(DIMS[0]): tile = Tile(c,0) tileRow.append(tile) # --------TEMPLATE FOR TILEROW-------- # for tile in tileRow: # ... tile # DD. GRID # grid = [TILEROW, ..., n=DIMS[1]] # interp. a grid of tiles in a 2D array grid = [] for r in range(DIMS[1]): tileRow = [] for c in range(DIMS[0]): tile = Tile(c,r) tileRow.append(tile) grid.append(tileRow) # --------TEMPLATE FOR GRID ------- # for tileRow in grid: # for tile in tileRow: # ...tile # DD. CURRENTANT # ca = TILE # interp. a tile from the grid to represent a current ant ca = grid[DIMS[0]//2][DIMS[1]//2] # DD. DIRECTION # dir = [int,int,int,int] # interp. the direction of the ant as RIGHT, DOWN, LEFT, UP dir_R = [1,0,0,0] #RIGHT dir_D = [0,1,0,0] #DOWN dir_L = [0,0,1,0] #LEFT dir_U = [0,0,0,1] #UP
The Algorithm
- Is the CURRENT_ANT state 0 (white)?
- T: correct the DIRECTION to index + 1. Change the color to Black
- F: correct the DIRECTION to index - 1. Change the color to white
- Update the position of the CURRENT_ANT, following the new DIRECTION