//Main drzewa decyzyjne 1 + algorytm genetyczny

#include<iostream>
#include<stdlib.h>
#include<windows.h>
#include<conio.h>
#include<string>
#include<list>
#include<set>
#include<math.h>
#include<stack>
#include<fstream>
#include <stdio.h>
#include <cstdlib> 
#include <ctime>
//#include<bits/stdc++.h>
#include <algorithm>
#include <utility>

using namespace std;

const float maxFloat = FLT_MAX;
const int ROW = 27;
const int COL = 27;
typedef pair<int, int> Pair;
typedef pair<double, pair<int, int> > pPair;
struct cell
{
	int parent_i, parent_j;
	double f, g, h;
};

char pole[27][27][6];
int pozycjaTraktoraX = 1, pozycjaTraktoraY = 1;
char currentWay = 'S';


//algorytm genetyczny
int scoreBuraki = 0;
int scoreZiemniaki = 0;
int rozmiarPopulacji = 500;
string* zebraneBuraki = new string[rozmiarPopulacji];
string* zebraneZiemniaki = new string[rozmiarPopulacji];
string* burakiDoSadzenia = new string[20];
string* ziemniakiDoSadzenia = new string[20];
int gmoLeftBuraki;
int gmoLeftZiemniaki;
string kod_genetyczny[27][27];

string generateValue() {
	string x;
	srand(time(NULL));
	int random = (rand() % 1000, 1);
	//string x = itoa(rand() % 1000,trash,10);
	x = to_string(random);
	if (x.size() == 2) {
		x = "0" + x;
	}
	else if (x.size() == 1) {
		x = "00" + x;
	}

	return x;

}


string generateVegetable() {

	string taste = generateValue();
	string colour = generateValue();
	string size = generateValue();

	return taste + colour + size;

}


void generatePopulation(string* population, int length) {

	int i;
	for (i = 0;i < length;i++) {
		population[i] = generateVegetable();
	}
}


int power(int x, int y) {

	if (y == 0) return 1;
	if (y == 1) return x;

	int temp = power(x, y / 2);
	if (y % 2 == 0) return temp * temp;
	else return x * temp * temp;
}


int stringToInt(string str, int size) {

	int x = 0;
	int i;
	reverse(str.begin(), str.end());

	for (i = 0;i < size;i++) {
		x += (str[i] - '0') * power(10, i);
	}

	reverse(str.begin(), str.end());

	return x;
}


int fitness(string vegetable) {

	int taste = stringToInt(vegetable.substr(0, 3), 3);
	int colour = stringToInt(vegetable.substr(3, 3), 3);
	int size = stringToInt(vegetable.substr(6, 3), 3);

	return (taste + colour + size) / 3;
}


bool comparePair(const pair<int, string>& i, const pair<int, string>& j)
{
	return i.first > j.first;
}


void ranking(string* population, string* parents, int populationSize, int parentsNumber) {

	int i;
	pair <int, string>* fitnessTable = new pair <int, string>[populationSize];
	for (i = 0;i < populationSize;i++) {
		fitnessTable[i] = make_pair(fitness(population[i]), population[i]);
	}

	sort(fitnessTable, fitnessTable + populationSize, comparePair);

	for (i = 0;i < parentsNumber;i++) {
		parents[i] = fitnessTable[i].second;
	}
	delete[] fitnessTable;
}


bool exists(int len, int* array, int element) {

	int i;
	for (i = 0;i < len;i++) {
		if (array[i] == element) return true;
	}
	return false;
}


void selection(string* population, string* parents, int populationSize, int parentsNumber) {

	int i, j, k;
	pair <int, string>* fitnessTable = new pair <int, string>[populationSize];
	for (i = 0;i < populationSize;i++) {
		fitnessTable[i] = make_pair(fitness(population[i]), population[i]);
	}

	sort(fitnessTable, fitnessTable + populationSize, comparePair);

	int roulette;
	int* taken = new int[parentsNumber];
	int sum = 0;
	for (i = 0;i < parentsNumber;i++) {
		for (j = populationSize - 1;j >= 0;j--) {
			if (not exists(parentsNumber, taken, j)) {
				sum += fitnessTable[j].first;
				fitnessTable[j].first = sum;
			}

		}
		roulette = rand() % fitnessTable[0].first;
		j = 0;
		while (exists(parentsNumber, taken, j)) {
			j += 1;
		}
		while (roulette > fitnessTable[j].first and j < populationSize) {
			if (not exists(parentsNumber, taken, j)) {
				roulette -= fitnessTable[j].first;
			}
			j += 1;
		}
		parents[i] = fitnessTable[j].second;
		taken[i] = j;
	}



}


