/*
 *    movegen.c
 *              - generovani a provadeni tahu
 *
 */

#include <stdio.h>
#include "data.h"

/* lokalni funkce */

void MoveGenKolm(THra *, TMG, int *, int, int);
void MoveGenSikm(THra *, TMG, int *, int, int);

int MoveGen(THra * h, TMG mg, int MM)
{
	int mp = 0, i = 1;
	THrac *hrac;
	TFigura *f;
	TPozice kam;
	TTah tah;
	char zt[5];
	if (h->natahu == BILYH) {
		MoveGenKolm(h, mg, &mp, BDAM, MM);
		if (MM && mp)
			return 1;
		MoveGenSikm(h, mg, &mp, BDAM, MM);
		if (MM && mp)
			return 1;
		MoveGenKolm(h, mg, &mp, BVEZ, MM);
		if (MM && mp)
			return 1;
		MoveGenSikm(h, mg, &mp, BSTR, MM);
		if (MM && mp)
			return 1;
		hrac = &(h->bily);
	} else {
		MoveGenKolm(h, mg, &mp, CDAM, MM);
		if (MM && mp)
			return 1;
		MoveGenSikm(h, mg, &mp, CDAM, MM);
		if (MM && mp)
			return 1;
		MoveGenKolm(h, mg, &mp, CVEZ, MM);
		if (MM && mp)
			return 1;
		MoveGenSikm(h, mg, &mp, CSTR, MM);
		if (MM && mp)
			return 1;
		hrac = &(h->cerny);
	}
	while (i < 16 && (hrac->figury[i].fig != PPOL)) {
		f = &(hrac->figury[i]);
		switch (f->fig) {
		case BJEZ:
		case CJEZ:
			kam.x = f->pos.x;
			kam.y = f->pos.y;
			kam.x = f->pos.x + 2;
			kam.y = f->pos.y - 1;
			tah.odkud = f->pos;
			tah.kam = kam;
			Num2Not(f->pos, &zt[0]);
			Num2Not(kam, &zt[2]);
			if (a1b1(zt) && JeToTah(zt, h, 0)) {
				mg[mp] = tah;
				mp++;
				if (MM)
					return 1;
			}
			kam.x = f->pos.x + 2;
			kam.y = f->pos.y + 1;
			tah.odkud = f->pos;
			tah.kam = kam;
			Num2Not(f->pos, &zt[0]);
			Num2Not(kam, &zt[2]);
			if (a1b1(zt) && JeToTah(zt, h, 0)) {
				mg[mp] = tah;
				mp++;
				if (MM)
					return 1;
			}
			kam.x = f->pos.x - 2;
			kam.y = f->pos.y - 1;
			tah.odkud = f->pos;
			tah.kam = kam;
			Num2Not(f->pos, &zt[0]);
			Num2Not(kam, &zt[2]);
			if (a1b1(zt) && JeToTah(zt, h, 0)) {
				mg[mp] = tah;
				mp++;
				if (MM)
					return 1;
			}
			kam.x = f->pos.x - 2;
			kam.y = f->pos.y + 1;
			tah.odkud = f->pos;
			tah.kam = kam;
			Num2Not(f->pos, &zt[0]);
			Num2Not(kam, &zt[2]);
			if (a1b1(zt) && JeToTah(zt, h, 0)) {
				mg[mp] = tah;
				mp++;
				if (MM)
					return 1;
			}
			kam.x = f->pos.x + 1;
			kam.y = f->pos.y - 2;
			tah.odkud = f->pos;
			tah.kam = kam;
			Num2Not(f->pos, &zt[0]);
			Num2Not(kam, &zt[2]);
			if (a1b1(zt) && JeToTah(zt, h, 0)) {
				mg[mp] = tah;
				mp++;
				if (MM)
					return 1;
			}
			kam.x = f->pos.x + 1;
			kam.y = f->pos.y + 2;
			tah.odkud = f->pos;
			tah.kam = kam;
			Num2Not(f->pos, &zt[0]);
			Num2Not(kam, &zt[2]);
			if (a1b1(zt) && JeToTah(zt, h, 0)) {
				mg[mp] = tah;
				mp++;
				if (MM)
					return 1;
			}
			kam.x = f->pos.x - 1;
			kam.y = f->pos.y + 2;
			tah.odkud = f->pos;
			tah.kam = kam;
			Num2Not(f->pos, &zt[0]);
			Num2Not(kam, &zt[2]);
			if (a1b1(zt) && JeToTah(zt, h, 0)) {
				mg[mp] = tah;
				mp++;
				if (MM)
					return 1;
			}
			kam.x = f->pos.x - 1;
			kam.y = f->pos.y - 2;
			tah.odkud = f->pos;
			tah.kam = kam;
			Num2Not(f->pos, &zt[0]);
			Num2Not(kam, &zt[2]);
			if (a1b1(zt) && JeToTah(zt, h, 0)) {
				mg[mp] = tah;
				mp++;
				if (MM)
					return 1;
			}
			break;
		case CPES:
		case BPES:
			kam.x = f->pos.x;
			kam.y = f->pos.y + 1;
			Num2Not(f->pos, &zt[0]);
			Num2Not(kam, &zt[2]);
			tah.odkud = f->pos;
			tah.kam = kam;
			if (a1b1(zt) && JeToTah(zt, h, 0)) {
				mg[mp] = tah;
				mp++;
				if (MM)
					return 1;
			}
			kam.x = f->pos.x;
			kam.y = f->pos.y + 2;
			Num2Not(f->pos, &zt[0]);
			Num2Not(kam, &zt[2]);
			tah.odkud = f->pos;
			tah.kam = kam;
			if (a1b1(zt) && JeToTah(zt, h, 0)) {
				mg[mp] = tah;
				mp++;
				if (MM)
					return 1;
			}
			kam.x = f->pos.x;
			kam.y = f->pos.y - 1;
			Num2Not(f->pos, &zt[0]);
			Num2Not(kam, &zt[2]);
			tah.odkud = f->pos;
			tah.kam = kam;
			if (a1b1(zt) && JeToTah(zt, h, 0)) {
				mg[mp] = tah;
				mp++;
				if (MM)
					return 1;
			}
			kam.x = f->pos.x;
			kam.y = f->pos.y - 2;
			Num2Not(f->pos, &zt[0]);
			Num2Not(kam, &zt[2]);
			tah.odkud = f->pos;
			tah.kam = kam;
			if (a1b1(zt) && JeToTah(zt, h, 0)) {
				mg[mp] = tah;
				mp++;
				if (MM)
					return 1;
			}
			kam.x = f->pos.x + 1;
			kam.y = f->pos.y + 1;
			Num2Not(f->pos, &zt[0]);
			Num2Not(kam, &zt[2]);
			tah.odkud = f->pos;
			tah.kam = kam;
			if (a1b1(zt) && JeToTah(zt, h, 0)) {
				mg[mp] = tah;
				mp++;
				if (MM)
					return 1;
			}
			kam.x = f->pos.x + 1;
			kam.y = f->pos.y - 1;
			Num2Not(f->pos, &zt[0]);
			Num2Not(kam, &zt[2]);
			tah.odkud = f->pos;
			tah.kam = kam;
			if (a1b1(zt) && JeToTah(zt, h, 0)) {
				mg[mp] = tah;
				mp++;
				if (MM)
					return 1;
			}
			kam.x = f->pos.x - 1;
			kam.y = f->pos.y + 1;
			Num2Not(f->pos, &zt[0]);
			Num2Not(kam, &zt[2]);
			tah.odkud = f->pos;
			tah.kam = kam;
			if (a1b1(zt) && JeToTah(zt, h, 0)) {
				mg[mp] = tah;
				mp++;
				if (MM)
					return 1;
			}
			kam.x = f->pos.x - 1;
			kam.y = f->pos.y - 1;
			Num2Not(f->pos, &zt[0]);
			Num2Not(kam, &zt[2]);
			tah.odkud = f->pos;
			tah.kam = kam;
			if (a1b1(zt) && JeToTah(zt, h, 0)) {
				mg[mp] = tah;
				mp++;
				if (MM)
					return 1;
			}
		}
		i++;
	}
	/* KRALe si nechame az na konec */
	f = &(hrac->figury[0]);
	if ((f->fig == BKRA) || (f->fig == CKRA)) {
		kam.x = f->pos.x;
		kam.y = f->pos.y;
		/* rochada */
		kam.x = f->pos.x + 2;
		kam.y = f->pos.y;
		tah.odkud = f->pos;
		tah.kam = kam;
		Num2Not(f->pos, &zt[0]);
		Num2Not(kam, &zt[2]);
		if (a1b1(zt) && JeToTah(zt, h, 0)) {
			mg[mp] = tah;
			mp++;
			if (MM)
				return 1;
		}
		kam.x = f->pos.x - 2;
		kam.y = f->pos.y;
		tah.odkud = f->pos;
		tah.kam = kam;
		Num2Not(f->pos, &zt[0]);
		Num2Not(kam, &zt[2]);
		if (a1b1(zt) && JeToTah(zt, h, 0)) {
			mg[mp] = tah;
			mp++;
			if (MM)
				return 1;
		}
		/* end of rochada */
		kam.x = f->pos.x + 1;
		kam.y = f->pos.y;
		tah.odkud = f->pos;
		tah.kam = kam;
		Num2Not(f->pos, &zt[0]);
		Num2Not(kam, &zt[2]);
		if (a1b1(zt) && JeToTah(zt, h, 0)) {
			mg[mp] = tah;
			mp++;
			if (MM)
				return 1;
		}
		kam.x = f->pos.x + 1;
		kam.y = f->pos.y - 1;
		tah.odkud = f->pos;
		tah.kam = kam;
		Num2Not(f->pos, &zt[0]);
		Num2Not(kam, &zt[2]);
		if (a1b1(zt) && JeToTah(zt, h, 0)) {
			mg[mp] = tah;
			mp++;
			if (MM)
				return 1;
		}
		kam.x = f->pos.x + 1;
		kam.y = f->pos.y + 1;
		tah.odkud = f->pos;
		tah.kam = kam;
		Num2Not(f->pos, &zt[0]);
		Num2Not(kam, &zt[2]);
		if (a1b1(zt) && JeToTah(zt, h, 0)) {
			mg[mp] = tah;
			mp++;
			if (MM)
				return 1;
		}
		kam.x = f->pos.x;
		kam.y = f->pos.y - 1;
		tah.odkud = f->pos;
		tah.kam = kam;
		Num2Not(f->pos, &zt[0]);
		Num2Not(kam, &zt[2]);
		if (a1b1(zt) && JeToTah(zt, h, 0)) {
			mg[mp] = tah;
			mp++;
			if (MM)
				return 1;
		}
		kam.x = f->pos.x;
		kam.y = f->pos.y + 1;
		tah.odkud = f->pos;
		tah.kam = kam;
		Num2Not(f->pos, &zt[0]);
		Num2Not(kam, &zt[2]);
		if (a1b1(zt) && JeToTah(zt, h, 0)) {
			mg[mp] = tah;
			mp++;
			if (MM)
				return 1;
		}
		kam.x = f->pos.x - 1;
		kam.y = f->pos.y - 1;
		tah.odkud = f->pos;
		tah.kam = kam;
		Num2Not(f->pos, &zt[0]);
		Num2Not(kam, &zt[2]);
		if (a1b1(zt) && JeToTah(zt, h, 0)) {
			mg[mp] = tah;
			mp++;
			if (MM)
				return 1;
		}
		kam.x = f->pos.x - 1;
		kam.y = f->pos.y;
		tah.odkud = f->pos;
		tah.kam = kam;
		Num2Not(f->pos, &zt[0]);
		Num2Not(kam, &zt[2]);
		if (a1b1(zt) && JeToTah(zt, h, 0)) {
			mg[mp] = tah;
			mp++;
			if (MM)
				return 1;
		}
		kam.x = f->pos.x - 1;
		kam.y = f->pos.y + 1;
		tah.odkud = f->pos;
		tah.kam = kam;
		Num2Not(f->pos, &zt[0]);
		Num2Not(kam, &zt[2]);
		if (a1b1(zt) && JeToTah(zt, h, 0)) {
			mg[mp] = tah;
			mp++;
			if (MM)
				return 1;
		}
	} else {
		printf("DEBUG: Nulta figura != KRAL ??? BUG!\n");
		TiskFig(*h);
	}
	return mp;
}

void MoveGenKolm(THra * h, TMG mg, int *mp, int FIG, int MM)
{
	int x, y, i, pv = 0;
	TFigura v[2];
	TPozice kam;
	TTah tah;
	char zt[5];
	if (h->natahu == BILYH) {
		i = 1;
		while (i < 16) {
			while (i < 16 && h->bily.figury[i].fig != FIG)
				i++;
			if (i < 16) {
				v[pv] = h->bily.figury[i];
				pv++;
				i++;
			}
		}
	} else {
		i = 1;
		while (i < 16) {
			while (i < 16 && h->cerny.figury[i].fig != FIG)
				i++;
			if (i < 16) {
				v[pv] = h->cerny.figury[i];
				pv++;
				i++;
			}
		}
	}
	for (i = 0; i < pv; i++) {
		/* doprava */
		x = v[i].pos.x + 1;
		y = v[i].pos.y;
		Num2Not(v[i].pos, &zt[0]);
		tah.odkud = v[i].pos;
		while (x <= 7 && h->sachovnice[x][y] == PPOL) {
			kam.x = x;
			kam.y = y;
			Num2Not(kam, &zt[2]);
			if (JeToTah(zt, h, 0)) {
				tah.kam = kam;
				mg[*mp] = tah;
				(*mp)++;
				if (MM)
					return;
			}
			x++;
		}		/* while doprava ... PPOL */
		if (x <= 7) {
			kam.x = x;
			kam.y = y;
			Num2Not(kam, &zt[2]);
			if (JeToTah(zt, h, 0)) {
				tah.kam = kam;
				mg[*mp] = tah;
				(*mp)++;
				if (MM)
					return;
			}
		}		/* posledni doprava ( braci ) */
		/* doleva */
		x = v[i].pos.x - 1;
		while (x >= 0 && h->sachovnice[x][y] == PPOL) {
			kam.x = x;
			kam.y = y;
			Num2Not(kam, &zt[2]);
			if (JeToTah(zt, h, 0)) {
				tah.kam = kam;
				mg[*mp] = tah;
				(*mp)++;
				if (MM)
					return;
			}
			x--;
		}		/* while doleva ... PPOL */
		if (x >= 0) {
			kam.x = x;
			kam.y = y;
			Num2Not(kam, &zt[2]);
			if (JeToTah(zt, h, 0)) {
				tah.kam = kam;
				mg[*mp] = tah;
				(*mp)++;
				if (MM)
					return;
			}
		}		/* posledni doleva ( braci ) */
		/* dolu */
		x = v[i].pos.x;
		y = v[i].pos.y - 1;
		while (y >= 0 && h->sachovnice[x][y] == PPOL) {
			kam.x = x;
			kam.y = y;
			Num2Not(kam, &zt[2]);
			if (JeToTah(zt, h, 0)) {
				tah.kam = kam;
				mg[*mp] = tah;
				(*mp)++;
				if (MM)
					return;
			}
			y--;
		}		/* while dolu ... PPOL */
		if (y >= 0) {
			kam.x = x;
			kam.y = y;
			Num2Not(kam, &zt[2]);
			if (JeToTah(zt, h, 0)) {
				tah.kam = kam;
				mg[*mp] = tah;
				(*mp)++;
				if (MM)
					return;
			}
		}		/* posledni dolu ( braci ) */
		/* nahoru */
		x = v[i].pos.x;
		y = v[i].pos.y + 1;
		while (y <= 7 && h->sachovnice[x][y] == PPOL) {
			kam.x = x;
			kam.y = y;
			Num2Not(kam, &zt[2]);
			if (JeToTah(zt, h, 0)) {
				tah.kam = kam;
				mg[*mp] = tah;
				(*mp)++;
				if (MM)
					return;
			}
			y++;
		}		/* while nahoru ... PPOL */
		if (y <= 7) {
			kam.x = x;
			kam.y = y;
			Num2Not(kam, &zt[2]);
			if (JeToTah(zt, h, 0)) {
				tah.kam = kam;
				mg[*mp] = tah;
				(*mp)++;
				if (MM)
					return;
			}
		}		/* posledni dolu ( braci ) */
	}			/* for i */
}

void MoveGenSikm(THra * h, TMG mg, int *mp, int FIG, int MM)
{
	int x, y, i, pv = 0;
	TFigura v[2];
	TPozice kam;
	TTah tah;
	char zt[5];
	if (h->natahu == BILYH) {
		i = 1;
		while (i < 16) {
			while (i < 16 && h->bily.figury[i].fig != FIG)
				i++;
			if (i < 16) {
				v[pv] = h->bily.figury[i];
				pv++;
				i++;
			}
		}
	} else {
		i = 1;
		while (i < 16) {
			while (i < 16 && h->cerny.figury[i].fig != FIG)
				i++;
			if (i < 16) {
				v[pv] = h->cerny.figury[i];
				pv++;
				i++;
			}
		}
	}
	for (i = 0; i < pv; i++) {
		/* doprava nahoru */
		x = v[i].pos.x + 1;
		y = v[i].pos.y + 1;
		Num2Not(v[i].pos, &zt[0]);
		tah.odkud = v[i].pos;
		while (x <= 7 && y <= 7 && h->sachovnice[x][y] == PPOL) {
			kam.x = x;
			kam.y = y;
			Num2Not(kam, &zt[2]);
			if (JeToTah(zt, h, 0)) {
				tah.kam = kam;
				mg[*mp] = tah;
				(*mp)++;
				if (MM)
					return;
			}
			x++;
			y++;
		}		/* while doprava ... PPOL */
		if (x <= 7 && y <= 7) {
			kam.x = x;
			kam.y = y;
			Num2Not(kam, &zt[2]);
			if (JeToTah(zt, h, 0)) {
				tah.kam = kam;
				mg[*mp] = tah;
				(*mp)++;
				if (MM)
					return;
			}
		}		/* posledni doprava a nahoru ( braci ) */
		/* doleva a nahoru */
		x = v[i].pos.x - 1;
		y = v[i].pos.y + 1;
		while (x >= 0 && y <= 7 && h->sachovnice[x][y] == PPOL) {
			kam.x = x;
			kam.y = y;
			Num2Not(kam, &zt[2]);
			if (JeToTah(zt, h, 0)) {
				tah.kam = kam;
				mg[*mp] = tah;
				(*mp)++;
				if (MM)
					return;
			}
			x--;
			y++;
		}		/* while doleva a nahoru ... PPOL */
		if (x >= 0 && y <= 7) {
			kam.x = x;
			kam.y = y;
			Num2Not(kam, &zt[2]);
			if (JeToTah(zt, h, 0)) {
				tah.kam = kam;
				mg[*mp] = tah;
				(*mp)++;
				if (MM)
					return;
			}
		}		/* posledni doleva a nahoru ( braci ) */
		/* doprava dolu */
		x = v[i].pos.x + 1;
		y = v[i].pos.y - 1;
		Num2Not(v[i].pos, &zt[0]);
		tah.odkud = v[i].pos;
		while (x <= 7 && y >= 0 && h->sachovnice[x][y] == PPOL) {
			kam.x = x;
			kam.y = y;
			Num2Not(kam, &zt[2]);
			if (JeToTah(zt, h, 0)) {
				tah.kam = kam;
				mg[*mp] = tah;
				(*mp)++;
				if (MM)
					return;
			}
			x++;
			y--;
		}		/* while doprava ... PPOL */
		if (x <= 7 && y >= 0) {
			kam.x = x;
			kam.y = y;
			Num2Not(kam, &zt[2]);
			if (JeToTah(zt, h, 0)) {
				tah.kam = kam;
				mg[*mp] = tah;
				(*mp)++;
				if (MM)
					return;
			}
		}		/* posledni doprava a dolu ( braci ) */
		/* doleva a dolu */
		x = v[i].pos.x - 1;
		y = v[i].pos.y - 1;
		while (x >= 0 && y >= 0 && h->sachovnice[x][y] == PPOL) {
			kam.x = x;
			kam.y = y;
			Num2Not(kam, &zt[2]);
			if (JeToTah(zt, h, 0)) {
				tah.kam = kam;
				mg[*mp] = tah;
				(*mp)++;
				if (MM)
					return;
			}
			x--;
			y--;
		}		/* while doleva a nahoru ... PPOL */
		if (x >= 0 && y >= 0) {
			kam.x = x;
			kam.y = y;
			Num2Not(kam, &zt[2]);
			if (JeToTah(zt, h, 0)) {
				tah.kam = kam;
				mg[*mp] = tah;
				(*mp)++;
				if (MM)
					return;
			}
		}		/* posledni (braci) */
	}			/* for i */
}

int SMoveGen(THra * H, TMG t)
{
	int p, i, c = 0;
	p = MoveGen(H, t, 0);
	for (i = 0; i < p; i++)
		if (SMove(H, t[i])) {
			t[c] = t[i];
			c++;
		}
	return (c);
}
