Skip to content

Instantly share code, notes, and snippets.

@toke
Last active April 20, 2016 20:30
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save toke/6f52bd0a035da110c6a3 to your computer and use it in GitHub Desktop.
Save toke/6f52bd0a035da110c6a3 to your computer and use it in GitHub Desktop.
Langtons Ant Processing 3.0 Script
/**
* Langton's Ant implementation
* Written for Processing 3.0
* "Do whatever you want with it - except Weapon stuff" - License
* Original Author: Thomas 'toke' Kerpe
**/
// Yes, I do globals
int delay = 110; // Delay between updates
color border = color(127);
color border2 = color(210,190,160);
color black = color(124,95,31);
color white = color(214,200,168);
Ant ant;
Plane plane;
PlaneGrid planegrid;
int ctr; // Statistics Counter
void setup() {
size(421, 320);
ctr = 0;
// Plane is our universe aka antverse
plane = new Plane(84, 64);
// And we have a visual representation too
planegrid = new PlaneGrid(plane, 5);
// Place an lonely ant inside
ant = new Ant(35, 35, Ant.SOUTH);
planegrid.draw();
}
void draw(){
// Actually let the ant decide where to go
ant.decide(plane.getState(ant.getX(), ant.getY()));
// Before the ant will leave the cell, toggle its color
plane.toggleState(ant.getX(), ant.getY());
// Let the ant leave
ant.step();
if (! plane.isInside(ant.getX(), ant.getY())) {
println("The ant fell off the cliff");
noLoop();
}
// Update visual representation
planegrid.draw();
// Basic Steps gone
// Display Ant as red dot on grid
planegrid.fillCell(ant.getX(), ant.getY(), color(255,0,0));
// Display Statistics
displayStats(ctr++, 320, 0);
// Display Radar "sensation"
planegrid.radar(ant.getX(),ant.getY(),5,370,70);
stroke(255,0,0);
fill(200,0,0);
print(ant.getHeading());
delay(delay);
}
void displayStats(int ctr, int x, int y) {
assert(x <= width - 100 && x >= 0);
assert(y <= height - 20 && y >= 0);
pushMatrix();
translate(x,y);
fill(255);
stroke(black);
rect(0,0,100,20);
textSize(12);
fill(0);
text("n = " + ctr, 10,15);
popMatrix();
}
class Plane {
boolean[][] space; // Antverse
public final int dimX, dimY;
public final static boolean BLACK = true;
public final static boolean WHITE = false;
Plane(int x, int y) {
dimX = x;
dimY = y;
space = new boolean[x][y];
// Initialize plane
for (int i=0; i < x; i++) {
for (int j=0; j < y; j++) {
space[i][j] = WHITE;
}
}
}
boolean getState(int x, int y) {
assert(x <= dimX && x >= 0);
assert(y <= dimY && y >= 0);
return space[x][y];
}
boolean setState(int x, int y, boolean newstate) {
assert(x <= dimX && x >= 0);
assert(y <= dimY && y >= 0);
boolean state = getState(x,y);
space[x][y] = newstate;
return state;
}
void toggleState(int x, int y) {
assert(x <= dimX && x >= 0);
assert(y <= dimY && y >= 0);
space[x][y] = ! space[x][y];
}
boolean isInside(int x, int y) {
if ((x >= 0 && x < dimX) && (y >= 0 && y < dimY)) {
return true;
} else {
return false;
}
}
}
class PlaneGrid {
private final Plane plane;
private final int spacing; // Actual grid size
PlaneGrid(Plane p, int size){
plane = p;
spacing = size;
assert(p.dimX * size <= width);
assert(p.dimY * size <= height);
}
void fillCell(int x, int y, color c) {
fill(c);
rect(x * spacing, y * spacing, spacing, spacing);
}
void draw(){
for (int i=0; i < plane.dimX ; i++) {
for (int j=0; j < plane.dimY ; j++) {
stroke(border2);
fillCell(i, j, plane.getState(i,j)?black:white);
}
}
}
void radar(int focusX, int focusY, int context, int posX, int posY){
int deltaX, deltaY;
int size = 10;
pushMatrix();
translate(posX, posY);
deltaX = focusX + 1;
deltaX = constrain(deltaX, context, plane.dimX - context);
deltaY = focusY + 1;
deltaY = constrain(deltaY, context, plane.dimY - context);
// Difference of focus center because of border
int centerX = focusX - deltaX;
int centerY = focusY - deltaY;
// Draw the "radar" box
for (int i=0-context; i < context ; i++) {
for (int j=0-context; j < context ; j++) {
int newX = deltaX + i;
int newY = deltaY + j;
fill(plane.getState(newX, newY)?black:white);
rect(i * size, j * size, size, size);
}
}
noFill();
stroke(0,0,0);
rect(centerX * size, centerY * size, 10, 10);
popMatrix();
}
}
/**
* Ant
* Holds state of current position and allows
* movement (turnLeft, turnRight, step)
* heading 0 = North, 1 = East, 2 = South, 3 = West
**/
class Ant {
private int xPos, yPos;
private int heading;
public final static int NORTH = 0;
public final static int EAST = 1;
public final static int SOUTH = 2;
public final static int WEST = 3;
Ant(int x, int y, int direction) {
xPos = x;
yPos = y;
assert(direction < 4);
assert(direction >= 0);
heading = direction;
}
// Turn the ant 90°
void turnRight() {
heading = turn(1);
}
// Turn the ant -90°
void turnLeft() {
heading = turn(-1);
}
// This is the crucial part, the decision
void decide(boolean col) {
if (col == Plane.BLACK) {
turnLeft();
} else {
turnRight();
}
}
void step(){
// Transform heading to Grid direction
int[][] dir = {{0, -1}, {1, 0}, {0, 1}, {-1, 0}};
xPos += dir[heading][0];
yPos += dir[heading][1];
}
int getX(){
return xPos;
}
int getY(){
return yPos;
}
int getHeading(){
return heading;
}
private int turn(int dir) {
heading = heading + dir;
// Normalize heading from 0-3°
heading = heading - ((heading / 4) * 4);
while (heading < 0) {
heading += 4;
}
// Retrun new heading (0..3)
return heading;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment