Octothorp - labs

Octothorp

Octothorp screenshot

Download

Usage

There's a .bat included for easy usage, which is optimized for the cmd-window in Windows 7. Using that is simple. Just open it, press return a few times and everything should be all-right.
Exiting is possible, through typing 'quit', 'exit', 'stop', 'q' or 'qq', Ctrl+C or closing the window. The last two don't free up the memory explicity, but that shouldn't be a problem on modern systems.
Customization is easy too, though. Options are pretty straightforward and are documented in the program itself, but listing them here doesn't hurt anyone.

Source

This runs just as easily on UNIX-like systems. Even better, probably.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int grid_height;
int grid_width;

int use_reps = 0;

char * cellstates;
char * newcellstates;

int generation = 0;

char ruletab[] = {0,14,3,8,0,0,0,0,0,
                  2,8,0,6,0,0,3,11,0,
                  0,0,0,10,0,0,0,0,0,
                  0,2,0,11,0,6,0,0,0,
                  6,0,0,0,4,0,9,0,0,
                  6,0,8,0,0,11,10,0,8,
                  10,0,0,0,11,0,0,6,0,
                  0,10,0,0,0,0,5,0,0,
                  2,8,0,0,0,0,0,0,0,
                  6,0,5,14,0,0,0,1,0,
                  0,11,6,0,0,8,8,0,0,
                  8,12,0,0,0,0,0,6,5,
                  8,0,0,0,0,0,8,8,0,
                  1,0,0,2,6,0,6,0,5,
                  0,0,0,0,0,0,0,11,0,
                  0,0,0,0,0,0,0,3,9
};

char reps[] = {' ', '!', '*', '=', '+', ':', '-', 'O', '@', ')', '(', '$', ';',
               '<', '#', '>', '0'};

void printGrid() {
    int x, y;
    char cells[grid_width];
    
    printf("#%i\n---------\n", generation);
    
    for(y = 0; y < grid_height; y++) {
        for(x = 0; x < grid_width; x++) {
            cells[x] = use_reps ? reps[cellstates[y * grid_width + x]] 
                : (cellstates[y * grid_width + x] > 0 ? '#' : ' ');
        }
        printf("%s", cells);
        printf("\n");
    }
    
    printf("----------\n");
}

char getCellRaw(int x, int y) {
     return cellstates[y * grid_width + x];
}

char getCell(int x, int y) {
    if(x < 0) {
        x += grid_width;
    }
    if(x > grid_width - 1) {
        x -= grid_width;
    }
    if(y < 0) {
        y += grid_height;
    }
    if(y > grid_height - 1) {
        y -= grid_height;
    }
    return cellstates[y * grid_width + x];
}

char getNumNeighbours(int x, int y) {
    char num;
    num += ((getCell(x + 1, y + 1) & 1) == 1);
    num += ((getCell(x - 1, y + 1) & 1) == 1);
    num += ((getCell(x + 1, y - 1) & 1) == 1);
    num += ((getCell(x - 1, y - 1) & 1) == 1);
    num += ((getCell(x + 0, y + 1) & 1) == 1);
    num += ((getCell(x - 0, y - 1) & 1) == 1);
    num += ((getCell(x + 1, y + 0) & 1) == 1);
    num += ((getCell(x - 1, y - 0) & 1) == 1);
    return num;
}

void updateCells(void) {
    int x, y;
    generation++;
    for(x = 0; x < grid_width; x++) {
        for(y = 0; y < grid_height; y++) {
            newcellstates[y * grid_width + x] = 
                ruletab[getCellRaw(x, y) * 9 + getNumNeighbours(x, y)];
            printf("");
            //printf("Cell at (%i,%i) with state %i and %i neighbours becomes state %i\n", x, y, getCellRaw(x, y), getNumNeighbours(x, y), ruletab[getCellRaw(x, y) * 9 + getNumNeighbours(x, y)]);
        }
    }
    memcpy(cellstates, newcellstates, grid_height * grid_width * sizeof(char));
}

int main(int argc, char** argv) {
    char input[512];
    int x, y, i;
    int r;
    int steps_per_run;
    int skip_generations;
    
    printf("Octothorp\n");
    printf("Simulating the Expanding Crawlers rule by Randy Rucker\n");
    printf("Applying settings...\n");
    
    grid_width = 80;
    grid_height = 30;
    srand(50);
    steps_per_run = 1;
    
    for(i = 1; i < argc; i++) {
        if(strcmp(argv[i], "width") == 0) {
            grid_width = atoi(argv[++i]);
            printf("Width is now %i\n", grid_width);
        }
        if(strcmp(argv[i], "height") == 0) {
            grid_height = atoi(argv[++i]);
            printf("Height is now %i\n", grid_height);
        }
        if(strcmp(argv[i], "seed") == 0) {
            srand(atoi(argv[++i]));
            printf("Seeded with %i\n", atoi(argv[i]));
        }
        if(strcmp(argv[i], "steps") == 0) {
            steps_per_run = atoi(argv[++i]);
            printf("Taking %i step%s every time return is tapped\n",
                steps_per_run, steps_per_run == 1 ? "" : "s");
        }
        if(strcmp(argv[i], "reps") == 0) {
            use_reps = 1;
            printf(
            "Using special characters for each different state instead of #\n");
        }
        if(strcmp(argv[i], "skip") == 0) {
            skip_generations = atoi(argv[++i]);
            printf("Skipping %i generations before starting\n", skip_generations);
        }
    }
    
    cellstates = (char *)malloc(grid_height * grid_width * sizeof(char));
    newcellstates = (char *)malloc(grid_height * grid_width * sizeof(char));
    
    for(x = 0; x < grid_width; x++) {
        for(y = grid_height - 1; y >= 0; y--) {
            if((rand() % 5) == 0) {
                r = rand();
                cellstates[y * grid_width + x] = r % 16;
            }
            else {
                cellstates[y * grid_width + x] = 0;
            }
        }
    }
    
    for(i = 0; i < skip_generations; i++) {
        updateCells();
    }
    
    while(1) {
        printf(">");
        fgets(input, 512, stdin);
        if((strcmp(input, "exit\n") == 0)
          || (strcmp(input, "quit\n") == 0)
          || (strcmp(input, "q\n") == 0)
          || (strcmp(input, "qq\n") == 0)
          || (strcmp(input, "stop\n") == 0)) break;
        for(i = 0; i < steps_per_run; i++) {
            updateCells();
        }
        printGrid();
    }
    
    printf("Releasing %i bytes of memory...", 2 * grid_height * grid_width * sizeof(char));
    
    free(cellstates);
    free(newcellstates);
    return 0;
}