/* Conway's Game of Life for RVController
 * A product of Advanced Mesecons Devices, a Cheapie Systems company
 * This is free and unencumbered software released into the public domain.
 * See http://unlicense.org/ for more information */

#include <stdint.h>
#include <stdbool.h>
#include "rvcontroller-ecalls.h"

bool field[176] = {false}; // 22*8, extra pixel on each edge will just always be false, makes generation logic easier
bool field2[176] = {false};
char screenbuf[121] = {'x'}; //20*6 + terminator

void randomFill(void) {
	for (int y=1;y<=6;y++) {
		for (int x=1;x<=20;x++) {
			int cell = (y*22)+x;
			field[cell] = (randomint(0,1) == 1);
		}
	}
}

void draw(void) {
	char channelbuf[3] = {0};
	for (int y=1;y<=6;y++) {
		channelbuf[1] = 0x30+y;
		for (int x=1;x<=20;x++) {
			channelbuf[0] = 0x40+x;
			int cell = (y*22)+x;
			int outpos = ((y-1)*20)+x-1;
			if (field[cell]) {
				screenbuf[outpos] = '*';
				digiline_send(channelbuf,"ffaa55");
			} else {
				screenbuf[outpos] = ' ';
				digiline_send(channelbuf,"552200");
			}
		}
	}
	screenbuf[120] = 0;
	printstr(screenbuf);
}

int countLivingCells(int cell) {
	int count = 0;
	if (field[cell-23]) { count += 1; } //Up-left
	if (field[cell-22]) { count += 1; } //Up
	if (field[cell-21]) { count += 1; } //Up-right
	if (field[cell-1])  { count += 1; } //Left
	if (field[cell+1])  { count += 1; } //Right
	if (field[cell+21]) { count += 1; } //Down-left
	if (field[cell+22]) { count += 1; } //Down
	if (field[cell+23]) { count += 1; } //Down-right
	return count;
}

void calculateNewGeneration(void) {
	for (int y=1;y<=6;y++) {
		for (int x=1;x<=20;x++) {
			int cell = (y*22)+x;
			int living = countLivingCells(cell);
			if (field[cell]) {
				//Currently alive, stay if 2 or 3
				field2[cell] = (living == 2 || living == 3);
			} else {
				//Not currently alive, spawn if 3
				field2[cell] = (living == 3);
			}
		}
	}
}

void copyNewGeneration(void) {
	for (int y=1;y<=6;y++) {
		for (int x=1;x<=20;x++) {
			int cell = (y*22)+x;
			field[cell] = field2[cell];
		}
	}
}

void main(void) {
	randomFill();
	while (true) {
		draw();
		calculateNewGeneration();
		copyNewGeneration();
	}
}