string mutate(string child) {

	int d3 = rand() % 3;
	string mutation = generateValue();
	switch (d3) {
	case 0:
		child = mutation + child.substr(3, 6);
		break;
	case 1:
		child = child.substr(0, 3) + mutation + child.substr(6, 3);
		break;
	case 2:
		child = child.substr(0, 6) + mutation;
		break;
	}

	return child;
}


string cross(string parent[2]) {

	int i;
	string child = "";
	for (i = 0;i < 3;i++) {
		child += parent[rand() % 2].substr(i * 3, 3);
	}
	if (child == parent[0] or child == parent[1]) {
		string other;
		if (child == parent[0]) other = parent[1];
		else other = parent[0];
		int d3 = rand() % 3;
		switch (d3) {
		case 0:
			child = other.substr((rand() % 3) * 3, 3) + child.substr(3, 6);
			break;
		case 1:
			child = child.substr(0, 3) + other.substr((rand() % 3) * 3, 3) + child.substr(6, 3);
			break;
		case 2:
			child = child.substr(0, 6) + other.substr((rand() % 3) * 3, 3);
			break;
		}
	}
	int d1000 = rand() % 1000;
	if (rand() % 100 == 0) {
		child = mutate(child);
	}
	return child;
}


void crossover(string* parents, string* nextGen, int parentsNumber, int nextGenSize) {

	int counter = 0;
	int i, j;
	for (i = 0;i < parentsNumber;i++) {
		if (counter >= nextGenSize) {
			break;
		}
		else {
			nextGen[counter] = parents[i];
			counter += 1;
		}
	}
	while (counter < nextGenSize) {
		for (i = 0;i < parentsNumber;i++) {
			if (counter >= nextGenSize) {
				break;
			}
			else {
				for (j = i;j < parentsNumber;j++) {
					if (counter >= nextGenSize) {
						break;
					}
					else {
						string couple[2];
						couple[0] = parents[i];
						couple[1] = parents[j];
						nextGen[counter] = cross(couple);
						counter += 1;
					}
				}
			}
		}
	}
}


void genetic_algorithm(string* population, int populationSize, int parentsNumber, string* outcome, int outcomeSize) {

	int iteration, i;
	for (iteration = 0;iteration < 5;iteration++) {
		string* parents = new string[parentsNumber];
		selection(population, parents, populationSize, parentsNumber);

		string* nextGen = new string[populationSize];
		crossover(parents, nextGen, parentsNumber, populationSize);

		for (i = 0;i < populationSize;i++) {
			population[i] = nextGen[i];
		}

	}
	ranking(population, outcome, populationSize, outcomeSize);
}


string przypiszKod(string warzywa) {
	if (warzywa == "buraki") {
		if (gmoLeftBuraki > 0) {
			string temp = burakiDoSadzenia[gmoLeftBuraki - 1];
			gmoLeftBuraki -= 1;
			return temp;
		}
		else {
			return generateVegetable();
		}
	}
	else {
		if (gmoLeftZiemniaki > 0) {
			string temp = ziemniakiDoSadzenia[gmoLeftZiemniaki - 1];
			gmoLeftZiemniaki -= 1;
			return temp;
		}
		else {
			return generateVegetable();
		}
	}
}


void przypiszKodGenetyczny(int i, int j, char plant) {
	if (plant == 'B') {
		kod_genetyczny[i][j] = przypiszKod("buraki");
	}
	else if (plant == 'Z') {
		kod_genetyczny[i][j] = przypiszKod("ziemniaki");
	}
}


