~lsof/x

1f4a15a7c4d5d7830caae39af8104d737a8ff432 — lemon 2 years ago 1ea1b60
vla/life: turn it into a graphical program
2 files changed, 98 insertions(+), 28 deletions(-)

M vla/Makefile
M vla/life.c
M vla/Makefile => vla/Makefile +1 -0
@@ 4,5 4,6 @@ all: md5sum sha256sum life
md5sum: md5sum.c
sha256sum: sha256sum.c
life: life.c
	$(CC) $(CFLAGS) -lSDL2 -o $@ $<
clean:
	$(RM) md5sum sha256sum life

M vla/life.c => vla/life.c +97 -28
@@ 1,27 1,58 @@
#define _GNU_SOURCE // for nanosleep..
/* Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE. */

#include <string.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <SDL2/SDL.h>
#include <time.h>

#define bool _Bool

#define TAIL /* tail call (declaration of intent) */
#define EXPECT(x, ...)                      \
   ((!(x)) ? (fprintf(stderr, "error: "),   \
              fprintf(stderr, __VA_ARGS__), \
              fputc('\n', stderr),          \
              exit(1))                      \
           : (void)0)
#define MIN(x,y) ((x) < (y) ? (x) : (y))
#define W 230
#define H 180
#define SCALE 4

#define W 64
#define H 32
static char board[H][W], boardtmp[H][W];
static unsigned gen;
/* live cells = 0, dead cells = 1..255, depending how long they've been dead,
 * for a fadeout effect */
static unsigned char board[H][W], boardtmp[H][W]; char title[60]; static unsigned gen;
static SDL_Window *win; static SDL_Renderer *ren; static bool running = 1,
                  pause;

#define neighbours(b,y,x)                                            \
   ( b[(y-1)%H][(x-1)%W] + b[(y-1)%H][(x)%W] + b[(y-1)%H][(x+1)%W]   \
   + b[(y+0)%H][(x-1)%W]                     + b[(y+0)%H][(x+1)%W]   \
   + b[(y+1)%H][(x-1)%W] + b[(y+1)%H][(x)%W] + b[(y+1)%H][(x+1)%W] ) \
   ( !b[(y-1)%H][(x-1)%W] + !b[(y-1)%H][(x)%W] + !b[(y-1)%H][(x+1)%W]   \
   + !b[(y+0)%H][(x-1)%W]                      + !b[(y+0)%H][(x+1)%W]   \
   + !b[(y+1)%H][(x-1)%W] + !b[(y+1)%H][(x)%W] + !b[(y+1)%H][(x+1)%W] ) \

