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

#define XSIZE 160
#define YSIZE 100
#define YMUL 2
#define XMUL 2

#define WRAP

#define r()   (rand())

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

void init(void);
void update(int, int);
void done(void);
int main(int, char **);

void init(void) {
	int r,g,b,x,y;
	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 if (x<192)
			b=(x-128);
		else
			r=g=b=255-x;
		vga_setpalette(x,r,g,b);
	}
	for(x=0;x<XSIZE;x++) for(y=0;y<YSIZE;y++) board[0][x][y]=r();
}

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

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

	sboard=&board[frame];
	dboard=&board[1-frame];
	for(y=0;y<YSIZE;y++) {
		lp=line;
		for(x=0;x<XSIZE;x++) {
			if((x==0)||(x==XSIZE-1)||(y==0)||(y==YSIZE-1)) 
#ifdef WRAP
			(*dboard)[x][y]=((
				(*sboard)[(x+XSIZE-1)%XSIZE] [(y+YSIZE-1)%YSIZE]+
				(*sboard)[x		   ] [(y+YSIZE-1)%YSIZE]+
				(*sboard)[(x+1)%XSIZE	   ] [(y+YSIZE-1)%YSIZE]+
				(*sboard)[(x+XSIZE-1)%XSIZE] [y		       ]+
				(*sboard)[x		   ] [y		       ]+
				(*sboard)[(x+1)%XSIZE	   ] [y		       ]+
				(*sboard)[(x+XSIZE-1)%XSIZE] [(y+1)%YSIZE      ]+
				(*sboard)[x		   ] [(y+1)%YSIZE      ]+
				(*sboard)[(x+1)%XSIZE	   ] [(y+1)%YSIZE      ]+
				inc
			)/9)&mask;
#else
			(*dboard)[x][y]=0;
#endif
			else
			(*dboard)[x][y]=((
				(*sboard)[x-1][y-1]+
				(*sboard)[x  ][y-1]+
				(*sboard)[x+1][y-1]+
				(*sboard)[x-1][y  ]+
				(*sboard)[x  ][y  ]+
				(*sboard)[x+1][y  ]+
				(*sboard)[x-1][y+1]+
				(*sboard)[x  ][y+1]+
				(*sboard)[x+1][y+1]+
				inc
			)/9)&mask;
/*
*/
			for(bx=0;bx<XMUL;bx++) *(lp++)=(*dboard)[x][y];
		}
		for(by=0;by<YMUL;by++) vga_drawscansegment(line,0,y*YMUL+by,XSIZE*XMUL);
	}
	frame=1-frame;
}

int main(int argc, char**argv) {
	long t=time(NULL);
	int i,j;
	
	if(argc>3) t=atoi(argv[3]);
	srand(t);
	if(argc>2) j=atoi(argv[2]); else {
		int b,c;
		j=(1<<(c=rand()%7+8))-1;
		for(b=rand()%4;b;b--) j&=~(2<<(rand()%c));
	}
	if(argc>1) i=atoi(argv[1]); else i=-(9+rand()%(j/30));

	printf("To duplicate this display: %s %d %d %ld\n",argv[0],i,j,t);
	srand(t);
	init();
	while(1)
		update(i,j);


	done();

	return 0;
}
