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

#define YSIZE 50
#define YMUL  (200/YSIZE)
#define XSIZE 80
#define XMUL (320/XSIZE)

#define r()   (lrand48())

typedef int board_t[3][XSIZE][YSIZE];
board_t board[2];
int frame=0;

void init(void) {
	int r,g,b,x,y;
	vga_setmode(G320x200x16M);
	r=g=b=0;
	for(x=0;x<256;x++) {
		if (x<64) 
			r=x;
		else if (x<128)
			g=(x-64);
		else if (x<192)
			b=(x-128);
		else
			r=g=b=255-x;
		vga_setpalette(x,r,g,b);
	}
	for(r=0;r<3;r++) 
		for(x=0;x<XSIZE;x++) 
			for(y=0;y<YSIZE;y++) 
				board[0][r][x][y]=r();
}

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

void update(void){
	int x,y,bx,by,p;	
	board_t *sboard, *dboard;
	char line[XSIZE*XMUL*3];

	sboard=&board[frame];
	dboard=&board[1-frame];
	for(y=0;y<YSIZE;y++) {
		for(x=0;x<XSIZE;x++) for(p=0;p<3;p++) {
			if((x==0)||(x==XSIZE-1)||(y==0)||(y==YSIZE-1)) (*dboard)[p][x][y]=0;
			else
			(*dboard)[p][x][y]=((
				(*sboard)[p][x-1][y-1]+
				(*sboard)[p][x  ][y-1]+
				(*sboard)[p][x+1][y-1]+
				(*sboard)[p][x-1][y  ]+
				(*sboard)[p][x  ][y  ]+
				(*sboard)[p][x+1][y  ]+
				(*sboard)[p][x-1][y+1]+
				(*sboard)[p][x  ][y+1]+
				(*sboard)[p][x+1][y+1]-
				9
			)/9)&0xae;
			for(bx=0;bx<XMUL;bx++) line[(x*XMUL+bx)*3+p]=~(*dboard)[p][x][y];
		}
		for(by=0;by<YMUL;by++) vga_drawscansegment(line,0,y*YMUL+by,sizeof(line));
	}
	frame=1-frame;
}

int main(int argc, char**argv) {
	long t=time(NULL);
	int i;
	
	argc==1?srand48(t):srand48(atoi(argv[1]));

	init();
	while(1)
		update();

	done();

	return 0;
}
