#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

#define YSIZE 58
#define XSIZE 80
#define XMUL 4
#define MOVE 1 
#define WARM 16
#define SPEED 1
#define VGA
#define DIAG

#define ITER  65536
#define r()   (rand48())

int board[2][YSIZE][XSIZE];
unsigned char dboard[YSIZE][XSIZE*4];
int t=0;

double www[WARM][3];
double tm=0;

#define FADE 15

#define new(y,x) board[t][(x)][(y)]
#define old(y,x) board[1-t][(x)][(y)]
#define d(y,x)  dboard[x][y*XMUL]=dboard[x][y*XMUL+1]=dboard[x][y*XMUL+2]=dboard[x][y*XMUL+3]

#ifdef VGA

#include <vga.h>

void init(void) {
	int r,g,b,x;
	vga_setmode(G320x200x256);
	r=g=b=0;
	for(x=0;x<256;x++) {
		if (x<64) 
			r=x;
		else if (x<128)
			g=(x-64);
		else
			b=(x-128)/2;
		vga_setpalette(x,r,g,b);
	}
}

void done(void) {
	vga_setmode(TEXT);
}

void do_plot(int bx) {
	int y;
	for(y=0;y<(YSIZE-8);y++) {
		vga_drawscansegment(dboard[y+8],0,200-4*y,XSIZE*XMUL);
		vga_drawscansegment(dboard[y+8],0,200-4*y-1,XSIZE*XMUL);
		vga_drawscansegment(dboard[y+8],0,200-4*y-2,XSIZE*XMUL);
		vga_drawscansegment(dboard[y+8],0,200-4*y-3,XSIZE*XMUL);
	}	
}

#else /* None */
void do_plot(int bx) {}
void done(void) {}
void init(void) {}
#endif

void update(void){
	int x,y,bx;	
/* Most are average of neighbors */
	for(y=SPEED;y<(YSIZE-1);y++)
		for(x=1;x<(XSIZE-1);x++) 
			new(x,y+1)=((
#if defined(DIAG)
				old(x+1,y+1)+
				old(x+1,y  )+
				old(x+1,y-1)+
				old(x  ,y+1)+
				old(x  ,y-1)+
				old(x-1,y+1)+
				old(x-1,y  )+
				old(x-1,y-1)
			)/8)-FADE;
#elif defined(DOWN)
				old(x+1,y  )+
				old(x+1,y-1)+
				old(x  ,y-1)+
				old(x-1,y  )+
				old(x-1,y-1)
			)/5)-FADE;	
#else
				old(x+1,y  )+
				old(x-1,y  )+
				old(x  ,y+1)+
				old(x  ,y-1)
			)/4)-FADE;
#endif
	for(x=1;x<(XSIZE-1);x++)
			new(x,SPEED)=((
#if defined(DIAG)
				old(x+1,1)+
				old(x+1,0)+
				old(x  ,1)+
				old(x-1,1)+
				old(x-1,0)
			)/5)-FADE;
#elif defined(DOWN)
				old(x+1,0)+
				old(x-1,0)
			)/2)-FADE;
#else
				old(x+1,0)+
				old(x-1,0)+
				old(x  ,1)
			)/3)-FADE;
#endif
				
	for(x=1;x<(XSIZE-1);x++) 
		for(y=0;y<SPEED;y++) 
			new(x,y)=0;

/* Borders are all 0 */
	for(y=0;y<YSIZE;y++) new(0,y)=new(XSIZE-1,y)=0; 
				
/* Maybe make a hostspot */
	{
#define MINTEMP 256
#define MAXTEMP 1024
#define DTEMP   32
		int temp,x,y;
		double tt,acc;
				
		tm++;
		for(x=0;x<XSIZE;x++) {
			acc=0;
			for(temp=0;temp<WARM;temp++) {
				tt=(sin(tm*www[temp][0]+x*www[temp][1])+1)/2;
				acc+=tt*tt;
			}
			temp=(acc/WARM)*(MAXTEMP-MINTEMP)+MINTEMP;
			for(y=0;y<8;y++)
				new(x,y)=temp;
		}
		bx=(320-XSIZE)/2;
	}

/* Make sure we're all positive */
	for(y=1;y<YSIZE;y++)
		for(x=1;x<XSIZE;x++) {
			if (new(x,y)<0) new(x,y)=d(x,y)=0;
/*			if (new(x,y)>2048) new(x,y)=2048; */
			if (new(x,y)>1023) d(x,y)=255;
			else d(x,y)=new(x,y)>>2;
		}
	do_plot(bx);
	t=1-t;
}

int main(int argc, char**argv) {
	long t=time(NULL);
	int i,count=ITER;
	
	argc==1?srand48(t):srand48(atoi(argv[1]));
	t=drand48()*12;
	for(i=0;i<WARM;i++) www[i][0]=drand48()*.5-.25,www[i][1]=drand48()*.5-.25;
	printf("%ld\n",t);

	init();
	tm=time(NULL);
	for(;count--;)
		update();

	done();

	printf("%f frames/second\n",(double)ITER/(time(NULL)-t));
	printf("%f pixels/second\n",(double)XSIZE*YSIZE*ITER/(time(NULL)-t));

	return 0;
}