void obslugaAlgorytmuGenetycznego() {
	cout << "Zebrane buraki: " << scoreBuraki << endl;
	cout << "Zebrane ziemniaki: " << scoreZiemniaki << endl;
	if (scoreBuraki >= rozmiarPopulacji) {
		scoreBuraki = 0;

		for (int i = 0;i < 20;i++) {
			burakiDoSadzenia[i] = "000000000";
		}
		genetic_algorithm(zebraneBuraki, rozmiarPopulacji, rozmiarPopulacji - 5, burakiDoSadzenia, 20);
		gmoLeftBuraki = 20;
		for (int i = 0; i < rozmiarPopulacji;i++) {
			zebraneBuraki[i] = "000000000";
		}
		for (int i = 0;i < 20;i++) {
			cout << burakiDoSadzenia[i] << endl;
		}
	}
	if (scoreZiemniaki >= rozmiarPopulacji) {
		scoreZiemniaki = 0;

		for (int i = 0;i < 20;i++) {
			ziemniakiDoSadzenia[i] = "000000000";
		}
		genetic_algorithm(zebraneZiemniaki, rozmiarPopulacji, rozmiarPopulacji - 5, ziemniakiDoSadzenia, 20);
		gmoLeftZiemniaki = 20;
		for (int i = 0; i < rozmiarPopulacji;i++) {
			zebraneZiemniaki[i] = "000000000";
		}
		for (int i = 0;i < 20;i++) {
			cout << ziemniakiDoSadzenia[i] << endl;
		}
	}
}


void generujKody() {
	for (int i = 0;i < 27;i++) {
		for (int j = 0;j < 27;j++) {
			if (pole[i][j][0] == 'B') {
				kod_genetyczny[i][j] = przypiszKod("buraki");
			}
			else if (pole[i][j][0] == 'Z') {
				kod_genetyczny[i][j] = przypiszKod("ziemniaki");
			}
		}
	}
}

//---------------------------------------------------------------------


void color(string foregroundColor, string backgroundColor)
{
	HANDLE hOut;
	hOut = GetStdHandle(STD_OUTPUT_HANDLE);
	int foregroundCode = 15;
	if (foregroundColor == "black")
		foregroundCode = 0;
	if (foregroundColor == "dark_blue")
		foregroundCode = 1;
	if (foregroundColor == "green")
		foregroundCode = 2;
	if (foregroundColor == "cyan")
		foregroundCode = 3;
	if (foregroundColor == "dark_red")
		foregroundCode = 4;
	if (foregroundColor == "purple")
		foregroundCode = 5;
	if (foregroundColor == "dark_yellow")
		foregroundCode = 6;
	if (foregroundColor == "light_gray")
		foregroundCode = 7;
	if (foregroundColor == "gray")
		foregroundCode = 8;
	if (foregroundColor == "blue")
		foregroundCode = 9;
	if (foregroundColor == "lime")
		foregroundCode = 10;
	if (foregroundColor == "light_blue")
		foregroundCode = 11;
	if (foregroundColor == "red")
		foregroundCode = 12;
	if (foregroundColor == "magenta")
		foregroundCode = 13;
	if (foregroundColor == "yellow")
		foregroundCode = 14;
	if (foregroundColor == "white")
		foregroundCode = 15;

	int backgroundCode = 0;
	if (backgroundColor == "black")
		backgroundCode = 0;
	if (backgroundColor == "dark_blue")
		backgroundCode = 1;
	if (backgroundColor == "green")
		backgroundCode = 2;
	if (backgroundColor == "cyan")
		backgroundCode = 3;
	if (backgroundColor == "dark_red")
		backgroundCode = 4;
	if (backgroundColor == "purple")
		backgroundCode = 5;
	if (backgroundColor == "dark_yellow")
		backgroundCode = 6;
	if (backgroundColor == "light_gray")
		backgroundCode = 7;
	if (backgroundColor == "gray")
		backgroundCode = 8;
	if (backgroundColor == "blue")
		backgroundCode = 9;
	if (backgroundColor == "lime")
		backgroundCode = 10;
	if (backgroundColor == "light_blue")
		backgroundCode = 11;
	if (backgroundColor == "red")
		backgroundCode = 12;
	if (backgroundColor == "magenta")
		backgroundCode = 13;
	if (backgroundColor == "yellow")
		backgroundCode = 14;
	if (backgroundColor == "white")
		backgroundCode = 15;
	SetConsoleTextAttribute(hOut, foregroundCode + backgroundCode * 16);
}

