sandpiles

sandpile art
git clone git://git.rr3.xyz/sandpiles
Log | Files | Refs | README | LICENSE

commit 38fb4a5bfce0be5fd2df2c982051794c8f62c0ea
parent 724be4a6457f653ec87761e2a436fa8a59bf48f7
Author: Robert Russell <robert@rr3.xyz>
Date:   Mon, 26 Aug 2024 03:19:11 -0700

Reorganize

Diffstat:
MMakefile | 23+++++++++++------------
Aconfig.mk | 2++
Dqueue.c | 146-------------------------------------------------------------------------------
Dsp2ff.c | 96-------------------------------------------------------------------------------
Dspgen.c | 18------------------
Rcommon.c -> src/common.c | 0
Rcommon.h -> src/common.h | 0
Rff2sp.c -> src/ff2sp.c | 0
Rsandpiles.c -> src/sandpiles.c | 0
Asrc/sp2ff.c | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/spgen.c | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rspstabilize4.c -> src/spstabilize4.c | 0
Rspstabilize8.c -> src/spstabilize8.c | 0
13 files changed, 177 insertions(+), 272 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,24 +1,23 @@ .POSIX: -CC = gcc -CFLAGS = -march=native -O3 -Wall +include config.mk all: spgen spstabilize4 spstabilize8 sp2ff ff2sp -spgen: spgen.c common.c common.h - $(CC) -o $@ $(CFLAGS) spgen.c common.c -lrcx +spgen: src/spgen.c src/common.c src/common.h + $(CC) -o $@ $(CFLAGS) src/spgen.c src/common.c -lrcx -spstabilize4: spstabilize4.c common.c common.h - $(CC) -o $@ $(CFLAGS) spstabilize4.c common.c -lrcx +spstabilize4: src/spstabilize4.c src/common.c src/common.h + $(CC) -o $@ $(CFLAGS) src/spstabilize4.c src/common.c -lrcx -spstabilize8: spstabilize8.c common.c common.h - $(CC) -o $@ $(CFLAGS) spstabilize8.c common.c -lrcx +spstabilize8: src/spstabilize8.c src/common.c src/common.h + $(CC) -o $@ $(CFLAGS) src/spstabilize8.c src/common.c -lrcx -sp2ff: sp2ff.c common.c common.h - $(CC) -o $@ $(CFLAGS) sp2ff.c common.c -lrcx +sp2ff: src/sp2ff.c src/common.c src/common.h + $(CC) -o $@ $(CFLAGS) src/sp2ff.c src/common.c -lrcx -ff2sp: ff2sp.c common.c common.h - $(CC) -o $@ $(CFLAGS) ff2sp.c common.c -lrcx +ff2sp: src/ff2sp.c src/common.c src/common.h + $(CC) -o $@ $(CFLAGS) src/ff2sp.c src/common.c -lrcx .PHONY: clean clean: diff --git a/config.mk b/config.mk @@ -0,0 +1,2 @@ +CFLAGS = -march=native -O3 -Wall +CC = cc diff --git a/queue.c b/queue.c @@ -1,146 +0,0 @@ -#include <errno.h> -#include <rcx/all.h> -#include <stdio.h> -#include <string.h> - -typedef struct pos Pos; -typedef struct rgba Rgba; -typedef struct palette Palette; -typedef struct farbfeld Farbfeld; -typedef struct sandpile Sandpile; - -struct pos { - isize x, y; -}; - -struct rgba { - u16 r, g, b, a; -}; - -struct palette { - Rgba rgba[4]; -}; - -struct farbfeld { - usize size; - void *img; -}; - -struct sandpile { - u32 w, h; - u32 s[]; -}; - -#define RIGHT (Pos){.x = +1, .y = +0} -#define UP (Pos){.x = +0, .y = +1} -#define LEFT (Pos){.x = -1, .y = +0} -#define DOWN (Pos){.x = +0, .y = -1} - -#define LIST_METHOD(name) q##name -#define LIST_T Pos -#define LIST_REALLOC r_erealloc -#include <rcx/list/static.h> - -Pos -pos_add(Pos a, Pos b) { - return (Pos){.x = a.x + b.x, .y = a.y + b.y}; -} - -u32 * -sand(Sandpile *sp, Pos p) { - usize i = (usize)p.y * (usize)sp->w + (usize)p.x; - return &sp->s[i]; -} - -void -stabilize(Sandpile *sp) { - Pos *q = 0; - Pos p; - - for (p.x = 0; p.x < sp->w; p.x++) { - for (p.y = 0; p.y < sp->h; p.y++) { - if (*sand(sp, p) >= 4) qpush(&q, p); - } - } - - while (qlen(&q) > 0) { - p = qpop(&q); - - u32 *s = sand(sp, p); - u32 a = *s / 4; - *s %= 4; - - #define TOPPLE(dir) do { \ - Pos n = pos_add(p, dir); \ - u32 *s = sand(sp, n); \ - *s += a; \ - if (*s >= 4) qpush(&q, n); \ - } while (0) - if (p.x < sp->w - 1) TOPPLE(LEFT); - if (p.y < sp->h - 1) TOPPLE(UP); - if (p.x > 0) TOPPLE(RIGHT); - if (p.y > 0) TOPPLE(DOWN); - #undef TOPPLE - } -} - -Sandpile * -new(u32 w, u32 h) { - Sandpile *sp = r_ealloc(sizeof *sp + (usize)w * (usize)h * sizeof(u32)); - sp->w = w; - sp->h = h; - return sp; -} - -Farbfeld -farbfeld(Sandpile *sp, Palette *palette) { - usize size = 8u + 4u + 4u + (usize)sp->w * (usize)sp->h * 8u; - void *img = r_ealloc(size); - u8 *cur = img; - - // Write header - memcpy(cur, "farbfeld", 8); - r_writeb32(cur + 8, sp->w); - r_writeb32(cur + 12, sp->h); - cur += 16; - - // Encode palette - u16 enc_palette[4][4]; - for (usize i = 0; i < 4; i++) { - enc_palette[i][0] = r_htob16(palette->rgba[i].r); - enc_palette[i][1] = r_htob16(palette->rgba[i].g); - enc_palette[i][2] = r_htob16(palette->rgba[i].b); - enc_palette[i][3] = r_htob16(palette->rgba[i].a); - } - - // Write pixels - Pos p; - for (p.x = 0; p.x < sp->w; p.x++) { - for (p.y = 0; p.y < sp->h; p.y++) { - u32 s = *sand(sp, p); - memcpy(cur, enc_palette[s < 4 ? s : 3], 8); - cur += 8; - } - } - - return (Farbfeld){.size = size, .img = img}; -} - -int -main(void) { - Sandpile *sp = new(101, 101); - *sand(sp, (Pos){.x = 50, .y = 50}) = 10000u; - stabilize(sp); - - Palette palette = { - .rgba = { - { 0x4a4a, 0x4242, 0x3838, 0xffff }, - { 0x4d4d, 0x5353, 0x5959, 0xffff }, - { 0x5050, 0x8484, 0x8484, 0xffff }, - { 0x7979, 0xc9c9, 0x9e9e, 0xffff }, - } - }; - Farbfeld ff = farbfeld(sp, &palette); - if (r_write_all(0, 1, ff.img, ff.size) < 0) - throw("write: %s", strerror(errno)); -} diff --git a/sp2ff.c b/sp2ff.c @@ -1,96 +0,0 @@ -#include <rcx/all.h> -#include <stdio.h> -#include <string.h> - -#include "common.h" - -#define USAGE \ - "usage: %s [COLOR0 COLOR1 COLOR2 COLOR3 [COLOR4 COLOR5 COLOR6 COLOR7]]\n" \ - "where COLORi is a 24 or 48 (32 or 64) bit RGB (RGBA) hex value\n" - -Rgba -parse_rgba(char *s) { - switch (strlen(s)) { - case 6: // 8-bit RGB - return (Rgba){ - parse_rgba_channel(s + 0, false), - parse_rgba_channel(s + 2, false), - parse_rgba_channel(s + 4, false), - 0xffff, - }; - case 8: // 8-bit RGBA - return (Rgba){ - parse_rgba_channel(s + 0, false), - parse_rgba_channel(s + 2, false), - parse_rgba_channel(s + 4, false), - parse_rgba_channel(s + 6, false), - }; - case 12: // 16-bit RGB - return (Rgba){ - parse_rgba_channel(s + 0, true), - parse_rgba_channel(s + 2, true), - parse_rgba_channel(s + 4, true), - 0xffff, - }; - case 16: // 16-bit RGBA - return (Rgba){ - parse_rgba_channel(s + 0, true), - parse_rgba_channel(s + 2, true), - parse_rgba_channel(s + 4, true), - parse_rgba_channel(s + 6, true), - }; - default: - r_fatalf("expected 6, 8, 12, or 16 hexadecimal numerals"); - } - unreachable; -} - -Image -draw(Sandpile sp, Rgba (*palette)[8]) { - usize w = sp.w; - usize h = sp.h; - - Rgba *pixels = r_ealloc(w * h * sizeof *pixels); - for (usize y = 0; y < h; y++) { - for (usize x = 0; x < w; x++) { - u32 s = sp.sand[(y + 1) * (w + 2) + (x + 1)]; - pixels[y * w + x] = (*palette)[MIN(s, 7)]; - } - } - - return (Image){.w = w, .h = h, .pixels = pixels}; -} - -int -main(int argc, char **argv) { - CHECK_FOR_HELP_OPTION(USAGE, argc, argv); - - Rgba palette[8]; - if (argc == 1) { // Default palette - #define RGB(r, g, b) (Rgba){ 0x##r##r, 0x##g##g, 0x##b##b, 0xffff } - palette[0] = RGB(BE, 80, 1D); - palette[1] = RGB(BE, 1D, A3); - palette[2] = RGB(78, 4E, 71); - palette[3] = RGB(4F, 65, 79); - palette[4] = RGB(38, A2, 18); - palette[5] = RGB(1D, 73, BE); - palette[6] = RGB(40, 6A, 33); - palette[7] = RGB(79, 69, 4F); - #undef RGB - } else if (argc == 5) { // Custom 4 color palette - for (usize i = 0; i < 4; i++) - palette[i] = parse_rgba(argv[i+1]); - for (usize i = 4; i < 8; i++) - palette[i] = palette[3]; - } else if (argc == 9) { // Custom 8 color palette - for (usize i = 0; i < 8; i++) - palette[i] = parse_rgba(argv[i+1]); - } else { - fprintf(stderr, USAGE, argv[0]); - return 1; - } - - Sandpile sp = sp_fread(stdin); - Image img = draw(sp, &palette); - ff_fwrite(stdout, img); -} diff --git a/spgen.c b/spgen.c @@ -1,18 +0,0 @@ -#include <rcx/all.h> -#include <stdio.h> - -#include "common.h" - -int -main(void) { - usize w = 101; - usize h = 101; - u32 *sand = r_eallocz((w + 2) * (h + 2) * sizeof(u32)); - Sandpile sp = { .w = w, .h = h, .sand = sand }; - - usize x = 50; - usize y = 50; - sand[(y + 1) * (w + 2) + (x + 1)] = 10000; - - sp_fwrite(stdout, sp); -} diff --git a/common.c b/src/common.c diff --git a/common.h b/src/common.h diff --git a/ff2sp.c b/src/ff2sp.c diff --git a/sandpiles.c b/src/sandpiles.c diff --git a/src/sp2ff.c b/src/sp2ff.c @@ -0,0 +1,97 @@ +#include <rcx/all.h> +#include <stdio.h> +#include <string.h> + +#include "common.h" + +#define USAGE \ + "usage: %s [COLOR0 COLOR1 COLOR2 COLOR3 [COLOR4 COLOR5 COLOR6 COLOR7]]\n" \ + "where COLORi is a 24 or 48 (32 or 64) bit RGB (RGBA) hex value\n" + +Rgba +parse_rgba(char *s) { + switch (strlen(s)) { + case 6: // 8-bit RGB + return (Rgba){ + parse_rgba_channel(s + 0, false), + parse_rgba_channel(s + 2, false), + parse_rgba_channel(s + 4, false), + 0xffff, + }; + case 8: // 8-bit RGBA + return (Rgba){ + parse_rgba_channel(s + 0, false), + parse_rgba_channel(s + 2, false), + parse_rgba_channel(s + 4, false), + parse_rgba_channel(s + 6, false), + }; + case 12: // 16-bit RGB + return (Rgba){ + parse_rgba_channel(s + 0, true), + parse_rgba_channel(s + 2, true), + parse_rgba_channel(s + 4, true), + 0xffff, + }; + case 16: // 16-bit RGBA + return (Rgba){ + parse_rgba_channel(s + 0, true), + parse_rgba_channel(s + 2, true), + parse_rgba_channel(s + 4, true), + parse_rgba_channel(s + 6, true), + }; + default: + r_fatalf("expected 6, 8, 12, or 16 hexadecimal numerals"); + } + unreachable; +} + +Image +draw(Sandpile sp, Rgba (*palette)[8]) { + usize w = sp.w; + usize h = sp.h; + + Rgba *pixels = r_ealloc(w * h * sizeof *pixels); + for (usize y = 0; y < h; y++) { + for (usize x = 0; x < w; x++) { + u32 s = sp.sand[(y + 1) * (w + 2) + (x + 1)]; + pixels[y * w + x] = (*palette)[MIN(s, 7)]; + } + } + + return (Image){.w = w, .h = h, .pixels = pixels}; +} + +int +main(int argc, char **argv) { + CHECK_FOR_HELP_OPTION(USAGE, argc, argv); + + Rgba palette[8]; + if (argc == 1) { // Default palette + #define RGB(r, g, b) (Rgba){ 0x##r##r, 0x##g##g, 0x##b##b, 0xffff } + palette[0] = RGB(D4, F1, F4); + palette[1] = RGB(75, E6, DA); + palette[2] = RGB(18, 9A, B4); + palette[3] = RGB(05, 44, 5E); + // TODO: The rest of these are scuffed + palette[4] = RGB(38, A2, 18); + palette[5] = RGB(1D, 73, BE); + palette[6] = RGB(40, 6A, 33); + palette[7] = RGB(79, 69, 4F); + #undef RGB + } else if (argc == 5) { // Custom 4 color palette + for (usize i = 0; i < 4; i++) + palette[i] = parse_rgba(argv[i+1]); + for (usize i = 4; i < 8; i++) + palette[i] = palette[3]; + } else if (argc == 9) { // Custom 8 color palette + for (usize i = 0; i < 8; i++) + palette[i] = parse_rgba(argv[i+1]); + } else { + fprintf(stderr, USAGE, argv[0]); + return 1; + } + + Sandpile sp = sp_fread(stdin); + Image img = draw(sp, &palette); + ff_fwrite(stdout, img); +} diff --git a/src/spgen.c b/src/spgen.c @@ -0,0 +1,67 @@ +#include <rcx/all.h> +#include <stdio.h> +#include <string.h> + +#include "common.h" + +/* +#define USAGE "usage: %s WIDTH HEIGHT RECTS..." + +#define SAND(x, y) sand[((y) + 1) * (w + 2) + ((x) + 1)] + +typedef struct rect Rect; + +struct rect { + u32 x, y; + u32 w, h; + u32 s; +}; + +void +parse_rect(Rect *r, char *s) { + RStr a[2]; + if (r_rstr_split(&a, s, ":", 2) != 2) // panic + + char *colon = strchr(s, ':'); + if (!colon) +} + +void +usage(char *argv0) { + fprintf(stderr, USAGE, argv0); + exit(1); +} +*/ + +int +main(int argc, char **argv) { + printf("spgen\n"); + /* + CHECK_FOR_HELP_OPTION(USAGE, argc, argv); + + if (argc < 3) usage(argv[0]); + + u32 w, h; + if (r_conv_zstr_to_u32(&w, argv[1], 0) < 0) usage(argv[0]); + if (r_conv_zstr_to_u32(&h, argv[2], 0) < 0) usage(argv[0]); + + usize nrects = argc - 3; + Rect *rects = r_eallocn(nrects, sizeof *rects); + for (usize i = 0; i < nrects; i++) { + parse_rect() + rects[i] = + } + + usize w = 32; + usize h = 32; + u32 *sand = r_eallocz((w + 2) * (h + 2) * sizeof(u32)); + Sandpile sp = { .w = w, .h = h, .sand = sand }; + + SAND(15, 15) = 420; + SAND(15, 16) = 420; + SAND(16, 15) = 420; + SAND(16, 16) = 420; + + sp_fwrite(stdout, sp); + */ +} diff --git a/spstabilize4.c b/src/spstabilize4.c diff --git a/spstabilize8.c b/src/spstabilize8.c