/*
 * CoCo sudoku solver example using Micro-C
 *
 * Copyright 2013 by John W. Linville
 */

#include <6809io.h>

/*
 * I hate #include'ing C files, but it seems to be the only option for
 * multiple C source files short of generating a new library...
 */
#include "screen.c"

char board[9][9];

void setupboard(char *addr) {
	int i, j;

	for (i = 0; i < 9; i++)
		for (j = 0; j < 9; j++)
			board[i][j] = *addr++;
};

void drawboard(void) {
	int i, j, pos;
	char val;

	pos = 96+9;
	curpos(pos);

	for (i = 0; i < 9; i++) {
		for (j = 0; j < 9; j++) {
			val = board[i][j];
			if (!val)
				putchr(' ');
			else
				putchr('0' + val);
			pos++;
			if ((j % 3) == 2)
				pos += 2;
			curpos(pos);
		}
		pos += (32 - 15);
		if ((i % 3) == 2)
			pos += 32;
		curpos(pos);
	}
}

void drawframe(void) {
	int i, j, pos;

	cls(0);

	curpos(12);
	putstr("SUDOKU!");
	for (i = 64+9; i < 576+9; i += 128) {
		curpos(i);
		for (j = 0; j < 13; j++)
			putchr(0xef);
	}

	for (i = 64+7; i < 64+27; i += 5) {
		pos = i;
		curpos(pos);
		for (j = 0; j < 13; pos += 32, j++) {
			curpos(pos);
			putchr(0xef);
			putchr(0xef);
		}
	}
}

int invalid(int okzero)
{
	int i, j, bi, bj;
	char val, seen[9];

	/*
	 * Check each row...
	 */
	for (i = 0; i < 9; i++) {
		memset(seen, 0, 9);

		for (j = 0; j < 9; j++) {
			val = board[i][j];
			if (!val)
				if (okzero)
					continue;
				else
					return 1;
			if (seen[val-1])
				return 1;
			else
				seen[val-1] = 1;
		}
	}

	/*
	 * Check each column...
	 */
	for (j = 0; j < 9; j++) {
		memset(seen, 0, 9);

		for (i = 0; i < 9; i++) {
			val = board[i][j];
			if (!val)
				if (okzero)
					continue;
				else
					return 1;
			if (seen[val-1])
				return 1;
			else
				seen[val-1] = 1;
		}
	}

	/*
	 * Check each block...
	 */
	for (i = 0; i < 9; i++) {
		memset(seen, 0, 9);

		for (j = 0; j < 9; j++) {
			bi = (3 * (i / 3)) + (j / 3);
			bj = (3 * (i % 3)) + (j % 3);

			val = board[bi][bj];
			if (!val)
				if (okzero)
					continue;
				else
					return 1;
			if (seen[val-1])
				return 1;
			else
				seen[val-1] = 1;
		}
	}

	return 0;
}

int solve(int row, int column) {
	int i, nrow, ncol;

	if (chkchr() == -1)
		exit();

	if (column != 8) {
		nrow = row;
		ncol = column + 1;
	} else {
		nrow = row + 1;
		ncol = 0;
	}

	if (!board[row][column]) {
		for (i = 1; i <= 9; i++) {
			board[row][column] = i;

			drawboard();

			if (invalid(1))
				continue;

			if (nrow == 9)
				return 1;

			if (solve(nrow, ncol))
				return 1;
		}

		board[row][column] = 0;
		return 0;
	}

	if (nrow == 9)
		return 1;
	else
		return solve(nrow, ncol);
}

void main(char *setupdata)
{

	drawframe();

	setupboard(setupdata);

	drawboard();

	solve(0, 0);

	if (invalid(0)) {
		curpos(492);
		putstr("INVALID");
	} else {
		curpos(493);
		putstr("VALID");
	}
}