void SetWindow(int Width, int Height)
{
	_COORD coord;
	coord.X = Width;
	coord.Y = Height;

	_SMALL_RECT Rect;
	Rect.Top = 0;
	Rect.Left = 0;
	Rect.Bottom = Height - 1;
	Rect.Right = Width - 1;

	HANDLE Handle = GetStdHandle(STD_OUTPUT_HANDLE);      // Get Handle 
	SetConsoleScreenBufferSize(Handle, coord);            // Set Buffer Size 
	SetConsoleWindowInfo(Handle, TRUE, &Rect);            // Set Window Size 
}

void updatePola()
{
	system("cls");
	for (int i = 0; i < 27; i++)
	{
		for (int j = 0; j < 27; j++)
		{
			char item = pole[i][j][0];
			switch (item)
			{
			case 'B':
			{
				color("purple", "dark_yellow");
			}break;
			case 'Z':
			{
				color("cyan", "dark_yellow");
			}break;
			case 'T':
			{
				color("red", "dark_yellow");
			}break;
			case 'G':
			{
				color("lime", "dark_yellow");
			}break;
			case '.':
			{
				color("yellow", "dark_yellow");
			}break;
			case '#':
			{
				color("light_gray", "gray");
			}break;
			}
			cout << pole[i][j][0];

		}
		cout << endl;
		color("white", "black");
	}

}

