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


/*
		 1
	 	 |
	2 ---*--- 0
		 |
		 3

0 	0000 	0000 	0 	0
1	1000	0010	4 	1
2 	0100 	0001 	8 	2
3 	1100 	0011 	12 	3
4 	0010 	1000 	1 	4
5 	1010 	0101 	10 	10
6 	0110 	1001 	9 	6
7 	1110 	1011 	13 	7
8 	0001 	0100 	2 	8
9 	1001 	0110 	6 	9
10 	0101 	1010 	5 	5
11 	1101 	1010 	5 	11 
12 	0011 	1100 	3 	12
13 	1011 	0101 	10 	13	
14 	0111 	1010 	5 	14	
15 	1111 	1111 	15	15
*/

#define NX 200
#define NY 200

static const uint8_t collide[16] =
{
	0, 4, 8, 12, 1, 10, 9, 13, 2, 6, 5, 14, 3, 7, 11, 15

};

uint8_t transport(uint8_t left, uint8_t right, uint8_t up, uint8_t down)
{
	uint8_t val = (0x1)&left | (0x4)&right | (0x8)&up | (0x2)&down;
	val = ((0x8)&val)>>2 | ((0x4)&val)>>2 | ((0x2)&val)<<2 | ((0x1)&val)<<2;
	return val;
}

main()
{

	uint8_t newcell[NX][NY], cell[NX][NY];
	int i, j, n, nsteps = 600;
	
	FILE *fp, *fopen();
	fp = fopen("data.dat","w");

	srand(time(NULL));

	// INITIALIZE
	for (i=0; i < NX; i++) {
		for (j=0; j < NY; j++) {
			newcell[i][j] = 0;
			cell[i][j] = 0;
			// if (rand()%10 < 2) {
			// 	cell[i][j] = rand()%16;
			// } else {
			// 	cell[i][j] = 0;
			// }
			
		}
	}
	for (i=NX/2-NX/4; i < NX/2+NX/4; i++) {
		for (j=NY/2-NY/4; j < NY/2+NY/4; j++) {
			cell[i][j] = 15;//rand()%15 + 1;
		}
	}
	
	for (n=0; n < nsteps; n++) {

		// collision
		for (i=0; i < NX; i++) {
			for (j=0; j < NY; j++) {
				newcell[i][j] = collide[cell[i][j]];
			}
		}

		// transport
		for (i=1; i < NX-1; i++) {
			for (j=1; j < NY-1; j++) {
				cell[i][j] = transport(newcell[i-1][j],newcell[i+1][j],newcell[i][j+1],newcell[i][j-1]);
			}
		}

		// periodic boundary
		for (i=0; i < NX; i++) {
			cell[i][0] = cell[i][NX-2];
			cell[i][NX-1] = cell[i][1];
		}
		for (j=0; j < NY; j++) {
			cell[0][j] = cell[NX-2][j];
			cell[NX-1][j] = cell[1][j];
		}


		for ( j=0; j < NY; j++) {
			for ( i=0; i < NX; i++) {
				fprintf(fp,"%d \t",cell[i][j]);
			}
			fprintf(fp, " \n");
		}
		fprintf(fp, "# T = %d \n", n);
	}

	fclose(fp);

}