mid-kid
6 years ago
6 changed files with 307 additions and 0 deletions
@ -0,0 +1,12 @@ |
|||||
|
CFLAGS := -O3 -Wall -Wextra -std=c17 -D_GNU_SOURCE |
||||
|
|
||||
|
.PHONY: all |
||||
|
all: main out/ |
||||
|
|
||||
|
.PHONY: clean |
||||
|
clean: |
||||
|
rm -f main out/* |
||||
|
|
||||
|
out/: |
||||
|
mkdir -p $@ |
||||
|
touch $@/.gitkeep |
@ -0,0 +1,50 @@ |
|||||
|
........#.##..#|#|.#.....|......#..#.|..##..||.#.. |
||||
|
#|##.|||.|..|||......|.##.#|#|....||#.#...#...#..# |
||||
|
..##...#|#..|#.|..#||#...|#....|#...#|#.|.||...|.. |
||||
|
.....#|||.|.#...###|....|#..#.#.#.|..#||#|....|#.| |
||||
|
....|.....#.||.#..#...#|....|||..#....##...|..|.#| |
||||
|
||...|###..|..|||..|#.##|.####.#...|.||.|....|.##. |
||||
|
..#.#.###..||......#|#|.|....#|.#|.|...#....#...#| |
||||
|
.|..||||||...#.##..|.#||.#|##|..#.#..##..#...|#... |
||||
|
.|.....||...#.#|.##|..|.##||..#.#..|..#.#.#..|.#|. |
||||
|
||...|#........#.|..##|.|..#...#...#|#|..||.|....# |
||||
|
#||.|.|..|.......##....|..#||#.#|.|||......|..||.. |
||||
|
.....#.|||.....|.#.#.......#.|..#.|.....|.|.#...#. |
||||
|
...#.##.#.||#.#|.#.##..#.||#.#.#|#.||.||.|......#. |
||||
|
|.|...#|.|####|.|..#.#|....|......|....|...||#||.. |
||||
|
.#...#.#......|...#.....|.....|.#|...##|||...#.|#. |
||||
|
||##.#...#.|...##..##.||#...#|...|##.##...#||..#|. |
||||
|
|.|#.||..|##.|.#.|..#..|.##.#.......#...|....||... |
||||
|
.|.......#..##...|.|..|#.#....|#|..##|#|.##|.|.|#. |
||||
|
.|....|.#|||#.#..#..|||.....||...#|.#..|..#.#...#. |
||||
|
...#..###.#|.##||.#.|.||###..|..|#.|#..||......||. |
||||
|
..##.......##|.....#...|#|..##|.#.|||.|#....|##... |
||||
|
#...#|##|......##|...|#..#.|..##..#..#.|##.##|#..# |
||||
|
|.#|.....|..#...|....|...#....#|..#.....||...|#|.| |
||||
|
##...#.....#.....|#|.......|....####.#..##.|.##... |
||||
|
.....|...|#|#..|#|.|..##.|..|....##..||.#...|..|.| |
||||
|
.|..|....##.||||.##|.#...|..|#|.#.|####.|..|##.#.. |
||||
|
#.........|##.#|..##|...|........|..|....|..#...## |
||||
|
.#.|...#...#...|.|...|..|.#.|....#..|.|..|..#|.... |
||||
|
.....#.....#|.#....|....##...##....###....#.|...|. |
||||
|
||.....|.|.##|.##||.#|#.##|.#..|#####|...|...||#.# |
||||
|
...#||....#.....##.|##|.##|#.##.#|.|.....#........ |
||||
|
..##.....||..#..#.|..##...#.|.|.|.|...|.#.|..|.... |
||||
|
|##..|..........##..#|...|......||.#....#....|..#. |
||||
|
...#..|.#.|...|.##|.##..##..|.|....#||#|##..||||.. |
||||
|
#...##......|..|#...#.#.|#||..#...|.#...|..###.||. |
||||
|
|#.......|#.|##|....|.....#..||.|#|#...#|....|..#| |
||||
|
.|.....#|##.|.#...#..#||#.....|....#||.#|.##.##.#| |
||||
|
|#..###..#..|#.....##...||.|.|.#.#|.||..||.||#|#.. |
||||
|
||||#....|#..|.|...|...||....|...#....#.##...#|... |
||||
|
...||##||#......|#.#..#..|.....|...#..#|...#...||| |
||||
|
.|#.|.|....|...#.....|#....|..#.#...#...||..##|..| |
||||
|
||#.|##.|...|.##......##|#..#..#.#.#.....|#|##.##. |
||||
|
|.#.....||.....#.#...|...|..|#|..|..#...|....|...| |
||||
|
###..#.#......#|..#....#......|##.##....|||.|..#|. |
||||
|
..#.|.#...#..|#####|.....##.|.|#......|..||.#|.... |
||||
|
.#||.|.##..#.|..##......|..|.|#..|.....#.....|#|.. |
||||
|
|##.#......#.#.#.#|||#|....#...#.|.........|||.#.. |
||||
|
|......||.|..#.|#||...||.#.#.##..#..#.#....#.#..#| |
||||
|
#.|..##.....#..|...|#...#...|.......|.|..|#|...... |
||||
|
##...#....#..#..#....|...#|#.||.|...|.#..###|##|.| |
@ -0,0 +1,243 @@ |
|||||
|
#include <stdlib.h> |
||||
|
#include <stdio.h> |
||||
|
#include <string.h> |
||||
|
#include <stdint.h> |
||||
|
#include <time.h> |
||||
|
|
||||
|
struct size2d { |
||||
|
unsigned w; |
||||
|
unsigned h; |
||||
|
}; |
||||
|
|
||||
|
struct buffer { |
||||
|
char *data; |
||||
|
size_t len; |
||||
|
size_t alloc; |
||||
|
}; |
||||
|
|
||||
|
void *xrealloc(void *ptr, size_t size) |
||||
|
{ |
||||
|
void *res = realloc(ptr, size); |
||||
|
if (!res) { |
||||
|
perror("realloc"); |
||||
|
exit(1); |
||||
|
} |
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
struct buffer buffer_alloc() |
||||
|
{ |
||||
|
struct buffer buffer; |
||||
|
buffer.len = 0; |
||||
|
buffer.alloc = 0x10; |
||||
|
buffer.data = xrealloc(NULL, buffer.alloc); |
||||
|
return buffer; |
||||
|
} |
||||
|
|
||||
|
void buffer_append(struct buffer *buffer, char c) |
||||
|
{ |
||||
|
if (buffer->alloc <= buffer->len) { |
||||
|
buffer->alloc *= 2; |
||||
|
buffer->data = xrealloc(buffer->data, buffer->alloc); |
||||
|
} |
||||
|
buffer->data[buffer->len++] = c; |
||||
|
} |
||||
|
|
||||
|
char *parse_acres(const char *fname, struct size2d *size) |
||||
|
{ |
||||
|
FILE *f = fopen(fname, "r"); |
||||
|
if (!f) { |
||||
|
perror(fname); |
||||
|
return NULL; |
||||
|
} |
||||
|
|
||||
|
struct buffer buffer = buffer_alloc(); |
||||
|
size->w = 0; |
||||
|
size->h = 0; |
||||
|
|
||||
|
unsigned width = 0; |
||||
|
int c; |
||||
|
|
||||
|
flockfile(f); |
||||
|
while ((c = getc_unlocked(f)) != EOF) { |
||||
|
if (c == '\n') { |
||||
|
if (!size->w) { |
||||
|
size->w = width; |
||||
|
} else { |
||||
|
if (size->w != width) { |
||||
|
fprintf(stderr, "ERROR: Not each line has the same width\n"); |
||||
|
goto error; |
||||
|
} |
||||
|
} |
||||
|
width = 0; |
||||
|
size->h++; |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
if (c != '.' && c != '|' && c != '#') { |
||||
|
fprintf(stderr, "ERROR: Unknown character: '%c'\n", c); |
||||
|
goto error; |
||||
|
} |
||||
|
|
||||
|
buffer_append(&buffer, c); |
||||
|
width++; |
||||
|
} |
||||
|
funlockfile(f); |
||||
|
fclose(f); |
||||
|
|
||||
|
return realloc(buffer.data, buffer.len); |
||||
|
|
||||
|
error: |
||||
|
funlockfile(f); |
||||
|
fclose(f); |
||||
|
free(buffer.data); |
||||
|
return NULL; |
||||
|
} |
||||
|
|
||||
|
void advance_frame(char *acres, char *next, const struct size2d size) |
||||
|
{ |
||||
|
for (unsigned y = 0; y < size.h; y++) { |
||||
|
for (unsigned x = 0; x < size.w; x++) { |
||||
|
char *a = next + y * size.w + x; |
||||
|
|
||||
|
char surrounding[8] = {'\0'}; |
||||
|
if (y > 0) surrounding[0] = acres[(y - 1) * size.w + x]; |
||||
|
if (x > 0) surrounding[1] = acres[y * size.w + (x - 1)]; |
||||
|
if (y + 1 < size.h) surrounding[2] = acres[(y + 1) * size.w + x]; |
||||
|
if (x + 1 < size.w) surrounding[3] = acres[y * size.w + (x + 1)]; |
||||
|
if (y > 0 && x + 1 < size.w) |
||||
|
surrounding[4] = acres[(y - 1) * size.w + (x + 1)]; |
||||
|
if (y > 0 && x > 0) |
||||
|
surrounding[5] = acres[(y - 1) * size.w + (x - 1)]; |
||||
|
if (y + 1 < size.h && x > 0) |
||||
|
surrounding[6] = acres[(y + 1) * size.w + (x - 1)]; |
||||
|
if (y + 1 < size.h && x + 1 < size.w) |
||||
|
surrounding[7] = acres[(y + 1) * size.w + (x + 1)]; |
||||
|
|
||||
|
unsigned tally = 0; |
||||
|
unsigned tally2 = 0; |
||||
|
char new = 0; |
||||
|
|
||||
|
switch (*a) { |
||||
|
case '.': |
||||
|
case '|': |
||||
|
new = (*a == '.' ? '|' : '#'); |
||||
|
for (char *c = surrounding; c < surrounding + 8; c++) { |
||||
|
if (*c == new) tally++; |
||||
|
} |
||||
|
if (tally >= 3) *a = new; |
||||
|
break; |
||||
|
case '#': |
||||
|
for (char *c = surrounding; c < surrounding + 8; c++) { |
||||
|
if (*c == '#') tally++; |
||||
|
if (*c == '|') tally2++; |
||||
|
} |
||||
|
if (!(tally >= 1 && tally2 >= 1)) *a = '.'; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
int render_bitmap(const char *fname, const char *acres, const struct size2d size) |
||||
|
{ |
||||
|
FILE *f = fopen(fname, "w"); |
||||
|
if (!f) { |
||||
|
perror(fname); |
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
|
flockfile(f); |
||||
|
fprintf(f, "P6\n%u %u\n255\n", size.w, size.h); |
||||
|
|
||||
|
for (unsigned y = 0; y < size.h; y++) { |
||||
|
for (unsigned x = 0; x < size.w; x++) { |
||||
|
char color[3] = {255}; |
||||
|
|
||||
|
switch (acres[y * size.w + x]) { |
||||
|
case '.': |
||||
|
// Yellow
|
||||
|
color[0] = 205; |
||||
|
color[1] = 255; |
||||
|
color[2] = 110; |
||||
|
break; |
||||
|
case '|': |
||||
|
// Green
|
||||
|
color[0] = 0; |
||||
|
color[1] = 255; |
||||
|
color[2] = 0; |
||||
|
break; |
||||
|
case '#': |
||||
|
// Brown
|
||||
|
color[0] = 192; |
||||
|
color[1] = 125; |
||||
|
color[2] = 0; |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
fwrite_unlocked(color, 3, 1, f); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
funlockfile(f); |
||||
|
fclose(f); |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
int main(int argc, char *argv[]) |
||||
|
{ |
||||
|
struct size2d size; |
||||
|
char *acres = parse_acres("input", &size); |
||||
|
if (!acres) return 1; |
||||
|
|
||||
|
unsigned minutes = 10; |
||||
|
int render = 0; |
||||
|
if (argc > 1) minutes = strtol(argv[1], NULL, 0); |
||||
|
if (argc > 2 && strcmp(argv[2], "-render") == 0) render = 1; |
||||
|
|
||||
|
char *next = xrealloc(NULL, size.w * size.h); |
||||
|
memcpy(next, acres, size.w * size.h); |
||||
|
|
||||
|
char *fname = NULL; |
||||
|
clock_t start = clock(); |
||||
|
for (unsigned i = 0; i <= minutes; i++) { |
||||
|
if (i != 0) { |
||||
|
advance_frame(acres, next, size); |
||||
|
memcpy(acres, next, size.w * size.h); |
||||
|
|
||||
|
if (i % 10000 == 0) { |
||||
|
double framespers = 10000 / ((double)(clock() - start) / CLOCKS_PER_SEC); |
||||
|
unsigned eta = (double)(minutes - i) / framespers; |
||||
|
fprintf(stderr, "Progress: %.2f%% (speed: %.2f frames/s, ETA: %u:%u:%u)\n", |
||||
|
(double)i / minutes * 100, framespers, |
||||
|
eta / 60 / 60, (eta / 60) % 60, eta % 60); |
||||
|
start = clock(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (render) { |
||||
|
if (asprintf(&fname, "out/frame%04u.ppm", i) == -1) { |
||||
|
perror("asprintf"); |
||||
|
break; |
||||
|
} |
||||
|
if (render_bitmap(fname, acres, size)) break; |
||||
|
free(fname); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
unsigned wood = 0; |
||||
|
unsigned lumber = 0; |
||||
|
for (unsigned y = 0; y < size.h; y++) { |
||||
|
for (unsigned x = 0; x < size.w; x++) { |
||||
|
char c = acres[y * size.w + x]; |
||||
|
if (c == '|') wood++; |
||||
|
if (c == '#') lumber++; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
printf("Resource value: %u\n", wood * lumber); |
||||
|
|
||||
|
free(next); |
||||
|
free(acres); |
||||
|
return 0; |
||||
|
} |
@ -0,0 +1,2 @@ |
|||||
|
#!/bin/sh |
||||
|
convert -monitor -resize 1000% -filter point -delay 5 -loop 0 out/*.ppm out.gif |
After Width: | Height: | Size: 1.8 MiB |
Loading…
Reference in new issue