void correctMovement(char wantedWay)
{
	while (currentWay != wantedWay)
	{
		switch (currentWay)
		{
		case 'N':
		{
			if (wantedWay == 'S')
				currentWay = wantedWay;
			else
				currentWay = 'W';
		}break;
		case 'S':
		{
			if (wantedWay == 'N')
				currentWay = wantedWay;
			else
				currentWay = 'W';
		}break;
		case 'W':
		{
			if (wantedWay == 'E')
				currentWay = wantedWay;
			else
				currentWay = 'N';
		}break;
		case 'E':
		{
			if (wantedWay == 'W')
				currentWay = wantedWay;
			else
				currentWay = 'N';
		}break;
		}
	}
}
void Move(char kierunek)
{
	switch (kierunek)
	{
		//gA3ra-(w)
	case 'w':
	{
		if (pole[pozycjaTraktoraY - 1][pozycjaTraktoraX][0] != '#')
		{
			if (pole[pozycjaTraktoraY - 1][pozycjaTraktoraX][0] == 'B') {
				zebraneBuraki[scoreBuraki] = kod_genetyczny[pozycjaTraktoraY - 1][pozycjaTraktoraX];
				scoreBuraki += 1;
				kod_genetyczny[pozycjaTraktoraY - 1][pozycjaTraktoraX] = "000000000";
			}

			else if (pole[pozycjaTraktoraY - 1][pozycjaTraktoraX][0] == 'Z') {
				zebraneZiemniaki[scoreZiemniaki] = kod_genetyczny[pozycjaTraktoraY - 1][pozycjaTraktoraX];
				scoreZiemniaki += 1;
				kod_genetyczny[pozycjaTraktoraY - 1][pozycjaTraktoraX] = "000000000";
			}

			correctMovement('N');
			pole[pozycjaTraktoraY][pozycjaTraktoraX][0] = '.';
			pozycjaTraktoraY--;
			pole[pozycjaTraktoraY][pozycjaTraktoraX][0] = 'T';
		}
		updatePola();
	}break;
	//dA3A‚-(s)
	case 's':
	{
		if (pole[pozycjaTraktoraY + 1][pozycjaTraktoraX][0] != '#')
		{
			if (pole[pozycjaTraktoraY + 1][pozycjaTraktoraX][0] == 'B') {
				zebraneBuraki[scoreBuraki] = kod_genetyczny[pozycjaTraktoraY + 1][pozycjaTraktoraX];
				scoreBuraki += 1;
				kod_genetyczny[pozycjaTraktoraY + 1][pozycjaTraktoraX] = "000000000";
			}

			else if (pole[pozycjaTraktoraY + 1][pozycjaTraktoraX][0] == 'Z') {
				zebraneZiemniaki[scoreZiemniaki] = kod_genetyczny[pozycjaTraktoraY + 1][pozycjaTraktoraX];
				scoreZiemniaki += 1;
				kod_genetyczny[pozycjaTraktoraY + 1][pozycjaTraktoraX] = "000000000";
			}


			correctMovement('S');
			pole[pozycjaTraktoraY][pozycjaTraktoraX][0] = '.';
			pozycjaTraktoraY++;
			pole[pozycjaTraktoraY][pozycjaTraktoraX][0] = 'T';
		}
		updatePola();
	}break;
	//lewo-(a)
	case 'a':
	{
		if (pole[pozycjaTraktoraY][pozycjaTraktoraX - 1][0] != '#')
		{
			if (pole[pozycjaTraktoraY][pozycjaTraktoraX - 1][0] == 'B') {
				zebraneBuraki[scoreBuraki] = kod_genetyczny[pozycjaTraktoraY][pozycjaTraktoraX - 1];
				scoreBuraki += 1;
				kod_genetyczny[pozycjaTraktoraY][pozycjaTraktoraX - 1] = "000000000";
			}

			else if (pole[pozycjaTraktoraY][pozycjaTraktoraX - 1][0] == 'Z') {
				zebraneZiemniaki[scoreZiemniaki] = kod_genetyczny[pozycjaTraktoraY][pozycjaTraktoraX - 1];
				scoreZiemniaki += 1;
				kod_genetyczny[pozycjaTraktoraY][pozycjaTraktoraX - 1] = "000000000";
			}


			correctMovement('W');
			pole[pozycjaTraktoraY][pozycjaTraktoraX][0] = '.';
			pozycjaTraktoraX--;
			pole[pozycjaTraktoraY][pozycjaTraktoraX][0] = 'T';
		}
		updatePola();
	}break;
	//prawo-(d)
	case 'd':
	{
		if (pole[pozycjaTraktoraY][pozycjaTraktoraX + 1][0] != '#')
		{
			if (pole[pozycjaTraktoraY][pozycjaTraktoraX + 1][0] == 'B') {
				zebraneBuraki[scoreBuraki] = kod_genetyczny[pozycjaTraktoraY][pozycjaTraktoraX + 1];
				scoreBuraki += 1;
				kod_genetyczny[pozycjaTraktoraY][pozycjaTraktoraX + 1] = "000000000";
			}

			else if (pole[pozycjaTraktoraY][pozycjaTraktoraX + 1][0] == 'Z') {
				zebraneZiemniaki[scoreZiemniaki] = kod_genetyczny[pozycjaTraktoraY][pozycjaTraktoraX + 1];
				scoreZiemniaki += 1;
				kod_genetyczny[pozycjaTraktoraY][pozycjaTraktoraX + 1] = "000000000";
			}

			correctMovement('E');
			pole[pozycjaTraktoraY][pozycjaTraktoraX][0] = '.';
			pozycjaTraktoraX++;
			pole[pozycjaTraktoraY][pozycjaTraktoraX][0] = 'T';
		}
		updatePola();
	}break;
	}

	obslugaAlgorytmuGenetycznego();

}


bool isValid(int x, int y)
{
	if (pole[x][y][0] != '#')
	{
		return true;
	}
	return false;
}
bool isDestination(int x, int y, Pair dest)
{
	if (dest.first == x && dest.second == y)
	{
		return true;
	}
	return false;
}
double calculateHValue(int x, int y, Pair dest)
{
	return abs(x - dest.first) + abs(y - dest.second);
}
void tracePath(cell cellDetails[][COL], Pair dest)
{
	//printf("\nThe Path is "); //----start info
	int row = dest.first;
	int col = dest.second;

	stack<Pair> Path;

	while (!(cellDetails[row][col].parent_i == row
		&& cellDetails[row][col].parent_j == col))
	{
		Path.push(make_pair(row, col));
		int temp_row = cellDetails[row][col].parent_i;
		int temp_col = cellDetails[row][col].parent_j;
		row = temp_row;
		col = temp_col;
	}

	Path.push(make_pair(row, col));
	while (!Path.empty())
	{
		pair<int, int> p = Path.top();
		Path.pop();
		if (p.first > pozycjaTraktoraX)
			Move('d');
		if (p.first < pozycjaTraktoraX)
			Move('a');
		if (p.second > pozycjaTraktoraY)
			Move('s');
		if (p.second < pozycjaTraktoraY)
			Move('w');

		//printf("-> (%d,%d) ", p.first, p.second);  //---- informacja wierzchołku
		Sleep(1000);
	}

	return;
}
void aStarSearch(int grid[][COL], Pair src, Pair dest)
{
	bool closedList[ROW][COL];
	memset(closedList, false, sizeof(closedList));

	cell cellDetails[ROW][COL];

	int i, j;
	for (i = 0; i < ROW; i++)
	{
		for (j = 0; j < COL; j++)
		{
			cellDetails[i][j].f = maxFloat;
			cellDetails[i][j].g = maxFloat;
			cellDetails[i][j].h = maxFloat;
			cellDetails[i][j].parent_i = -1;
			cellDetails[i][j].parent_j = -1;
		}
	}
	i = src.first, j = src.second;
	cellDetails[i][j].f = 0.0;
	cellDetails[i][j].g = 0.0;
	cellDetails[i][j].h = 0.0;
	cellDetails[i][j].parent_i = i;
	cellDetails[i][j].parent_j = j;

	set<pPair> openList;
	openList.insert(make_pair(0.0, make_pair(i, j)));
	bool foundDest = false;

	while (!openList.empty())
	{
		pPair p = *openList.begin();
		openList.erase(openList.begin());
		i = p.second.first;
		j = p.second.second;
		closedList[i][j] = true;

		double gNew, hNew, fNew;
		double waga = 1.0;
		waga = ((double)pole[j][i][1] - 48) * 1.0;//----waga

		//----------- 1st Successor (North) ------------ 
		if (isValid(i - 1, j) == true)
		{
			if (isDestination(i - 1, j, dest) == true)
			{
				cellDetails[i - 1][j].parent_i = i;
				cellDetails[i - 1][j].parent_j = j;
				//printf("The destination cell is found\n");
				tracePath(cellDetails, dest);
				foundDest = true;
				return;
			}
			else if (closedList[i - 1][j] == false)
			{
				gNew = cellDetails[i][j].g + waga;
				hNew = calculateHValue(i - 1, j, dest);
				fNew = gNew + hNew;

				if (cellDetails[i - 1][j].f == maxFloat ||
					cellDetails[i - 1][j].f > fNew)
				{
					openList.insert(make_pair(fNew,
						make_pair(i - 1, j)));


					cellDetails[i - 1][j].f = fNew;
					cellDetails[i - 1][j].g = gNew;
					cellDetails[i - 1][j].h = hNew;
					cellDetails[i - 1][j].parent_i = i;
					cellDetails[i - 1][j].parent_j = j;
				}
			}
		}

		//----------- 2nd Successor (South) ------------ 
		if (isValid(i + 1, j) == true)
		{
			if (isDestination(i + 1, j, dest) == true)
			{
				cellDetails[i + 1][j].parent_i = i;
				cellDetails[i + 1][j].parent_j = j;
				//printf("The destination cell is found\n");
				tracePath(cellDetails, dest);
				foundDest = true;
				return;
			}
			else if (closedList[i + 1][j] == false)
			{
				gNew = cellDetails[i][j].g + waga;
				hNew = calculateHValue(i + 1, j, dest);
				fNew = gNew + hNew;
				if (cellDetails[i + 1][j].f == maxFloat ||
					cellDetails[i + 1][j].f > fNew)
				{
					openList.insert(make_pair(fNew, make_pair(i + 1, j)));
					cellDetails[i + 1][j].f = fNew;
					cellDetails[i + 1][j].g = gNew;
					cellDetails[i + 1][j].h = hNew;
					cellDetails[i + 1][j].parent_i = i;
					cellDetails[i + 1][j].parent_j = j;
				}
			}
		}

		//----------- 3rd Successor (East) ------------ 
		if (isValid(i, j + 1) == true)
		{
			if (isDestination(i, j + 1, dest) == true)
			{
				cellDetails[i][j + 1].parent_i = i;
				cellDetails[i][j + 1].parent_j = j;
				//printf("The destination cell is found\n");
				tracePath(cellDetails, dest);
				foundDest = true;
				return;
			}
			else if (closedList[i][j + 1] == false)
			{
				gNew = cellDetails[i][j].g + waga;
				hNew = calculateHValue(i, j + 1, dest);
				fNew = gNew + hNew;
				if (cellDetails[i][j + 1].f == maxFloat ||
					cellDetails[i][j + 1].f > fNew)
				{
					openList.insert(make_pair(fNew,
						make_pair(i, j + 1)));
					cellDetails[i][j + 1].f = fNew;
					cellDetails[i][j + 1].g = gNew;
					cellDetails[i][j + 1].h = hNew;
					cellDetails[i][j + 1].parent_i = i;
					cellDetails[i][j + 1].parent_j = j;
				}
			}
		}

		//----------- 4th Successor (West) ------------ 
		if (isValid(i, j - 1) == true)
		{
			if (isDestination(i, j - 1, dest) == true)
			{
				cellDetails[i][j - 1].parent_i = i;
				cellDetails[i][j - 1].parent_j = j;
				//printf("The destination cell is found\n");
				tracePath(cellDetails, dest);
				foundDest = true;
				return;
			}
			else if (closedList[i][j - 1] == false)
			{
				gNew = cellDetails[i][j].g + waga;
				hNew = calculateHValue(i, j - 1, dest);
				fNew = gNew + hNew;
				if (cellDetails[i][j - 1].f == maxFloat ||
					cellDetails[i][j - 1].f > fNew)
				{
					openList.insert(make_pair(fNew,
						make_pair(i, j - 1)));
					cellDetails[i][j - 1].f = fNew;
					cellDetails[i][j - 1].g = gNew;
					cellDetails[i][j - 1].h = hNew;
					cellDetails[i][j - 1].parent_i = i;
					cellDetails[i][j - 1].parent_j = j;
				}
			}
		}
	}

	/*if (foundDest == false)
		printf("Failed to find the Destination Cell\n");*/

	return;
}

