/* NAME * vants - simulate a population of generalized virtual ants * NOTES * None. * MISCELLANY * It is definitely worthwhile to simulate multiple vants as * the possible composite behavior of multiple vants is far * different than a single vant. In fact, multiple vants can * invert the work of other vants, which yields interesting * deconstructive behavior. * BUGS * No sanity checks are performed to make sure that any of the * options make sense. * AUTHOR * Copyright (c) 1997, Gary William Flake. * * Permission granted for any use according to the standard GNU * ``copyleft'' agreement provided that the author's comments are * neither modified nor removed. No warranty is given or implied. */ #include #include #include #include "misc.h" int width = 200, height = 200, num = 1, seed = 0, invert = 0; int states = 2, steps = 100000000, mag = 1; double dense = 0.0; char *term = NULL, *rule = "10"; char help_string[] = "\ Simulate and plot a population of virtual ants (vants). The behavior \ of the vants is determined by a bit string with length equal to the \ number of states that each cell in the vants' grid world can take. If \ a vant walks on a cell in state S, then the vant turns right if the \ S'th bit of the rule string is 1 and left if it's 0. As it leaves the \ cell the vant changes the state of the old cell to \ (S + 1) % NUMSTATES.\ "; OPTION options[] = { { "-width", OPT_INT, &width, "Width of the plot in pixels." }, { "-height", OPT_INT, &height, "Height of the plot in pixels." }, { "-num", OPT_INT, &num, "Number of ants." }, { "-rule", OPT_STRING, &rule, "Rule string." }, { "-dense", OPT_DOUBLE, &dense, "Density of random crud." }, { "-steps", OPT_INT, &steps, "Number of simulated steps." }, { "-seed", OPT_INT, &seed, "Random seed for initial state." }, { "-inv", OPT_SWITCH, &invert, "Invert all colors?" }, { "-mag", OPT_INT, &mag, "Magnification factor." }, { "-term", OPT_STRING, &term, "How to plot points." }, { NULL, OPT_NULL, NULL, NULL } }; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ int main(int argc, char **argv) { extern int plot_mag; extern int plot_inverse; int i, j, *vx, *vy, *vd, nx, ny, old; char **grid; get_options(argc, argv, options, help_string); states = strlen(rule); plot_mag = mag; plot_inverse = invert; plot_init(width, height, states, term); plot_set_all(0); srandom(seed); /* Allocate space for the vants (x, y) position and direction, and * initialize to sane values. */ vx = xmalloc(sizeof(int) * num); vy = xmalloc(sizeof(int) * num); vd = xmalloc(sizeof(int) * num); for(i = 0; i < num; i++) { vx[i] = random_range(0, width); vy[i] = random_range(0, height); vd[i] = random_range(0, 4); } /* Make our grid world and optionally fill with some crud. */ grid = xmalloc(sizeof(char *) * width); for(i = 0; i < width; i++) { grid[i] = xmalloc(sizeof(char) * height); for(j = 0; j < height; j++) { if(dense > 0) grid[i][j] = (random_range(0.0, 1.0) < dense) ? random() % states : 0; else grid[i][j] = 0; plot_point(i, j, grid[i][j]); } } /* For each time step... */ for(i = 0; i < steps; i++) { /* For each vant... */ for(j = 0; j < num; j++) { /* Get the current position. */ nx = vx[j]; ny = vy[j]; /* Walk in the proper direction. */ if(vd[j] == 0) ny++; else if(vd[j] == 1) nx++; else if(vd[j] == 2) ny--; else nx--; /* Wrap around coordinates if necessary. */ nx = (nx < 0) ? width - 1 : (nx > width - 1) ? 0 : nx; ny = (ny < 0) ? height - 1 : (ny > height - 1) ? 0 : ny; /* Change the state of the grid to reflect the vants * new position. */ old = grid[nx][ny]; grid[nx][ny] = (grid[nx][ny] + 1) % states; plot_point(nx, ny, grid[nx][ny]); /* Updates th vant's position and change it's direction * according to the rule string. */ vx[j] = nx; vy[j] = ny; vd[j] += (rule[old] - '0') ? 4 + 1 : 4 - 1; vd[j] %= 4; } } plot_finish(); exit(0); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */