/*
 *    makemove.c
 *              - provadeni tahu a vyber tahu
 *
 */

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

extern int IQ, SIQ;
extern TTah historie[MAXPOCTAH];	/* 1.tah = [1] */

void ZpracujTah(char *c, THra * H)
{
	/* TFigura *fig,*brfig; - predelano na integery - indexy */
	int fi, brfi, vez;
	TPozice odkud, kam, tmpoz;
	TTah hrtah;
	Not2Num(&c[0], &odkud);
	Not2Num(&c[2], &kam);
	hrtah.odkud = odkud;
	hrtah.kam = kam;
	/* najit figuru */
	switch (H->natahu) {
	case BILYH:
		if (!NajdiFiguru(odkud, H->sachovnice, &(H->bily), &fi)) {
			printf("Nesrovnalost sachovnice a figur!!!");
			TiskSach(*H);
			printf("%s", c);
			return;
		}
		break;
	case CERNYH:
		if (!NajdiFiguru(odkud, H->sachovnice, &(H->cerny), &fi)) {
			printf("DEBUG: Inconsistent data on board!!!");
			TiskSach(*H);
			printf("%s", c);
			return;
		}
		break;
	}
	/* zmen POS u figury ... */
	switch (H->natahu) {
	case BILYH:
		H->bily.figury[fi].pos = kam;
		if (H->bily.figury[fi].fig == BKRA) {
			H->bily.rochada[0] = 0;
			H->bily.rochada[1] = 0;
		} else if ((H->bily.figury[fi].fig == BVEZ)) {
			if (odkud.x == 7)
				H->bily.rochada[0] = 0;
			if (odkud.x == 0)
				H->bily.rochada[1] = 0;
		}
		break;
	case CERNYH:
		H->cerny.figury[fi].pos = kam;
		if (H->cerny.figury[fi].fig == CKRA) {
			H->cerny.rochada[0] = 0;
			H->cerny.rochada[1] = 0;
		} else if ((H->cerny.figury[fi].fig == CVEZ)) {
			if (odkud.x == 7)
				H->cerny.rochada[0] = 0;
			if (odkud.x == 0)
				H->cerny.rochada[1] = 0;
		}
		break;
	}
	/* pokud bere nejakou figuru, tak vyres protihrace */
	if (H->sachovnice[kam.x][kam.y] != PPOL) {
		/* pokud se tahne na rohova pole, zakaz prislusne rochady */
		if (kam.x == 0 && kam.y == 0)
			H->bily.rochada[1] = 0;
		else if (kam.x == 7 && kam.y == 0)
			H->bily.rochada[0] = 0;
		else if (kam.x == 0 && kam.y == 7)
			H->cerny.rochada[1] = 0;
		else if (kam.x == 7 && kam.y == 7)
			H->cerny.rochada[0] = 0;
		switch (H->natahu) {
		case CERNYH:
			if (!NajdiFiguru(kam, H->sachovnice, &(H->bily), &brfi)) {
				printf("DEBUG: Inconsistent data on board!!!");
				TiskSach(*H);
				printf("%s", c);
				return;
			}
			break;
		case BILYH:
			if (!NajdiFiguru(kam, H->sachovnice, &(H->cerny), &brfi)) {
				printf("DEBUG: Inconsistent data on board!!!");
				TiskSach(*H);
				printf("%s", c);
				return;
			}
			break;
		}
		/* ted odebrat figuru z protihracovych figurek */
		switch (H->natahu) {
		case CERNYH:
			H->bily.figury[brfi].fig = PPOL;
			OdeberFiguru(&(H->bily));
			break;
		case BILYH:
			H->cerny.figury[brfi].fig = PPOL;
			OdeberFiguru(&(H->cerny));
			break;
		}
	}
	/* "kam" == PPOL  ...  ==> */
	else if ((H->enpas == hrtah.kam.x) &&
		 ((H->sachovnice[odkud.x][odkud.y] == CPES) ||
		  (H->sachovnice[odkud.x][odkud.y] == BPES)) &&
		 (hrtah.kam.x != hrtah.odkud.x))
		/* hraji na enpas sloupec a navic sikmo na PPOL => ENPAS */
		/* ;-) navic hraji nejakym pindikem */
		/* ^^ toto je spravne, pokud je JeToTah spravny */
	{
		switch (H->natahu) {
		case BILYH:
			tmpoz.y = 4;
			break;
		case CERNYH:
			tmpoz.y = 3;
			break;
		}
		tmpoz.x = H->enpas;
		switch (H->natahu) {
		case CERNYH:
			if (!NajdiFiguru(tmpoz, H->sachovnice, &(H->bily), &brfi)) {
				printf("DEBUG: Inconsistent data on board!!!");
				TiskSach(*H);
				printf("%s", c);
				return;
			}
			break;
		case BILYH:
			if (!NajdiFiguru(tmpoz, H->sachovnice, &(H->cerny), &brfi)) {
				printf("DEBUG: Inconsistent data on board!!!");
				TiskSach(*H);
				printf("%s", c);
				return;
			}
			break;
		}
		/* ted odebrat pesce z protihracovych figurek */
		switch (H->natahu) {
		case CERNYH:
			H->bily.figury[brfi].fig = PPOL;
			OdeberFiguru(&(H->bily));
			break;
		case BILYH:
			H->cerny.figury[brfi].fig = PPOL;
			OdeberFiguru(&(H->cerny));
			break;
		}
		/* jeste ji zrusit na sachovnici */
		H->sachovnice[tmpoz.x][tmpoz.y] = PPOL;
	}			/* end of ENPASSANT - odebrano z figur, odebrano z sachovnice */
	/* hejbni prislusnou figurou na sachovnici */
	H->sachovnice[kam.x][kam.y] = H->sachovnice[odkud.x][odkud.y];
	H->sachovnice[odkud.x][odkud.y] = PPOL;
	switch (H->natahu) {	/* nastavi promennou enpas */
	case BILYH:
		if ((H->bily.figury[fi].fig == BPES) &&
		    (kam.y - odkud.y == 2))
			H->enpas = kam.x;
		else
			H->enpas = -1;
		break;
	case CERNYH:
		if ((H->cerny.figury[fi].fig == CPES) &&
		    (kam.y - odkud.y == -2))
			H->enpas = kam.x;
		else
			H->enpas = -1;
		break;
	}
	/* pokud je rochada, hejbni jeste vezema */
	if (((H->natahu == BILYH) && (H->bily.figury[fi].fig == BKRA)) ||
	  ((H->natahu == CERNYH) && (H->cerny.figury[fi].fig == CKRA))) {
		if (strcmp(c, "e1g1") == 0) {
			H->bily.rochada[2] = 1;
			tmpoz.x = 7;
			tmpoz.y = 0;
			if (!NajdiFiguru(tmpoz, H->sachovnice, &(H->bily), &vez))
				printf("%s - Ta VEZ by tam mela bejt !!! :( => BUG\n", c);
			else {
				tmpoz.x = 5;
				H->bily.figury[vez].pos = tmpoz;
				H->sachovnice[7][0] = PPOL;
				H->sachovnice[5][0] = BVEZ;
			}
		} else if (strcmp(c, "e1c1") == 0) {
			H->bily.rochada[2] = 1;
			tmpoz.x = 0;
			tmpoz.y = 0;
			if (!NajdiFiguru(tmpoz, H->sachovnice, &(H->bily), &vez))
				printf("%s - Ta VEZ by tam mela bejt !!! :( => BUG\n", c);
			else {
				tmpoz.x = 3;
				H->bily.figury[vez].pos = tmpoz;
				H->sachovnice[0][0] = PPOL;
				H->sachovnice[3][0] = BVEZ;
			}
		} else if (strcmp(c, "e8g8") == 0) {
			H->cerny.rochada[2] = 1;
			tmpoz.x = 7;
			tmpoz.y = 7;
			if (!NajdiFiguru(tmpoz, H->sachovnice, &(H->cerny), &vez)) {
				printf("%s - Ta VEZ by tam mela bejt !!! :( => BUG\n", c);
				TiskSach(*H);
				TiskFig(*H);
				printf(" --- %d\n ", H->cerny.rochada[1]);
			} else {
				tmpoz.x = 5;
				H->cerny.figury[vez].pos = tmpoz;
				H->sachovnice[7][7] = PPOL;
				H->sachovnice[5][7] = CVEZ;
			}
		} else if (strcmp(c, "e8c8") == 0) {
			H->cerny.rochada[2] = 1;
			tmpoz.x = 0;
			tmpoz.y = 7;
			if (!NajdiFiguru(tmpoz, H->sachovnice, &(H->cerny), &vez))
				printf("Ta VEZ by tam mela bejt !!! :( => BUG\n");
			else {
				tmpoz.x = 3;
				H->cerny.figury[vez].pos = tmpoz;
				H->sachovnice[0][7] = PPOL;
				H->sachovnice[3][7] = CVEZ;
			}
		}
	}			/* end of HEJBANI VEZema pri rochade */
	/* pokud pesec dorazi na konec, zmen ho na DAMu */
	if (((H->natahu == BILYH) && (H->bily.figury[fi].fig == BPES) &&
	     (kam.y == 7)) ||
	    ((H->natahu == CERNYH) && (H->cerny.figury[fi].fig == CPES) &&
	     (kam.y == 0))) {	/* budeme menit */
		switch (H->natahu) {
		case BILYH:
			H->bily.figury[fi].fig = BDAM;
			H->sachovnice[kam.x][kam.y] = BDAM;
			break;
		case CERNYH:
			H->cerny.figury[fi].fig = CDAM;
			H->sachovnice[kam.x][kam.y] = CDAM;
			break;
		}
	}
	/* update historie tahu */
	(H->PHT)++;
	historie[H->PHT] = hrtah;
	/* prohodit hrace na tahu */
	if (H->natahu == BILYH)
		H->natahu = CERNYH;
	else
		H->natahu = BILYH;
    /* TODO: 50 tahu bez vymeny, bez tahu pescem... remiza */
}

int NejlepsiTah(THra * H, char c[5], int vv)
{
	static THra temp;
	TMG mg;
	int p, i, k = 1, best, bestval, t, hod[MAXGENTAH], siq = SIQ;
	time_t t1, t2;
	time(&t1);
	p = MoveGen(H, mg, 0);
	if (p == 0)
		return -1;
	vv && printf("\n");
    if (p == 1) {
        best = 0;
        t2=t1;
    } else
        while (1) {
            vv && printf("Depth <%d,%2d> %3d%%", k, siq, 0);
            best = -1;
            bestval = -MATVAL - 1;	/* pokud najde mat ... */
            for (i = 0; i < p; i++) {
                temp = *H;
                Num2Not(mg[i].odkud, &c[0]);
                Num2Not(mg[i].kam, &c[2]);
                ZpracujTah(c, &temp);
                t = -AlfaBeta(&temp, k - 1, -MATVAL, -bestval);
                hod[i] = t;
                if (t > bestval) {
                    best = i;
                    bestval = t;
                }
                vv && printf("\b\b\b\b%3d%%", (i + 1) * 100 / p);
            }
            time(&t2);
            vv && printf(" (%3ds)\n", t2 - t1);
            /* TODO make this better */
            if ( ( ((t2-t1)*5) * (H->tmoves - (((H->PHT+1))/2)%H->tmoves)) 
                    > H->tleft )
                break;
            else {
                Sort(mg, hod, p);
                k++;
            }
        }
	Num2Not(mg[best].odkud, &c[0]);
	Num2Not(mg[best].kam, &c[2]);
	return (t2 - t1 + 1);
}
