sandpiles

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

spgen.c (1966B)


      1 #include <rcx/all.h>
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 
      5 #include "common.h"
      6 
      7 #define USAGE \
      8 	"usage: %s WIDTH HEIGHT RECT...\n" \
      9 	"where RECT ::= X,Y:W,H:S\n"
     10 
     11 typedef struct rect Rect;
     12 
     13 struct rect {
     14 	u32 x, y;
     15 	u32 w, h;
     16 	u32 s;
     17 };
     18 
     19 void
     20 parse_rect(usize i, Rect *r, char *s) {
     21 	char **xy_wh_s = (char*[3]){};
     22 	if (r_str_split(&xy_wh_s, s, ":", 3) != 3)
     23 		r_fatalf("rectangle %zu malformed", i);
     24 
     25 	char **x_y = (char*[2]){};
     26 	if (r_str_split(&x_y, xy_wh_s[0], ",", 2) != 2)
     27 		r_fatalf("rectangle %zu malformed", i);
     28 
     29 	char **w_h = (char*[2]){};
     30 	if (r_str_split(&w_h, xy_wh_s[1], ",", 2) != 2)
     31 		r_fatalf("rectangle %zu malformed", i);
     32 
     33 	if (r_conv_zstr_to_u32(&r->x, x_y[0], 0) < 0)
     34 		r_fatalf("invalid x position in rectangle %zu", i);
     35 
     36 	if (r_conv_zstr_to_u32(&r->y, x_y[1], 0) < 0)
     37 		r_fatalf("invalid y position in rectangle %zu", i);
     38 
     39 	if (r_conv_zstr_to_u32(&r->w, w_h[0], 0) < 0)
     40 		r_fatalf("invalid width in rectangle %zu", i);
     41 
     42 	if (r_conv_zstr_to_u32(&r->h, w_h[1], 0) < 0)
     43 		r_fatalf("invalid height in rectangle %zu", i);
     44 
     45 	if (r_conv_zstr_to_u32(&r->s, xy_wh_s[2], 0) < 0)
     46 		r_fatalf("invalid sand in rectangle %zu", i);
     47 }
     48 
     49 int
     50 main(int argc, char **argv) {
     51 	CHECK_FOR_HELP_OPTION(USAGE, argc, argv);
     52 
     53 	if (argc < 3) {
     54 		fprintf(stderr, USAGE, argv[0]);
     55 		exit(1);
     56 	}
     57 
     58 	u32 w, h;
     59 	if (r_conv_zstr_to_u32(&w, argv[1], 0) < 0) r_fatalf("invalid width");
     60 	if (r_conv_zstr_to_u32(&h, argv[2], 0) < 0) r_fatalf("invalid height");
     61 
     62 	u32 *sand = r_eallocz((w + 2) * (h + 2) * sizeof(u32));
     63 	Sandpile sp = { .w = w, .h = h, .sand = sand };
     64 #define SAND(x, y) sand[((y) + 1) * (w + 2) + ((x) + 1)]
     65 
     66 	usize nrects = argc - 3;
     67 	for (usize i = 0; i < nrects; i++) {
     68 		Rect r;
     69 		parse_rect(i, &r, argv[3+i]);
     70 
     71 		usize xmin = r.x;
     72 		usize xmax = MIN(w, r.x + r.w);
     73 
     74 		usize ymin = r.y;
     75 		usize ymax = MIN(h, r.y + r.h);
     76 
     77 		for (usize y = ymin; y < ymax; y++) {
     78 			for (usize x = xmin; x < xmax; x++)
     79 				SAND(x, y) += r.s;
     80 		}
     81 	}
     82 
     83 	sp_fwrite(stdout, sp);
     84 }