#include <u.h>
#include <libc.h>
#include <libg.h>
#define	NPJW	48
#define	NSPLIT	6
#define	NDOT	(NSPLIT*NSPLIT+1)
uchar pjwbits[]={
0x00,0x00,0x30,0x07,0x80,0x00,
0x00,0x00,0xc0,0x00,0x80,0x00,
0x00,0x01,0x80,0x00,0x30,0x00,
0x00,0x01,0x80,0x00,0x08,0x00,
0x00,0x03,0x00,0x00,0x06,0x00,
0x00,0x03,0x3f,0x00,0x03,0xd0,
0x00,0x02,0x7f,0xc0,0x00,0x38,
0x00,0x0c,0xff,0xe0,0x00,0x38,
0x00,0x19,0xff,0xf0,0x00,0x0e,
0x00,0x33,0xff,0xf0,0x00,0x08,
0x00,0x63,0xff,0xf8,0x00,0x02,
0x00,0xc7,0xff,0xf8,0x00,0x03,
0x00,0xc7,0xff,0xfc,0x00,0x01,
0x01,0x87,0xff,0xfc,0x00,0x01,
0x03,0x07,0xff,0xfe,0x00,0x01,
0x03,0x0f,0xff,0xff,0x00,0x01,
0x06,0x0f,0xff,0xff,0x80,0x01,
0x0c,0x0f,0x3f,0xff,0x80,0x03,
0x0c,0x00,0x03,0xf0,0x00,0x01,
0x18,0x03,0xe1,0xc2,0x00,0x03,
0x18,0x07,0x00,0x00,0x00,0x03,
0x10,0x06,0x00,0x00,0x00,0x01,
0x10,0x06,0x84,0xc0,0x00,0x01,
0x10,0x07,0xfd,0xc0,0x00,0x03,
0x18,0x07,0xfd,0xc0,0x00,0x03,
0x18,0x0f,0xff,0xcf,0xc0,0x02,
0x1a,0x1f,0xfb,0xe7,0xc0,0x06,
0x0d,0x1f,0xf7,0xe7,0xf8,0x2e,
0x07,0x1f,0x8f,0xf0,0xc0,0x18,
0x07,0xde,0x7f,0xd8,0x00,0x38,
0x03,0xdf,0xf9,0x00,0x00,0x78,
0x07,0x3f,0xf8,0x01,0x80,0x78,
0x03,0x1f,0xfc,0x03,0x80,0x78,
0x03,0x1f,0xfe,0x03,0x80,0x18,
0x01,0x9f,0xff,0x80,0x00,0x18,
0x01,0x9f,0x99,0x80,0x00,0x30,
0x01,0x8f,0x8c,0x00,0x00,0x20,
0x00,0xcf,0xff,0xe0,0x00,0x20,
0x00,0x6f,0xff,0xc0,0x04,0x40,
0x00,0x3f,0xf8,0x00,0x07,0x80,
0x00,0x0f,0xfc,0x00,0x02,0x00,
0x00,0x0f,0xff,0xc0,0x06,0x00,
0x00,0x07,0xff,0xf0,0x0e,0x00,
0x00,0x0f,0xff,0xf0,0x1e,0x00,
0x00,0x07,0xff,0xe0,0x1c,0x00,
0x00,0x07,0xf8,0x00,0x18,0x00,
0x00,0x0f,0x90,0x00,0x18,0x00,
0x00,0x07,0xc0,0x00,0x18,0x00,
};
uchar pjwmaskbits[]={
0x00,0x00,0x3f,0xff,0x80,0x00,
0x00,0x00,0xff,0xff,0x80,0x00,
0x00,0x01,0xff,0xff,0xf0,0x00,
0x00,0x01,0xff,0xff,0xf8,0x00,
0x00,0x03,0xff,0xff,0xfe,0x00,
0x00,0x03,0xff,0xff,0xff,0xf0,
0x00,0x03,0xff,0xff,0xff,0xf8,
0x00,0x0f,0xff,0xff,0xff,0xf8,
0x00,0x1f,0xff,0xff,0xff,0xfe,
0x00,0x3f,0xff,0xff,0xff,0xf8,
0x00,0x7f,0xff,0xff,0xff,0xfe,
0x00,0xff,0xff,0xff,0xff,0xff,
0x00,0xff,0xff,0xff,0xff,0xff,
0x01,0xff,0xff,0xff,0xff,0xff,
0x03,0xff,0xff,0xff,0xff,0xff,
0x03,0xff,0xff,0xff,0xff,0xff,
0x07,0xff,0xff,0xff,0xff,0xff,
0x0f,0xff,0xff,0xff,0xff,0xff,
0x0f,0xff,0xff,0xff,0xff,0xff,
0x1f,0xff,0xff,0xff,0xff,0xff,
0x1f,0xff,0xff,0xff,0xff,0xff,
0x1f,0xff,0xff,0xff,0xff,0xff,
0x1f,0xff,0xff,0xff,0xff,0xff,
0x1f,0xff,0xff,0xff,0xff,0xff,
0x1f,0xff,0xff,0xff,0xff,0xff,
0x1f,0xff,0xff,0xff,0xff,0xfe,
0x1f,0xff,0xff,0xff,0xff,0xfe,
0x0f,0xff,0xff,0xff,0xff,0xfe,
0x07,0xff,0xff,0xff,0xff,0xf8,
0x07,0xff,0xff,0xff,0xff,0xf8,
0x03,0xff,0xff,0xff,0xff,0xf8,
0x07,0xff,0xff,0xff,0xff,0xf8,
0x03,0xff,0xff,0xff,0xff,0xf8,
0x03,0xff,0xff,0xff,0xff,0xf8,
0x01,0xff,0xff,0xff,0xff,0xf8,
0x01,0xff,0xff,0xff,0xff,0xf0,
0x01,0xff,0xff,0xff,0xff,0xe0,
0x00,0xff,0xff,0xff,0xff,0xe0,
0x00,0x7f,0xff,0xff,0xff,0xc0,
0x00,0x3f,0xff,0xff,0xff,0x80,
0x00,0x0f,0xff,0xff,0xfe,0x00,
0x00,0x0f,0xff,0xff,0xfe,0x00,
0x00,0x07,0xff,0xff,0xfe,0x00,
0x00,0x0f,0xff,0xff,0xfe,0x00,
0x00,0x07,0xff,0xff,0xfc,0x00,
0x00,0x07,0xff,0xff,0xf8,0x00,
0x00,0x0f,0xff,0xff,0xf8,0x00,
0x00,0x07,0xff,0xff,0xf8,0x00,
};
Bitmap *pjw, *pjwmask;
struct dot{
	Point pos;
	Point vel;
	int size, life;
}dot[NDOT];
struct dot *edot=&dot[NDOT];
Point gravity={ 0, 1 };
Point dv[NSPLIT]={
	 5, 0,
	 3, 4,
	-3, 4,
	-5, 0,
	-3,-4,
	 3,-4,
};
#define	DISP	16
int life, disp;
#define	or origin
#define	co corner
void
upd(struct dot *d){
	int i=d->size;
	bitblt(&screen, add(d->pos, Pt(-i, -i)), pjwmask, pjwmask->r, D&~S);
	bitblt(&screen, add(d->pos, Pt(-i, -i)), pjw, pjw->r, S|D);
	d->pos=add(d->pos, d->vel);
	if(d->pos.x<screen.r.min.x+d->size){
		d->pos.x=2*(screen.r.min.x+d->size)-d->pos.x;
		d->vel.x=-d->vel.x;
	}
	else if(d->pos.x>=screen.r.max.x-d->size){
		d->pos.x=2*(screen.r.max.x-d->size)-d->pos.x;
		d->vel.x=-d->vel.x;
	}
	if(d->pos.y<screen.r.min.y+d->size){
		d->pos.y=2*(screen.r.min.y+d->size)-d->pos.y;
		d->vel.y=-d->vel.y;
	}
	else if(d->pos.y>=screen.r.max.y-d->size){
		d->pos.y=2*(screen.r.max.y-d->size)-d->pos.y;
		d->vel.y=-d->vel.y*4/5;
	}
	d->vel=add(d->vel, gravity);
	if(--d->life!=0)
		return;
	d->size/=2;
	if(d->size==0)
		return;
	d->life=life;
	for(i=1;i!=NSPLIT && edot!=&dot[NDOT];i++){
		*edot=*d;
		edot->vel=add(edot->vel, div(mul(dv[i], disp), DISP));
		edot++;
	}
	d->vel=add(d->vel, div(mul(dv[0], disp), DISP));
}
int rrand(int lo, int hi){
	return lo+nrand(hi+1-lo);
}
void
main(void){
	struct dot *d;
	Bitmap *t;
	binit(0,0,0);
	t=balloc(Rect(0, 0, NPJW, NPJW), 0);
	wrbitmap(t, 0, NPJW, pjwbits);
	pjw=balloc(Rect(0, 0, NPJW, NPJW), screen.ldepth);
	bitblt(pjw, pjw->r.min, t, t->r, S);
	wrbitmap(t, 0, NPJW, pjwmaskbits);
	pjwmask=balloc(Rect(0, 0, NPJW, NPJW), screen.ldepth);
	bitblt(pjwmask, pjwmask->r.min, t, t->r, S);
	bitblt(pjw, pjw->r.min, pjwmask, pjwmask->r, S^D);
	for(;;){
		if(edot==&dot[NDOT]){
			edot=dot+1;
			dot[0].pos.x=(screen.r.min.x+screen.r.max.x)/2;
			dot[0].size=16;
			dot[0].pos.y=screen.r.max.y-dot[0].size;
			dot[0].life=life=rrand(30, 72);
			dot[0].vel.x=rrand(-5, 5);
			dot[0].vel.y=rrand(30, 60);
			disp=rrand(DISP/4, 2*DISP);
			bitblt(&screen, screen.r.min, &screen, screen.r, F);
		}
		for(d=dot;d!=edot;d++)
			upd(d);
		bflush();
		sleep(1);
	}
}