void gogo(int endX, int endY)
{
	updatePola();
	Sleep(1000);
	int grid[27][27];
	for (int i = 0; i < 27; i++)
	{
		for (int j = 0; j < 27; j++)
		{
			grid[i][j] = 0;
		}
	}
	Pair src = make_pair(pozycjaTraktoraX, pozycjaTraktoraY);
	Pair dest = make_pair(endX, endY);
	aStarSearch(grid, src, dest);

}

void test1()
{
	pole[1][3][0] = 'B';
	pole[1][3][1] = '9';
	pole[3][1][0] = 'Z';
	pole[3][1][1] = '9';

	kod_genetyczny[1][3] = przypiszKod("buraki");
	kod_genetyczny[3][1] = przypiszKod("ziemniaki");
}
void test2()
{
	for (int i = 1; i < 26; i++)
	{
		for (int j = 1; j < i; j++)
		{
			pole[i][j][0] = 'B';
			pole[i][j][1] = '9';

			kod_genetyczny[i][j] = przypiszKod("buraki");
		}
	}
	test1();
	updatePola();
}

void testSI1()
{
	for (int i = 1; i < 26; i++)
	{
		for (int j = 1; j < 26; j++)
		{
			if (j % 3 == 0)
			{
				pole[i][j][2] = 'z';	//zyzne
				pole[i][j][3] = 'n';	//nawodnione
				pole[i][j][4] = 'c';	//w cieniu
				pole[i][j][5] = 'k';	//kwasne
			}
			else
			{
				if (j % 3 == 1)
				{
					pole[i][j][2] = 'j';	//jalowe
					pole[i][j][3] = 'n';	//nawodnione
					pole[i][j][4] = 's';	//w sloncu
					pole[i][j][5] = 'n';	//neutralne
				}
				else
				{
					pole[i][j][2] = 'z';	//zyzne
					pole[i][j][3] = 's';	//suche
					pole[i][j][4] = 's';	//sloneczne
					pole[i][j][5] = 'z';	//zasadowe
				}
			}
		}
	}
}