static void life(size_t i, size_t y, size_t x, size_t n, char *);
static void life(size_t i, size_t y, size_t x, size_t n, char _[(
   y = i/W, x = i%W,
   n = neighbours(board, y, x),
   boardtmp[y][x] = (board[y][x] ? (n == 2 || n == 3) : (n == 3)),
   boardtmp[y][x] = board[y][x],
   (board[y][x] == 0 ? (n == 2 || n == 3) : (n == 3)) ?
      boardtmp[y][x] = 0
   : (board[y][x] == 0) ?
      boardtmp[y][x] = 150
   :
      (boardtmp[i/W][i%W] = MIN(boardtmp[i/W][i%W]*5/4, 255)),

   (++i < W*H) ?
      TAIL life(i, y,x,n,"")
   :


@@ 30,41 61,79 @@ static void life(size_t i, size_t y, size_t x, size_t n, char _[(

static void randini(size_t i, char *);
static void randini(size_t i, char _[(
   board[i/W][i%W] = rand() < RAND_MAX / 2,
   board[i/W][i%W] = rand() < RAND_MAX / 3 ? 0 : 255,
   (++i < W*H) ?
      TAIL randini(i, "")
   : (void)0,
1)]) {}

static void clear(char _[(
   printf("%s", "\x1b[2J"),
   fflush(stdout),
static void draw(size_t i, int c, SDL_Rect *rc, char *);
static void draw(size_t i, int c, SDL_Rect *rc, char _[(
   (rc->x = i%W*SCALE, rc->y = i/W*SCALE, rc->w = rc->h = SCALE),
   ((c = board[i/W][i%W]) > 0) ?
      c = pause ? 255 : c,
      SDL_SetRenderDrawColor(ren, 200,200,255,255-c)
   :
      SDL_SetRenderDrawColor(ren, 255,255,255,255),
   SDL_RenderFillRect(ren, rc),
   (++i < W*H) ?
      TAIL draw(i, c, rc, "")
   : (void)0,
1)]) {}

static void events(SDL_Event *, char *);
static void events(SDL_Event *ev, char _[(
   (SDL_PollEvent(ev)) ? (
      (ev->type == SDL_QUIT || (ev->type == SDL_KEYDOWN && ev->key.keysym.sym == SDLK_ESCAPE)) ?
         running = 0
      : (ev->type == SDL_KEYDOWN && ev->key.keysym.sym == SDLK_SPACE) ?
         pause ^= 1
      : (ev->type == SDL_KEYDOWN && ev->key.keysym.sym == SDLK_r) ?
         randini(0, "")
      : (ev->type == SDL_KEYDOWN && ev->key.keysym.sym == SDLK_c) ?
         memset(board, 255, sizeof board)
      : (void)0,

      TAIL events(ev, "")
   ) : (void)0,
1)]) {}

static void draw(size_t i, char *);
static void draw(size_t i, char _[(
   (i && i%W == 0) ? putchar('\n') : (void)0,
   putchar(board[i/W][i%W] ? '#' : ' '),
   (++i < W*H) ?
      TAIL draw(i, "")
   : putchar('\n'),
static void maybepaint(int mb, int mx, int my, char _[(
   (mb = SDL_GetMouseState(&mx, &my)),
   (mb & SDL_BUTTON_LMASK && mx >= 0 && my >= 0 && mx < W*SCALE && my < H*SCALE) ?
      board[my/SCALE][mx/SCALE] = 0
   : (mb & SDL_BUTTON_RMASK && mx >= 0 && my >= 0 && mx < W*SCALE && my < H*SCALE) ?
      board[my/SCALE][mx/SCALE] = 255
   : (void)0,
1)]) {}

static void loop(char *);
static void loop(char _[(
   clear(""),
   printf("Generation %u\n", gen++),
   draw(0, ""),
   life(0, 0,0,0,""),
   puts("Enter: step    ^D: auto    ^C: quit"),
   getchar() == EOF ?
      nanosleep(&(struct timespec){ .tv_nsec = 30000000 }, NULL)
   sprintf(title, "SPC: Pause;   R: Reset;   C: Clear - Gen. %u\n", gen),
   SDL_SetWindowTitle(win, title),
   events(&(SDL_Event){}, ""),
   maybepaint(0,0,0,""),
   SDL_SetRenderDrawColor(ren, 0, 0, 0, 255),
   SDL_RenderClear(ren),
   (!pause && !(SDL_GetMouseState(NULL, NULL) & (SDL_BUTTON_LMASK | SDL_BUTTON_RMASK))) ?
      ++gen,
      life(0, 0,0,0,"")
   : (void)0,
   draw(0, 0, &(SDL_Rect){0}, ""),
   SDL_RenderPresent(ren),
   SDL_Delay(16),
   running ?
      TAIL loop("")
   : (void)0,
   TAIL loop(""),
1)]) {}

int main(int argc, char *argv[(
   EXPECT(SDL_Init(SDL_INIT_VIDEO) == 0, "SDL: %s", SDL_GetError()),
   EXPECT(SDL_CreateWindowAndRenderer(W*SCALE, H*SCALE, 0, &win, &ren) == 0, "SDL: %s", SDL_GetError()),
   SDL_SetRenderDrawBlendMode(ren, SDL_BLENDMODE_BLEND),
   srand(time(NULL)),
   randini(0, ""),

   loop(""),
   SDL_Quit(),
1)]) {}