Skip to content

Instantly share code, notes, and snippets.

@khlorghaal
Created August 1, 2022 01:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save khlorghaal/2656ca3cba255569126dffeee15194a5 to your computer and use it in GitHub Desktop.
Save khlorghaal/2656ca3cba255569126dffeee15194a5 to your computer and use it in GitHub Desktop.
water.c
#include<ncurses.h>
#include<malloc.h>
#include<memory.h>
#include<unistd.h>
typedef unsigned int usecs;
void usleep(usecs);
//khlor stuff
typedef size_t sizt;
#define ITER(o,n) for(size_t o=0; o<n; o++)
#define ITER2(o,n0,n1) for(size_t o=n0; o<n1; o++)
#define ITER_GRID(x,y,w,h) ITER(y,h){ ITER(x,w){
#define SNAKE(x,y,w) (x+y*w)
#include "water.h"
const char cell_on = '+';
const char cell_off= ' ';
const char cell_bound= '_';
typedef unsigned char byte;
//not reentrant nor threadsafe
bool cellrd(void* cells, int x, int y, int w){
byte c= ((byte*)cells)[SNAKE(x,y,w)/8];
return (c>>(x%8))&1;
}
void cellwr(void* cells, bool v, int x, int y, int w){
byte b= 1<<(x%8);
byte* cp= cells+SNAKE(x,y,w)/8;
byte c= *cp;
c= v? c|b : c&~b;
*cp= c;
}
void water_init(water* wa, int w, int h){
wa->w= w;
wa->h= h;
wa->rd= malloc(w*h/8);
wa->wr= malloc(w*h/8);
wa->bd= malloc(w*h/8);
}
void water_simulate_c(water* _, int rand, int frame){
//automata
int w= _->w;
int h= _->h;
void* rd= _->rd;
void* wr= _->wr;
void* bound= _->bd;
bool r1= rand &7;
bool r2= (rand>>8)&7;
char o[8][2]={//kernel
{ 0, -1},
//{ 2,0},
{-1, -1},
//{ 0, -1},
{ 4, 0},
{ r1, 0},
{ 0, -1},
//{-2,0},
{ 1, -1},
//{ 0, -1},
{-4, 0},
{-r2, 0}
};
int oi= (frame)%8;
char ox= o[oi][0];
char oy= o[oi][1];
ITER2(y,1,h-1){
ITER2(x,1,w-1){
#define m(_v) \
f(_v##z,x ,y )\
f(_v##n,x-ox,y-oy)\
f(_v##p,x+ox,y+oy)
#define f(_v,_x,_y) bool _v= cellrd(rd, _x,_y, w);
m( )
#undef f
#define f(_v,_x,_y) bool _v= cellrd(bound, _x,_y, w);
m(b)
#undef f
#undef m
if(bp)
p= true;
bool v= z?p:n;
if(bz) v= false;
//else if(bn) v= p;
//else if(bp) v= z;
cellwr(wr, v, x,y,w);
}}
memcpy(rd,wr,w*h/8);
}
#include<signal.h>
bool running= true;
void sigint(int signo){ running= false; }
#define rand(r) ((r)+((r)<<16))^0x73a71731
int main(){
signal(SIGINT, sigint);
signal(SIGHUP, sigint);
//ncurses
initscr();
cbreak();
noecho();
curs_set(0);
keypad(stdscr,1);
timeout(-1);
WINDOW* win;
int w,h;
const int PADW= 2;
const int PADH= 2;
w= COLS-PADW*2;
h= LINES-PADH*2;
w-= w%8;//byte alignment
win= newwin(h,w, PADH,PADW);
water water;
water_init(&water,w,h);
{
//initial state
void* rd= water.rd;
void* wr= water.wr;
void* bd= water.bd;
ITER_GRID(x,y,w,h){
//bool b= x/3 == y;//initial volume
bool b= false;
b|= x>=w-4 & y==h-1;//emitter
b|= x== 16 & y==h-1;
b|= (x==120|x==121) & (y==h-1);
cellwr(rd,b,x,y,w);
cellwr(wr,b,x,y,w);
b= x==0|x==w-1|y==0;
cellwr(bd,b,x,y,w);
}}}
}
//getch();
int frame= 0;
int r= 0;
//loop
while(running){
//rendering
char line[w+1];
line[w]=0;//terminator
void* cells= water.wr;
void* bd= water.bd;
ITER(cy,h){
ITER(cx,w){
bool c= cellrd(cells,cx,h-cy-1,w);
bool b= cellrd(bd,cx,h-cy-1,w);
line[cx]= !!c? cell_on:cell_off;
if(b)
line[cx]= cell_bound;
}
mvwaddnstr(win, cy,0, line, w);
}
refresh();
wrefresh(win);
//getch();
usleep((int)(1000000./30.));
//water_simulate(&water);
r= rand(r);
water_simulate_c(&water, r, frame++);
}
delwin(win);
endwin();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment