/* Processing source for displaying evolved ants navigating through their mazes */ // representation of the world int[][][] world; int dx, dy; int finish_x, finish_y; int[] pathx; int[] pathy; int w, h; // view-port configuration int window_width = 800; int window_height = 600; int border = 25; int ant_frame_delay = 2; // no of frames to skip when moving the ant int framecounter = 0; // ant path variables boolean maze_complete = false; boolean ant_finished = false; int ant_step = 0; int ant_x = 0; int ant_y = 0; // data paths String mazeDir = "/Users/richard/snapr-workspace/dev8d/am/data/mazes"; String antDir = "/Users/richard/snapr-workspace/dev8d/am/data/ants"; // history of what's been displayed so far long lastAnt = 0; ArrayList oldAnts = new ArrayList(); // metadata holding variables String antName = ""; String nextMaze = ""; String credits = ""; String antDna = ""; void setup() { size(window_width, window_height); frameRate(25); colorMode(RGB, 255); // load base grid load_next_path(); load_maze(); // set up the fonts PFont font = createFont("Monospaced", 10); textFont(font); } void draw() { drawcycle(); framecounter++; if (framecounter == ant_frame_delay) { // print(ant_x + " " + ant_y + "\n"); fade_old(); world[ant_x][invert_y(ant_y)][1] = 8; move_ant(); framecounter = 0; } if (maze_complete || ant_finished) { load_next_path(); load_maze(); } } File[] listFiles(String dir) { File file = new File(dir); if (file.isDirectory()) { File[] files = file.listFiles(); return files; } else { // If it's not a directory return null; } } File nextAnt() { File next = null; File[] files = listFiles(antDir); for (int i = 0; i < files.length; i++) { long lm = files[i].lastModified(); // is it eligible for display? if (!contains(oldAnts, files[i].getName())) { // if so, is it sufficiently new and sufficiently old? if (next == null && lm >= lastAnt) { next = files[i]; } else if (next != null && lm >= lastAnt && lm <= next.lastModified()) { next = files[i]; } } } return next; } boolean contains(ArrayList arr, String value) { for (int i = 0; i < arr.size(); i++) { // print(arr.get(i) + " = " + value); if (arr.get(i).equals(value)) { return true; } } return false; } void print_world() { for (int x = 0; x < w; x++) { for (int y = 0; y < h; y++) { print(world[x][y][1]); } print("\n"); } print("\n\n"); } void load_maze() { w = 0; h = 0; int sx = 0; int sy = 0; int ex = 0; int ey = 0; // print ("maze: " + nextMaze + "\n"); String lines[] = loadStrings(mazeDir + "/" + nextMaze); for (int y = -1; y < lines.length - 1; y++) { if (y == -1) { String[] starts = split(lines[0], ' '); sx = int(starts[0]); sy = int(starts[1]); ex = int(starts[2]); ey = int(starts[3]); h = lines.length - 1; finish_x = ex; finish_y = invert_y(ey); } else { String[] bits = split(lines[y + 1], " "); if (y == 0) { w = bits.length - 1; // strip the newline dx = (width - (border * 2))/w; dy = (height - (border * 2))/h; world = new int[w][h][2]; // x, y and layer - 0 = background and 1 = foreground } for (int x = 0; x < w; x++) { if (int(bits[x]) == 0) { world[x][y][0] = 0; // open space world[x][y][1] = 0; } else { world[x][y][0] = 1; // wall world[x][y][1] = 1; } } } } // now set the start and finish points int start_y = invert_y(sy); int end_y = invert_y(ey); world[sx][start_y][0] = 2; // start world[sx][start_y][1] = 2; world[ex][end_y][0] = 3; // finish world[ex][end_y][1] = 3; } int invert_y(int original_y) { int new_y = h - original_y; if (new_y < 0) { new_y *= -1; } return new_y - 1; } void load_next_path() { maze_complete = false; ant_finished = false; ant_step = 0; File next = nextAnt(); if (next != null) { antName = next.getName(); oldAnts.add(antName); } // if there's no more ants, start again else { lastAnt = 0; oldAnts = new ArrayList(); next = nextAnt(); } // print ("ant: " + antName + " | "); String lines[] = loadStrings(next.getPath()); pathx = new int[lines.length - 3]; pathy = new int[lines.length - 3]; nextMaze = lines[0]; antDna = lines[1]; credits = lines[2]; for (int i = 3; i < lines.length; i++) { String[] coords = split(lines[i], ' '); // print(coords[0] + coords[1]); pathx[i - 3] = int(coords[0]); pathy[i - 3] = int(coords[1]); } ant_x = pathx[0]; ant_y = pathy[0]; } void drawcycle() { background(0); for (int x = 0; x != w; x++) { for (int y = 0; y != h; y++) { if (world[x][y][1] > 3) // if the world is displaying an ant in the foreground { fill(ant_colour(world[x][y][1])); } else if (world[x][y][0] == 3) // the end { fill(color(255, 0, 0)); } else if (world[x][y][0] == 2) // the start { fill(color(0, 255, 0)); } else if (world[x][y][0] == 1) // a wall { fill(255); } else if (world[x][y][0] == 0) // background { fill(0); } rect(x*dx + border, y*dy + border, dx, dy); } } // add the ant's name to the screen fill(255); text(credits, 15, 5, 700, 20); text(antName + ": " + antDna, 15, 580, 700, 695); } color ant_colour(int stage) { switch(stage) { case 4: return color(30, 30, 60); case 5: return color(60, 60, 105); case 6: return color(90, 90, 150); case 7: return color(120, 120, 195); case 8: return color(150, 150, 240); } return color(0, 0, 0); } void fade_old() { for (int x = 0 ; x != w; x++) { for (int y = 0; y != h; y++) { if (world[x][y][1] > 3) // is there an ant in the foreground? { if (world[x][y][1] == 4) // if it is the most faded allowed { // set it back to the background world[x][y][1] = world[x][y][0]; } else { // reduce the path by one level world[x][y][1] = world[x][y][1] - 1; } } } } } void move_ant() { ant_step++; if (ant_step > pathx.length - 1) { ant_finished = true; } else { ant_x = pathx[ant_step]; ant_y = pathy[ant_step]; } if (ant_x == finish_x && ant_y == finish_y) { maze_complete = true; } }