void sendState()
{
	ofstream write("dane.txt");
	for (int i = 1; i < 26; i++)
	{
		for (int j = 1; j < 26; j++)
		{
			string a;
			a += pole[i][j][2];
			a += ' ';
			a += pole[i][j][3];
			a += ' ';
			a += pole[i][j][4];
			a += ' ';
			a += pole[i][j][5];
			write << a << endl;
		}
	}
	write.close();
}
void reciveState()
{
	ifstream read("decyzje.txt");
	if (read.is_open())
	{
		char plant;
		int i = 1;
		int j = 1;
		while (read >> plant)
		{
			if (j == 25)
			{
				gogo(1, i + 1);
			}
			else
			{
				gogo(j + 1, i);
			}
			pole[i][j][0] = plant;

			przypiszKodGenetyczny(i, j, plant);

			if (plant == '.')
			{
				pole[i][j][1] = '1';
			}
			else
			{
				pole[i][j][1] = '9';
			}
			if (j == 25)
			{
				j = 1;
				i += 1;
			}
			else
			{
				j += 1;
			}


		}
	}
}

void start1()
{
	int goalX = 3, goalY = 4;
	test1();
	testSI1();
	pole[1][1][0] = 'T';
	pole[1][1][1] = '1';
	pole[goalY][goalX][0] = 'G';
	pole[goalY][goalX][1] = '9';
	gogo(goalX, goalY);
	gogo(goalX - 1, goalY);
	pole[goalY][goalX][0] = 'Z';
	pole[goalY][goalX][1] = '9';

	kod_genetyczny[goalY][goalX] = przypiszKod("ziemniaki");

	updatePola();


	//sendState();		//trzeba ręcznie zmieniać między wysyłaniem stanu a pobieraniem stanu pola
	reciveState();
}
void start2()
{
	int goalX = 6, goalY = 6;
	test2();
	pole[1][1][0] = 'T';
	pole[1][1][1] = '1';
	pole[goalY][goalX][0] = 'G';
	pole[goalY][goalX][1] = '9';
	gogo(goalX, goalY);
}
void start3()
{
	int goalX = 6, goalY = 9;
	test2();
	pole[1][1][0] = 'T';
	pole[1][1][1] = '1';
	pole[goalY][goalX][0] = 'G';
	pole[goalY][goalX][1] = '9';
	gogo(goalX, goalY);
}

int main()
{
	srand(time(0));

	SetWindow(50, 30);
	//create pola//
	for (int i = 0; i < 27; i++)
	{
		pole[i][0][0] = '#';
		pole[0][i][0] = '#';
		pole[26][i][0] = '#';
		pole[i][26][0] = '#';
		pole[i][0][1] = '9';
		pole[0][i][1] = '9';
		pole[26][i][1] = '9';
		pole[i][26][1] = '9';
	}
	for (int i = 1; i < 26; i++)
	{
		for (int j = 1; j < 26; j++)
		{
			pole[i][j][0] = '.';
			pole[i][j][1] = '1';
		}
	}

	for (int i = 0; i < 25; i++)
	{
		pole[i + 1][i + 1][0] = 'B';
		pole[i + 1][i + 1][1] = '9';
	}

	for (int i = 0; i < 25; i++) {
		for (int j = 0; j < 10; j++) {
			pole[j + 1][i + 1][0] = 'B';
			pole[j + 1][i + 1][1] = '9';
		}
	}
	for (int i = 0; i < 25; i++) {
		for (int j = 10; j < 20; j++) {
			pole[j + 1][i + 1][0] = 'Z';
			pole[j + 1][i + 1][1] = '9';
		}
	}

	generujKody();

	updatePola();

	start1();  // testy start 1-3

	//---------start---------//
	bool traktorDziala = true;

	char akcja;

	do
	{
		akcja = _getch();
		if (akcja == 'w' || akcja == 's' || akcja == 'a' || akcja == 'd')
		{
			Move(akcja);
		}
		if (akcja == '0')
		{
			traktorDziala = false;
		}


	} while (traktorDziala);
	//---------end---------//

	return 0;
}