miriam_e: from my drawing MoonGirl (Default)
[personal profile] miriam_e
A little bit of a delay in releasing the canvas server. I wanted to include an example of using it for running John Conway's Game of Life. That meant adding a few more functions and getting shared memory access working properly. That all works properly, and the Game of Life works really well. On a 500x500 pixel canvas it runs about 30 generations per second. Not bad! (This is not awk. It's a short C program that uses the canvas server for display.)

There are a couple more things I need to make demos for, and then I'll finish the documentation and release it. I know I keep saying I'll release it and then put it off, but I want it to be as useful as possible.

Here's just a few seconds of it, to give you an idea of how fast it runs, and below that, the C program.

I've uploaded it to YouTube:
https://youtube.com/shorts/mbF7khhrmIQ?feature=share

Here is the C code I used:
// gol.c - Game of Life using shared memory
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include "pixel_protocol.h"

int main(int argc, char **argv) {
    int w = argc > 1 ? atoi(argv[1]) : 80;
    int h = argc > 2 ? atoi(argv[2]) : 60;
    int generations = argc > 3 ? atoi(argv[3]) : 100;
    
    // Open shared memory
    int fd = shm_open(PIXEL_SHM_NAME, O_RDWR, 0666);
    if (fd < 0) {
        perror("shm_open - is canvas_server running?");
        return 1;
    }
    
    size_t size = sizeof(shm_canvas_t) + w * h * 4;
    shm_canvas_t *shm = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    if (shm == MAP_FAILED) {
        perror("mmap");
        close(fd);
        return 1;
    }
        
    // Verify dimensions match
    if (shm->width != w || shm->height != h) {
        fprintf(stderr, "Error: canvas size is %dx%d, expected %dx%d\n", 
                shm->width, shm->height, w, h);
        munmap(shm, size);
        close(fd);
        return 1;
    }
    
    uint8_t *grid = malloc(w * h);
    uint8_t *next = malloc(w * h);
    if (!grid || !next) {
        perror("malloc");
        return 1;
    }
    
    // Random initialization
    srand(time(NULL));
    for (int i = 0; i < w * h; i++) {
        grid[i] = rand() > RAND_MAX * 0.25;
        ((uint32_t*)shm->pixels)[i] = grid[i] ? 0xFFFFFFFF : 0xFF000000;
    }
    shm->seq++;
    printf("Generation 0: random init\n");
    
    // Evolve
    for (int gen = 1; gen <= generations; gen++) {
        // Compute next generation
        for (int y = 0; y < h; y++) {
            for (int x = 0; x < w; x++) {
                int neighbors = 0;
                for (int dy = -1; dy <= 1; dy++) {
                    for (int dx = -1; dx <= 1; dx++) {
                        if (dx == 0 && dy == 0) continue;
                        int nx = (x + dx + w) % w;
                        int ny = (y + dy + h) % h;
                        neighbors += grid[ny * w + nx];
                    }
                }
                
                int alive = grid[y * w + x];
                next[y * w + x] = (alive && neighbors >= 2 && neighbors <= 3) ||
                                  (!alive && neighbors == 3);
            }
        }
        
        // Update display
        int changed = 0;
        for (int i = 0; i < w * h; i++) {
            if (grid[i] != next[i]) {
                grid[i] = next[i];
                ((uint32_t*)shm->pixels)[i] = grid[i] ? 0xFFFFFFFF : 0xFF000000;
                changed = 1;
            }
        }
        
        if (changed) {
            shm->seq++;
            printf("Gen: %d \r", gen);
			fflush(stdout);
        } else {
            printf("Generation %d: stable\n", gen);
            break;  // Stop if no changes
        }
        
        //usleep(50000);  // 50ms per generation
    }
    
    munmap(shm, size);
    close(fd);
    free(grid);
    free(next);
    return 0;
}

Profile

miriam_e: from my drawing MoonGirl (Default)
miriam_e

March 2026

S M T W T F S
12 34567
89 1011 121314
15161718192021
22 232425 262728
29 3031    

Style Credit

Expand Cut Tags

No cut tags
Page generated Monday, 30 March 2026 11:00 pm
Powered by Dreamwidth Studios