#include "stdafx.h"
#include "Structures.h"

sStackWorks::sStackWorks ()
{
	vLastN = -1;
	//pFirst = NULL;
	//pLast = NULL;
	vQ_PlacesWorks = 0;
	vLastN2 = -1;
}

bool sStackWorks::fCheckOccupiedPositions()
{
	for (vvi = 0; vvi < MAX_Q_PLACE_WORK; vvi++)
	{
		for (vvj = 0; vvj < vMassPlaceWork[vvi].vQ_PosWork; vvj++)
		{
			pPosWorkTest = &vMassPlaceWork[vvi].pPosWork[vvj];
			if (pPosWorkTest)
			{
				pPosWorkTest->vBusy = FALSE;
				if (pPosWorkTest->vBusy == FALSE &&
					!fNullUnit((unit)pPosWorkTest->pDataUnit)
					)
				{
					hGroupFarm = CreateGroup();
					GroupEnumUnitsInRange(hGroupFarm,
											pPosWorkTest->vPos.X,
											pPosWorkTest->vPos.Y,
											300,
											NULL);
					u = FirstOfGroup(hGroupFarm);
					vCheck = FALSE;
					while (u)
					{
						if (u == pPosWorkTest->pDataUnit->WhichUnit)
						{
							vCheck = TRUE;
							break;
						}
						GroupRemoveUnit(hGroupFarm,u);
						u = FirstOfGroup(hGroupFarm);
					}
					DestroyGroup(hGroupFarm);
					if (vCheck == FALSE)
					{
						pPosWorkTest->fClear();
					}
					else
					{
						hGroupFarm = CreateGroup();
						GroupEnumUnitsInRange(hGroupFarm,
												pPosWorkTest->vPos.X,
												pPosWorkTest->vPos.Y,
												fRadius_Unit(pPosWorkTest->pDataUnit->vId)//+
												//vMassPlaceWork[vvi].vDistanceWork
												,
												NULL);
						u = FirstOfGroup(hGroupFarm);
						DestroyGroup(hGroupFarm);
						if (u &&
							u != pPosWorkTest->pDataUnit->WhichUnit)
						{
							pPosWorkTest->vBusy = TRUE;
						}
					}
				}
			}
		}
	}
	return TRUE;
}

int sStackWorks::fCountingPosWorks ()
{
	vCount = 0;
	for (vvi = 0; vvi < MAX_Q_PLACE_WORK; vvi++)
	{
		for (vvj = 0; vvj < vMassPlaceWork[vvi].vQ_PosWork; vvj++)
		{
			pPosWorkTest = &vMassPlaceWork[vvi].pPosWork[vvj];
			if (pPosWorkTest)
			{
				if (pPosWorkTest->vBusy == FALSE)
				{
					vCount++;
				}
			}
		}
	}
	return vCount;
}

int sStackWorks::fGetPosHarvesting (DataUnit *pDataUnit)
{
	if (pDataUnit == NULL) return -1;
	for (vvi = 0; vvi < MAX_Q_PLACE_WORK; vvi++)
	{
		for (vvj = 0; vvj < vMassPlaceWork[vvi].vQ_PosWork; vvj++)
		{
			pPosWorkTest = &vMassPlaceWork[vvi].pPosWork[vvj];
			if (pPosWorkTest)
			{
				if (pPosWorkTest->pDataUnit == pDataUnit)
				{
					return pPosWorkTest->vPosHarvesting;
				}
			}
		}
	}
	return -1;
}

bool sStackWorks::fFullPosHarvest (DataUnit *pDataUnit)
{
	if (pDataUnit == NULL) return FALSE;
	pPlaceWorkTest = fGetPlaceWork(pDataUnit->WhichUnit);
	if (pPlaceWorkTest == NULL) return FALSE;
	for (vvj = 0; vvj < pPlaceWorkTest->vQ_PosWork; vvj++)
	{
		pPosWorkTest = &vMassPlaceWork[vvi].pPosWork[vvj];
		if (pPosWorkTest)
		{
			if (pPosWorkTest->vBusy == FALSE &&
				pPosWorkTest->vHarvest == FALSE)
			{
				return FALSE;
			}
		}
	}
	return TRUE;
}

int sStackWorks::fCountingPosWorksHarvest ()
{
	vCount = 0;
	for (vvi = 0; vvi < MAX_Q_PLACE_WORK; vvi++)
	{
		for (vvj = 0; vvj < vMassPlaceWork[vvi].vQ_PosWork; vvj++)
		{
			pPosWorkTest = &vMassPlaceWork[vvi].pPosWork[vvj];
			if (pPosWorkTest)
			{
				if (pPosWorkTest->vBusy == FALSE &&
					pPosWorkTest->vHarvest == TRUE)
				{
					vCount++;
				}
			}
		}
	}
	return vCount;
}

int sStackWorks::fCountingPosWorksHarvestToDataUnit (DataUnit *pDataUnit)
{
	if (pDataUnit == NULL) return -1;
	pPlaceWorkTest = fGetPlaceWork(pDataUnit->WhichUnit);
	if (pPlaceWorkTest == NULL) return -1;
	vCount = 0;
	for (vvj = 0; vvj < pPlaceWorkTest->vQ_PosWork; vvj++)
	{
		if (pPlaceWorkTest->pPosWork[vvj].vBusy == FALSE &&
			pPlaceWorkTest->pPosWork[vvj].vHarvest == TRUE)
		{
			vCount++;
		}
	}
	return vCount;
}

void sStackWorks::fPryOutPositions ()
{
	for (vvi = 0; vvi < MAX_Q_PLACE_WORK; vvi++)
	{
		for (vvj = 0; vvj < vMassPlaceWork[vvi].vQ_PosWork; vvj++)
		{
			pPosWorkTest = &vMassPlaceWork[vvi].pPosWork[vvj];
			if (pPosWorkTest)
			{
				pPosWorkTest->vGougedOut = FALSE;
			}
		}
	}
	for (vvi = 0; vvi < MAX_Q_PLACE_WORK; vvi++)
	{
		for (vvj = 0; vvj < vMassPlaceWork[vvi].vQ_PosWork; vvj++)
		{
			pPosWorkTest = &vMassPlaceWork[vvi].pPosWork[vvj];
			if (pPosWorkTest)
			{
				hGroupFarm = CreateGroup();
				GroupEnumUnitsInRange(hGroupFarm,
										pPosWorkTest->vPos.X,
										pPosWorkTest->vPos.Y,
										300,
										NULL);
				u = FirstOfGroup(hGroupFarm);
				vCheck = FALSE;
				while (u)
				{
					pDataUnitTest = fGetDataUnit(u);
					if (pDataUnitTest &&
						pDataUnitTest->vId != ID_UNIT_WORKER &&
						fRadius_Unit(pDataUnitTest->vId) >= fG(pDataUnitTest->LastCoordinates.X,pDataUnitTest->LastCoordinates.Y,pPosWorkTest->vPos.X,pPosWorkTest->vPos.Y))
					{
						vCheck = TRUE;
						break;
					}
					GroupRemoveUnit(hGroupFarm,u);
					u = FirstOfGroup(hGroupFarm);
				}
				DestroyGroup(hGroupFarm);
				if (vCheck == TRUE)
				{
					pPosWorkTest->vGougedOut = TRUE;
					continue;
				}
				for (vvo = 0; vvo < MAX_Q_PLACE_WORK; vvo++)
				{
					for (vvl = 0; vvl < vMassPlaceWork[vvo].vQ_PosWork; vvl++)
					{
						if (vvo == vvi && vvl == vvj)
						{
							continue;
						}
						pPosWorkTest2 = &vMassPlaceWork[vvo].pPosWork[vvl];
						if (pPosWorkTest2)
						{
							vG = fG(pPosWorkTest->vPos.X,
									pPosWorkTest->vPos.Y,
									pPosWorkTest2->vPos.X,
									pPosWorkTest2->vPos.Y);
							if (vG <= 42)
							{
								pPosWorkTest->vGougedOut = TRUE;
							}
						}
					}
				}
			}
		}
	}
}

bool sStackWorks::fCancellationWork (DataUnit *pDataUnit)
{
	if (pDataUnit == NULL) return FALSE;
	for (vvi = 0; vvi < MAX_Q_PLACE_WORK; vvi++)
	{
		for (vvj = 0; vvj < vMassPlaceWork[vvi].vQ_PosWork; vvj++)
		{
			pPosWorkTest = &vMassPlaceWork[vvi].pPosWork[vvj];
			if (pPosWorkTest)
			{
				if (pPosWorkTest->pDataUnit == pDataUnit)
				{
					pPosWorkTest->fClear();
					return TRUE;
				}
			}
		}
	}
	return FALSE;
}

int sStackWorks::fCheckDataUnitToPosWork (DataUnit *pDataUnit)
{
	if (pDataUnit == NULL) return 0;
	vG_Min = -1;
	vvi2 = -1;
	vvj2 = -1;
	for (vvi = 0; vvi < MAX_Q_PLACE_WORK; vvi++)
	{
		for (vvj = 0; vvj < vMassPlaceWork[vvi].vQ_PosWork; vvj++)
		{
			pPosWorkTest = &vMassPlaceWork[vvi].pPosWork[vvj];
			if (pPosWorkTest)
			{
				if (pPosWorkTest->pDataUnit == pDataUnit)
				{
					if (pPosWorkTest->vBusy == TRUE)
					{
						pPosWorkTest->fClear();
						pPosWorkTest->vBusy = TRUE;
						return 0;
					}
					vG = fG(pPosWorkTest->vPos.X,
							pPosWorkTest->vPos.Y,
							pDataUnit->LastCoordinates.X,
							pDataUnit->LastCoordinates.Y);
					if (vG_Min == -1 || vG_Min > vG)
					{
						vG_Min = vG;
						vvi2 = vvi;
						vvj2 = vvj;
					}
					if (vvi2 >= 0 && vvj2 >= 0)
					{
						pPosWorkTest2 = &vMassPlaceWork[vvi2].pPosWork[vvj2];
						if (pPosWorkTest2)
						{
							if (vG_Min <= vMassPlaceWork[vvi2].vDistanceWork)
							{
								pPosWorkTest2->pDataUnit = pDataUnit;
								pPosWorkTest2->vHarvest = TRUE;
								pPosWorkTest2->vG = vG_Min;
								return 1;
							}
							if (pDataUnit->Blinked == TRUE &&
								GetUnitState(pDataUnit->WhichUnit, UNIT_STATE_MANA) >= 1)
							{
								vOrder = ID_ORDER_BLINK;
							}
							else
							{
								vOrder = ID_ORDER_MOVE;
							}
							if (IssuePointOrderById(pDataUnit->WhichUnit,
													vOrder,
													pPosWorkTest2->vPos.X,
													pPosWorkTest2->vPos.Y) == TRUE)
							{
								return 2;
							}
						}
					}
					return 3;
				}
			}
		}
	}
	return 0;
}

int sStackWorks::fGoNearestPlaceWork (DataUnit *pDataUnit)
{
	if (pDataUnit == NULL) return 0;
	if (GetUnitTypeId(pDataUnit->WhichUnit) == 0) return 1;
	vResult = -1;
	vResult = fCheckDataUnitToPosWork(pDataUnit);
	if (vResult == 1)
	{
		return 1;
	}
	else if (vResult == 2)
	{
		return 2;
	}
	vG_Min = -1;
	vvi2 = -1;
	vvj2 = -1;
	for (vvi = 0; vvi < MAX_Q_PLACE_WORK; vvi++)
	{
		for (vvj = 0; vvj < vMassPlaceWork[vvi].vQ_PosWork; vvj++)
		{
			pPosWorkTest = &vMassPlaceWork[vvi].pPosWork[vvj];
			if (pPosWorkTest)
			{
				if (pPosWorkTest->vBusy == FALSE &&
					pPosWorkTest->vGougedOut == FALSE &&
					pPosWorkTest->vHarvest == FALSE &&
					pPosWorkTest->pDataUnit == NULL)
				{
					vG = fG(pPosWorkTest->vPos.X,
							pPosWorkTest->vPos.Y,
							pDataUnit->LastCoordinates.X,
							pDataUnit->LastCoordinates.Y);
					if (vG_Min == -1 || vG_Min > vG)
					{
						vG_Min = vG;
						vvi2 = vvi;
						vvj2 = vvj;
					}
					break;
				}
			}
		}
	}
	if (vvi2 != -1 && vvj2 != -1)
	{
		pPosWorkTest2 = &vMassPlaceWork[vvi2].pPosWork[vvj2];
		if (pPosWorkTest2)
		{
			if (vG_Min < pPosWorkTest->vG)
			{
				//ID_ORDER_DETONATE
				if (pPosWorkTest2->pDataUnit)
				{
					pPosWorkTest2->fClear();
				}
			}
			if (vvi2 >= 0 && vvj2 >= 0)
			{
				if (vG_Min <= vMassPlaceWork[vvi2].vDistanceWork)
				{
					pPosWorkTest2->pDataUnit = pDataUnit;
					pPosWorkTest2->vHarvest = TRUE;
					pPosWorkTest2->vG = vG_Min;
					return TRUE;
				}
				if (pDataUnit->Blinked == TRUE &&
					GetUnitState(pDataUnit->WhichUnit, UNIT_STATE_MANA) >= 1)
				{
					vOrder = ID_ORDER_BLINK;
				}
				else
				{
					vOrder = ID_ORDER_MOVE;
				}
				if (IssuePointOrderById(pDataUnit->WhichUnit,
										vOrder,
										pPosWorkTest2->vPos.X,
										pPosWorkTest2->vPos.Y) == TRUE)
				{
					pPosWorkTest2->pDataUnit = pDataUnit;
					return 2;
				}
			}
		}
	}
	return 0;
}

bool sStackWorks::fAddPlaceWork (int vType, int vTypeWood, DataUnit *pDataUnit)
{
	if (vType < 0 || vType > 5) return FALSE;
	if (vTypeWood < 0 || vTypeWood > 13) return FALSE;
	if (pDataUnit == NULL) return FALSE;
	if (GetUnitTypeId(pDataUnit->WhichUnit) == 0) return TRUE;
	if (fCheckUnit(pDataUnit->WhichUnit) == FALSE)
	{
		if (fDeletePlaceWork(pDataUnit) == FALSE) return FALSE;
	}
	pPlaceWorkTest = fNewPlaceWork();
	if (pPlaceWorkTest == NULL) return FALSE;
	pPlaceWorkTest->pDataUnit = pDataUnit;
	pPlaceWorkTest->vType = vType;
	pPlaceWorkTest->vTypeWood = vTypeWood;
	pPlaceWorkTest->vDistanceWork = fDistanceWork(pPlaceWorkTest->vType);
	pPlaceWorkTest->vRadiusUnit = fRadiusUnit(pPlaceWorkTest->vType);
	pPlaceWorkTest->fCreatePosWorks(pPlaceWorkTest->vTypeWood);
	fPryOutPositions();
	return TRUE;
}

real sStackWorks::fRadiusUnit (int vType)
{
	if (vType < 0 || vType > 5) return 0;
	if (vType == CONST_TYPE_PLACE_WORK_FOR_WORKER) return fRadius_Unit(ID_UNIT_WORKER);
	if (vType == CONST_TYPE_PLACE_WORK_FOR_TWO) return 32;
	if (vType == CONST_TYPE_PLACE_WORK_FOR_ONLY_SATYRS) return fRadius_Unit(ID_UNIT_SATYR);
	return 32;
}

real sStackWorks::fDistanceWork (int vType)
{
	if (vType < 0 || vType > 5) return 0;
	if (vType == CONST_TYPE_PLACE_WORK_FOR_WORKER) return CONST_PLUS_DISTANCE_FOR_WORKERS;
	if (vType == CONST_TYPE_PLACE_WORK_FOR_TWO) return 128;
	if (vType == CONST_TYPE_PLACE_WORK_FOR_ONLY_SATYRS) return CONST_PLUS_DISTANCE_FOR_SATYRS;
	return CONST_PLUS_DISTANCE_FOR_WORKERS_2;
}

bool sStackWorks::fDeletePlaceWork (DataUnit *pDataUnit)
{
	if (pDataUnit == NULL) return FALSE;
	for (vvi = 0; vvi < MAX_Q_PLACE_WORK; vvi++)
	{
		for (vvj = 0; vvj < vMassPlaceWork[vvi].vQ_PosWork; vvj++)
		{
			if (vMassPlaceWork[vvi].pDataUnit == pDataUnit &&
				vMassPlaceWork[vvi].fDeletePlaceWork() == TRUE)
			{
				return TRUE;
			}
		}
	}
	return FALSE;
}

bool sStackWorks::fCheckUnit(unit WhichUnit)
{
	if (vLastN < 0) return TRUE;
	for (vvi = 0; vvi <= vLastN; vvi++)
	{
		pPlaceWorkTest = fGetPlaceWork(vvi);
		if (pPlaceWorkTest &&
			pPlaceWorkTest->vBusy == TRUE &&
			pPlaceWorkTest->pDataUnit &&
			pPlaceWorkTest->pDataUnit->WhichUnit == WhichUnit)
		{
			return FALSE;
		}
	}
	return TRUE;
}

sPlaceWork * sStackWorks::fGetPlaceWork(unit WhichUnit)
{
	if (vLastN < 0) return NULL;
	for (vvi = 0; vvi <= vLastN; vvi++)
	{
		pPlaceWorkTest = fGetPlaceWork(vvi);
		if (pPlaceWorkTest &&
			pPlaceWorkTest->vBusy == TRUE &&
			pPlaceWorkTest->pDataUnit &&
			pPlaceWorkTest->pDataUnit->WhichUnit == WhichUnit)
		{
			return pPlaceWorkTest;
		}
	}
	return NULL;
}

sPlaceWork * sStackWorks::fGetPlaceWork (int vN_In)
{
	if (vN_In < 0 || vN_In >= MAX_Q_PLACE_WORK) return NULL;
	if (vN_In > vLastN) return NULL;
	return &vMassPlaceWork[vN_In];
}

sPlaceWork * sStackWorks::fNewPlaceWork()
{
	vNPlaceWork = fNFreePlaceWork();
	if (vNPlaceWork < 0 || vNPlaceWork >= MAX_Q_PLACE_WORK) return NULL;
	vMassPlaceWork[vNPlaceWork].fInit(this);
	vMassPlaceWork[vNPlaceWork].vBusy = TRUE;
	return &vMassPlaceWork[vNPlaceWork];
}

int sStackWorks::fNFreePlaceWork()
{
	if (vLastN >= MAX_Q_PLACE_WORK - 1)
	{
		vFree = TRUE;
		for (vvi = vLastN; vvi >= 0; vvi--)
		{
			if (vMassPlaceWork[vvi].vBusy == FALSE)
			{
				if (vFree == TRUE)
				{
					vLastN = vvi;
				}
				return vvi;
			}
			else
			{
				vFree = FALSE;
			}
		}
	}
	else
	{
		vLastN++;
		return vLastN;
	}
	return MAX_Q_PLACE_WORK;
}

bool sStackWorks::fDeletePosWork (DataUnit *pDataUnit)
{
	if (pDataUnit == NULL) return FALSE;
	for (vvi = 0; vvi < MAX_Q_POS_WORKS; vvi++)
	{
		if (vMassPosWork[vvi].pDataUnit == pDataUnit &&
			vMassPosWork[vvi].fDeletePosWork() == TRUE)
		{
			return TRUE;
		}
	}
	return FALSE;
}

bool sStackWorks::fDeletePosWork (int vN_In)
{
	if (vN_In < 0 || vN_In > vLastN2) return FALSE;
	if (vMassPosWork[vN_In].fDeletePosWork() == TRUE)
	{
		return TRUE;
	}
	return FALSE;
}

bool sStackWorks::fCheckUnitPosWork(unit WhichUnit)
{
	if (vLastN < 0) return TRUE;
	for (vvi = 0; vvi <= vLastN2; vvi++)
	{
		pPosWorkTest = fGetPosWork(vvi);
		if (pPosWorkTest &&
			pPosWorkTest->vBusy2 == TRUE &&
			pPosWorkTest->pDataUnit &&
			pPosWorkTest->pDataUnit->WhichUnit == WhichUnit)
		{
			return FALSE;
		}
	}
	return TRUE;
}

sPosWork * sStackWorks::fGetPosWork(unit WhichUnit)
{
	if (vLastN2 < 0) return NULL;
	for (vvi = 0; vvi <= vLastN2; vvi++)
	{
		pPosWorkTest = fGetPosWork(vvi);
		if (pPosWorkTest &&
			pPosWorkTest->vBusy2 == TRUE &&
			pPosWorkTest->pDataUnit &&
			pPosWorkTest->pDataUnit->WhichUnit == WhichUnit)
		{
			return pPosWorkTest;
		}
	}
	return NULL;
}

sPosWork * sStackWorks::fGetPosWork (int vN_In)
{
	if (vN_In < 0 || vN_In >= MAX_Q_POS_WORKS) return NULL;
	if (vN_In > vLastN2) return NULL;
	return &vMassPosWork[vN_In];
}

sPosWork * sStackWorks::fNewPosWork()
{
	vN2PosWork = fN2FreePosWork();
	if (vN2PosWork < 0 || vN2PosWork >= MAX_Q_POS_WORKS) return NULL;
	vMassPosWork[vN2PosWork].vBusy2 = TRUE;
	return &vMassPosWork[vN2PosWork];
}

int sStackWorks::fN2FreePosWork()
{
	if (vLastN2 >= MAX_Q_POS_WORKS - 1)
	{
		vFree = TRUE;
		for (vvi = vLastN2; vvi >= 0; vvi--)
		{
			if (vMassPosWork[vvi].vBusy2 == FALSE)
			{
				if (vFree == TRUE)
				{
					vLastN2 = vvi;
				}
				return vvi;
			}
			else
			{
				vFree = FALSE;
			}
		}
	}
	else
	{
		vLastN2++;
		return vLastN2;
	}
	return MAX_Q_POS_WORKS;
}

sPlaceWork::sPlaceWork ()
{
	vBusy = FALSE;
	vType = -1;
	vTypeWood = -1;
	pDataUnit = NULL;
	vDistanceWork = 0;
	vRadiusUnit = 0;
	//pPosWork = NULL;
	vQ_PosWork = 0;
	vQ_PosWorkHarvest = 0;
	vQ_PosWorkSide = 0;
	vLastN = -1;
}

void sPlaceWork::fInit (sStackWorks_Type * pStackWorks2)
{
	if (pStackWorks2 == NULL) return;
	pStackWorks = pStackWorks2;
	pPosWork.fInit(this);
	//vPosWorkArray.fInit(this);
	//pPosWork = &pStackWorks2->vMassPosWork[0];
}

sPlaceWork::~sPlaceWork ()
{
	pStackWorks = NULL;
	pDataUnit = NULL;
	/*for (vvi = 0; vvi < vQ_PosWork; vvi++)
	{
		pPosWork[vvi].~sPosWork();
	}*/
	//free(pPosWork);//delete pPosWork;
	//delete[] pPosWork;
	//pPosWork = NULL;
}

bool sPlaceWork::fCopy (sPlaceWork * vPlaceWork)
{
	if (vPlaceWork == NULL) return FALSE;
	vBusy = vPlaceWork->vBusy;
	vType = vPlaceWork->vType;
	vTypeWood = vPlaceWork->vTypeWood;
	pDataUnit = vPlaceWork->pDataUnit;
	vDistanceWork = vPlaceWork->vDistanceWork;
	vRadiusUnit = vPlaceWork->vRadiusUnit;
	pPosWork = vPlaceWork->pPosWork;
	vQ_PosWork = vPlaceWork->vQ_PosWork;
	vQ_PosWorkHarvest = vPlaceWork->vQ_PosWorkHarvest;
	vQ_PosWorkSide = vPlaceWork->vQ_PosWorkSide;
	return TRUE;
}

bool sPlaceWork::fCreatePosWorks (int vTypeWood)
{
	if (vType < 0 || vType > 5) return FALSE;
	if (vRadiusUnit <= 0) return FALSE;
	if (vDistanceWork <= 0) return FALSE;
	if (vTypeWood < 0 || vTypeWood > 13) return FALSE;
	switch (vType)
	{
	case CONST_TYPE_PLACE_WORK_FOR_WORKER:
	case CONST_TYPE_PLACE_WORK_FOR_WORKER_AND_FURBOLGS:
	case CONST_TYPE_PLACE_WORK_FOR_FANG_AND_FIRE_SPAWN:
	case CONST_TYPE_PLACE_WORK_FOR_FIRE_SPAWN_SATIR:
		vQ_PosWorkSide = (int)((CONST_SIDE-(vRadiusUnit*2))/((vRadiusUnit*2)+vDistanceWork)+1);
		switch (vTypeWood)
		{
		case CONST_TYPE_WOOD_PLACE_WORK_TOP:
		case CONST_TYPE_WOOD_PLACE_WORK_LEFT:
		case CONST_TYPE_WOOD_PLACE_WORK_BOTTOM:
		case CONST_TYPE_WOOD_PLACE_WORK_RIGHT:
			vQ_PosWork = vQ_PosWorkSide;
			break;
		case CONST_TYPE_WOOD_PLACE_WORK_TOP_LEFT:
		case CONST_TYPE_WOOD_PLACE_WORK_TOP_RIGHT:
		case CONST_TYPE_WOOD_PLACE_WORK_LEFT_BOTTOM:
		case CONST_TYPE_WOOD_PLACE_WORK_BOTTOM_RIGHT:
			vQ_PosWork = vQ_PosWorkSide + vQ_PosWorkSide - 1;
			break;
		case CONST_TYPE_WOOD_PLACE_WORK_TOP_BOTTOM:
		case CONST_TYPE_WOOD_PLACE_WORK_LEFT_RIGHT:
			vQ_PosWork = vQ_PosWorkSide + vQ_PosWorkSide;
			break;
		case CONST_TYPE_WOOD_PLACE_WORK_TOP_RIGHT_BOTTOM:
		case CONST_TYPE_WOOD_PLACE_WORK_RIGHT_BOTTOM_LEFT:
		case CONST_TYPE_WOOD_PLACE_WORK_BOTTOM_LEFT_TOP:
		case CONST_TYPE_WOOD_PLACE_WORK_LEFT_TOP_RIGHT:
			vQ_PosWork = vQ_PosWorkSide + (vQ_PosWorkSide - 1) * 2;
			break;
		default:
			return FALSE;
		}
		//pPosWork = (sPosWork*) malloc(sizeof(sPosWork)*vQ_PosWork);//new sPosWork[vQ_PosWork];
		//pPosWork = new sPosWork[vQ_PosWork];
		if (fNewPosWork(vQ_PosWork) == FALSE) return FALSE;
		/*for (vvi = 0; vvi < vQ_PosWork; vvi++)
		{
			pPosWork[vvi].sPosWork::sPosWork();
		}*/
		if (pPosWork.size() == NULL) return FALSE;
		vTemp_Q = 0;
m1:;
		if (vTemp_Q >= vQ_PosWork) goto m2;
		vvj = vTemp_Q;
		switch (vTypeWood)
		{
		case CONST_TYPE_WOOD_PLACE_WORK_TOP:
			vvn = CONST_TYPE_WOOD_PLACE_WORK_TOP;
			vvz = 0;
			break;
		case CONST_TYPE_WOOD_PLACE_WORK_LEFT:
			vvn = CONST_TYPE_WOOD_PLACE_WORK_LEFT;
			vvz = 0;
			break;
		case CONST_TYPE_WOOD_PLACE_WORK_BOTTOM:
			vvn = CONST_TYPE_WOOD_PLACE_WORK_BOTTOM;
			vvz = 0;
			break;
		case CONST_TYPE_WOOD_PLACE_WORK_RIGHT:
			vvn = CONST_TYPE_WOOD_PLACE_WORK_RIGHT;
			vvz = 0;
			break;
		case CONST_TYPE_WOOD_PLACE_WORK_TOP_LEFT:
			if (vTemp_Q == 0)
			{
				vvn = CONST_TYPE_WOOD_PLACE_WORK_LEFT;
				vvz = 0;
			}
			else if (vTemp_Q == vQ_PosWorkSide)
			{
				vvn = CONST_TYPE_WOOD_PLACE_WORK_TOP;
				vvz = 1;
			}
			break;
		case CONST_TYPE_WOOD_PLACE_WORK_TOP_RIGHT:
			if (vTemp_Q == 0)
			{
				vvn = CONST_TYPE_WOOD_PLACE_WORK_TOP;
				vvz = 0;
			}
			else if (vTemp_Q == vQ_PosWorkSide)
			{
				vvn = CONST_TYPE_WOOD_PLACE_WORK_RIGHT;
				vvz = 1;
			}
			break;
		case CONST_TYPE_WOOD_PLACE_WORK_TOP_BOTTOM:
			if (vTemp_Q == 0)
			{
				vvn = CONST_TYPE_WOOD_PLACE_WORK_TOP;
				vvz = 0;
			}
			else if (vTemp_Q == vQ_PosWorkSide)
			{
				vvn = CONST_TYPE_WOOD_PLACE_WORK_BOTTOM;
				vvz = 0;
			}
			break;
		case CONST_TYPE_WOOD_PLACE_WORK_LEFT_RIGHT:
			if (vTemp_Q == 0)
			{
				vvn = CONST_TYPE_WOOD_PLACE_WORK_LEFT;
				vvz = 0;
			}
			else if (vTemp_Q == vQ_PosWorkSide)
			{
				vvn = CONST_TYPE_WOOD_PLACE_WORK_RIGHT;
				vvz = 0;
			}
			break;
		case CONST_TYPE_WOOD_PLACE_WORK_LEFT_BOTTOM:
			if (vTemp_Q == 0)
			{
				vvn = CONST_TYPE_WOOD_PLACE_WORK_BOTTOM;
				vvz = 0;
			}
			else if (vTemp_Q == vQ_PosWorkSide)
			{
				vvn = CONST_TYPE_WOOD_PLACE_WORK_LEFT;
				vvz = 1;
			}
			break;
		case CONST_TYPE_WOOD_PLACE_WORK_BOTTOM_RIGHT:
			if (vTemp_Q == 0)
			{
				vvn = CONST_TYPE_WOOD_PLACE_WORK_RIGHT;
				vvz = 0;
			}
			else if (vTemp_Q == vQ_PosWorkSide)
			{
				vvn = CONST_TYPE_WOOD_PLACE_WORK_BOTTOM;
				vvz = 1;
			}
			break;
		case CONST_TYPE_WOOD_PLACE_WORK_TOP_RIGHT_BOTTOM:
			if (vTemp_Q == 0)
			{
				vvn = CONST_TYPE_WOOD_PLACE_WORK_TOP;
				vvz = 0;
			}
			else if (vTemp_Q == vQ_PosWorkSide)
			{
				vvn = CONST_TYPE_WOOD_PLACE_WORK_RIGHT;
				vvz = 1;
			}
			else if (vTemp_Q == vQ_PosWorkSide + vQ_PosWorkSide - 1)
			{
				vvn = CONST_TYPE_WOOD_PLACE_WORK_BOTTOM;
				vvz = 1;
			}
			break;
		case CONST_TYPE_WOOD_PLACE_WORK_RIGHT_BOTTOM_LEFT:
			if (vTemp_Q == 0)
			{
				vvn = CONST_TYPE_WOOD_PLACE_WORK_RIGHT;
				vvz = 0;
			}
			else if (vTemp_Q == vQ_PosWorkSide)
			{
				vvn = CONST_TYPE_WOOD_PLACE_WORK_BOTTOM;
				vvz = 1;
			}
			else if (vTemp_Q == vQ_PosWorkSide + vQ_PosWorkSide - 1)
			{
				vvn = CONST_TYPE_WOOD_PLACE_WORK_LEFT;
				vvz = 1;
			}
			break;
		case CONST_TYPE_WOOD_PLACE_WORK_BOTTOM_LEFT_TOP:
			if (vTemp_Q == 0)
			{
				vvn = CONST_TYPE_WOOD_PLACE_WORK_BOTTOM;
				vvz = 0;
			}
			else if (vTemp_Q == vQ_PosWorkSide)
			{
				vvn = CONST_TYPE_WOOD_PLACE_WORK_LEFT;
				vvz = 1;
			}
			else if (vTemp_Q == vQ_PosWorkSide + vQ_PosWorkSide - 1)
			{
				vvn = CONST_TYPE_WOOD_PLACE_WORK_TOP;
				vvz = 1;
			}
			break;
		case CONST_TYPE_WOOD_PLACE_WORK_LEFT_TOP_RIGHT:
			if (vTemp_Q == 0)
			{
				vvn = CONST_TYPE_WOOD_PLACE_WORK_LEFT;
				vvz = 0;
			}
			else if (vTemp_Q == vQ_PosWorkSide)
			{
				vvn = CONST_TYPE_WOOD_PLACE_WORK_TOP;
				vvz = 1;
			}
			else if (vTemp_Q == vQ_PosWorkSide + vQ_PosWorkSide - 1)
			{
				vvn = CONST_TYPE_WOOD_PLACE_WORK_RIGHT;
				vvz = 1;
			}
			break;
		}
		switch (vvn)
		{
		case CONST_TYPE_WOOD_PLACE_WORK_TOP:
			for (vvi = vvz; vvi < vQ_PosWorkSide; vvi++)
			{
				pPosWork[vTemp_Q].vPos.X = pDataUnit->LastCoordinates.X - 128 + 16 + vRadiusUnit + vvi * ((vRadiusUnit * 2) + vDistanceWork);
				pPosWork[vTemp_Q].vPos.Y = pDataUnit->LastCoordinates.Y + 128 - 16 - vRadiusUnit;
				pPosWork[vTemp_Q].vPosHarvesting = fConverterI(pPosWork[vTemp_Q].vPos.X,pPosWork[vTemp_Q].vPos.Y);
				vTemp_Q++;
			}
			break;
		case CONST_TYPE_WOOD_PLACE_WORK_RIGHT:
			for (vvi = vvz; vvi < vQ_PosWorkSide; vvi++)
			{
				pPosWork[vTemp_Q].vPos.X = pDataUnit->LastCoordinates.X + 128 - 16 - vRadiusUnit;
				pPosWork[vTemp_Q].vPos.Y = pDataUnit->LastCoordinates.Y + 128 - 16 - vRadiusUnit - vvi * ((vRadiusUnit * 2) + vDistanceWork);
				pPosWork[vTemp_Q].vPosHarvesting = fConverterI(pPosWork[vTemp_Q].vPos.X,pPosWork[vTemp_Q].vPos.Y);
				vTemp_Q++;
			}
			break;
		case CONST_TYPE_WOOD_PLACE_WORK_BOTTOM:
			for (vvi = vvz; vvi < vQ_PosWorkSide; vvi++)
			{
				pPosWork[vTemp_Q].vPos.X = pDataUnit->LastCoordinates.X + 128 - 16 - vRadiusUnit - vvi * ((vRadiusUnit * 2) + vDistanceWork);
				pPosWork[vTemp_Q].vPos.Y = pDataUnit->LastCoordinates.Y - 128 + 16 + vRadiusUnit;
				pPosWork[vTemp_Q].vPosHarvesting = fConverterI(pPosWork[vTemp_Q].vPos.X,pPosWork[vTemp_Q].vPos.Y);
				vTemp_Q++;
			}
			break;
		case CONST_TYPE_WOOD_PLACE_WORK_LEFT:
			for (vvi = vvz; vvi < vQ_PosWorkSide; vvi++)
			{
				pPosWork[vTemp_Q].vPos.X = pDataUnit->LastCoordinates.X - 128 + 16 + vRadiusUnit;
				pPosWork[vTemp_Q].vPos.Y = pDataUnit->LastCoordinates.Y - 128 + 16 + vRadiusUnit + vvi * ((vRadiusUnit * 2) + vDistanceWork);
				pPosWork[vTemp_Q].vPosHarvesting = fConverterI(pPosWork[vTemp_Q].vPos.X,pPosWork[vTemp_Q].vPos.Y);
				vTemp_Q++;
			}
			break;
		}
		goto m1;
m2:;
		break;
	case CONST_TYPE_PLACE_WORK_FOR_TWO:
		vQ_PosWork = 2;
		//pPosWork = new sPosWork[vQ_PosWork];
		if (fNewPosWork(vQ_PosWork) == FALSE) return FALSE;
		if (pPosWork.size() == NULL) return FALSE;
		vTemp_Q = 0;
		switch (vTypeWood)
		{
		case CONST_TYPE_WOOD_PLACE_WORK_TOP:
			for (vvi = 0; vvi < vQ_PosWork; vvi++)
			{
				pPosWork[vTemp_Q].vPos.X = pDataUnit->LastCoordinates.X - 128 + 16 + vRadiusUnit + vvi * (128 + vRadiusUnit * 2);
				pPosWork[vTemp_Q].vPos.Y = pDataUnit->LastCoordinates.Y + 64 - 8 - vRadiusUnit;
				pPosWork[vTemp_Q].vPosHarvesting = fConverterI(pPosWork[vTemp_Q].vPos.X,pPosWork[vTemp_Q].vPos.Y);
				vTemp_Q++;
			}
			break;
		case CONST_TYPE_WOOD_PLACE_WORK_RIGHT:
			for (vvi = 0; vvi < vQ_PosWork; vvi++)
			{
				pPosWork[vTemp_Q].vPos.X = pDataUnit->LastCoordinates.X + 64 - 8 - vRadiusUnit;
				pPosWork[vTemp_Q].vPos.Y = pDataUnit->LastCoordinates.Y + 128 - 16 - vRadiusUnit - vvi * (128 + vRadiusUnit * 2);
				pPosWork[vTemp_Q].vPosHarvesting = fConverterI(pPosWork[vTemp_Q].vPos.X,pPosWork[vTemp_Q].vPos.Y);
				vTemp_Q++;
			}
			break;
		case CONST_TYPE_WOOD_PLACE_WORK_BOTTOM:
			for (vvi = 0; vvi < vQ_PosWork; vvi++)
			{
				pPosWork[vTemp_Q].vPos.X = pDataUnit->LastCoordinates.X + 128 - 16 - vRadiusUnit - vvi * (128 + vRadiusUnit * 2);
				pPosWork[vTemp_Q].vPos.Y = pDataUnit->LastCoordinates.Y - 64 + 8 + vRadiusUnit;
				pPosWork[vTemp_Q].vPosHarvesting = fConverterI(pPosWork[vTemp_Q].vPos.X,pPosWork[vTemp_Q].vPos.Y);
				vTemp_Q++;
			}
			break;
		case CONST_TYPE_WOOD_PLACE_WORK_LEFT:
			for (vvi = 0; vvi < vQ_PosWork; vvi++)
			{
				pPosWork[vTemp_Q].vPos.X = pDataUnit->LastCoordinates.X - 64 + 8 + vRadiusUnit;
				pPosWork[vTemp_Q].vPos.Y = pDataUnit->LastCoordinates.Y - 128 + 16 + vRadiusUnit + vvi * (128 + vRadiusUnit * 2);
				pPosWork[vTemp_Q].vPosHarvesting = fConverterI(pPosWork[vTemp_Q].vPos.X,pPosWork[vTemp_Q].vPos.Y);
				vTemp_Q++;
			}
			break;
		}
		break;
	case CONST_TYPE_PLACE_WORK_FOR_ONLY_SATYRS:
		vQ_PosWork = 6;
		//pPosWork = new sPosWork[vQ_PosWork];
		if (fNewPosWork(vQ_PosWork) == FALSE) return FALSE;
		if (pPosWork.size() == NULL) return FALSE;
		vTemp_Q = 0;
		for (vvi = 0; vvi < vQ_PosWork; vvi++)
		{
			switch (vvi)
			{
			case 0:
			case 1:
				pPosWork[vTemp_Q].vPos.X = pDataUnit->LastCoordinates.X - 64 + 8 + vRadiusUnit + (vvi - 0) * (64);
				pPosWork[vTemp_Q].vPos.Y = pDataUnit->LastCoordinates.Y + 64 + 8 + vRadiusUnit;
				break;
			case 2:
			case 3:
				pPosWork[vTemp_Q].vPos.X = pDataUnit->LastCoordinates.X + 64 + 8 + vRadiusUnit;
				pPosWork[vTemp_Q].vPos.Y = pDataUnit->LastCoordinates.Y + 64 - 8 - vRadiusUnit - (vvi - 2) * (64);
				break;
			case 4:
			case 5:
				pPosWork[vTemp_Q].vPos.X = pDataUnit->LastCoordinates.X + 64 - 8 - vRadiusUnit - (vvi - 4) * (64);
				pPosWork[vTemp_Q].vPos.Y = pDataUnit->LastCoordinates.Y - 64 - 8 - vRadiusUnit;
				break;
			case 6:
			case 7:
				pPosWork[vTemp_Q].vPos.X = pDataUnit->LastCoordinates.X - 64 - 8 - vRadiusUnit;
				pPosWork[vTemp_Q].vPos.Y = pDataUnit->LastCoordinates.Y - 64 + 8 + vRadiusUnit + (vvi - 6) * (64);
				break;
			}
			pPosWork[vTemp_Q].vPosHarvesting = fConverterI(pPosWork[vTemp_Q].vPos.X,pPosWork[vTemp_Q].vPos.Y);
			vTemp_Q++;
		}
		break;
	}
	return TRUE;
}

int sPlaceWork::fGetPosHarvesting (DataUnit *pDataUnit)
{
	if (pDataUnit == NULL) return -1;
	for (vvi = 0; vvi < vQ_PosWork; vvi++)
	{
		if (pPosWork[vvi].pDataUnit == pDataUnit)
		{
			return pPosWork[vvi].vPosHarvesting;
		}
	}
	return -1;
}

bool sPlaceWork::fDeletePlaceWork ()
{
	if (vBusy == FALSE) return FALSE;
	if (vQ_PosWork <= 0) return FALSE;
	vBusy = FALSE;
	vType = -1;
	vTypeWood = -1;
	pDataUnit = NULL;
	vDistanceWork = 0;
	/*for (vvi = 0; vvi < vQ_PosWork; vvi++)
	{
		pPosWork[vvi].pDataUnit = NULL;
		//ppPosWork[vvi]->pPlaceWork = NULL;
	}*/
	/*for (vvi = 0; vvi < vQ_PosWork; vvi++)
	{
		pPosWork[vvi].~sPosWork();
	}*/
	//free(pPosWork);//delete pPosWork;
	//delete[] pPosWork;
	//pPosWork = NULL;
	vQ_PosWork = 0;
}

sPosWork * sPlaceWork::fGetPosWork(int vN)
{
	if (vN < 0) return NULL;
	return pStackWorks->fGetPosWork(vMassNPosWork[vN]);
}

bool sPlaceWork::fDeletePosWork(int vN)
{
	if (vN < 0) return FALSE;
	pStackWorks->fDeletePosWork(vMassNPosWork[vN]);
	vMassNPosWork[vN] = -1;
	while (vLastN >= 0)
	{
		if (vMassNPosWork[vLastN] == -1)
		{
			vLastN--;
		}
		else
		{
			break;
		}
	}
	return TRUE;
}

bool sPlaceWork::fNewPosWork(int vQ)
{
	if (vQ < 0 || vQ > MAX_Q_POS_WORKS || vQ > MAX_Q_POS_WORKS - vLastN + 1) return FALSE;
	for (vvi = 0; vvi < vQ; vvi++)
	{
		if (fNewPosWork() == FALSE) return FALSE;
	}
	return TRUE;
}

bool sPlaceWork::fNewPosWork()
{
	pPosWorkTest = pStackWorks->fNewPosWork();
	if (pPosWorkTest == NULL) return FALSE;
	vNPosWork = fNFreePosWork();
	if (vNPosWork < 0 || vNPosWork >= MAX_Q_POS_WORKS) return FALSE;
	pPosWorkTest->fInit(this);
	vMassNPosWork[vNPosWork] = pStackWorks->vLastN2;
	return TRUE;
}

int sPlaceWork::fNFreePosWork()
{
	if (vLastN >= MAX_Q_POS_WORKS - 1)
	{
		vFree = TRUE;
		for (vvi = vLastN; vvi >= 0; vvi--)
		{
			if (vMassNPosWork[vvi] == -1)
			{
				if (vFree == TRUE)
				{
					vLastN = vvi;
				}
				return vvi;
			}
			else
			{
				vFree = FALSE;
			}
		}
	}
	else
	{
		vLastN++;
		return vLastN;
	}
	return MAX_Q_POS_WORKS;
}

sPosWork::sPosWork()
{
	pDataUnit = NULL;
	vPos.X = 0;
	vPos.Y = 0;
	vPosHarvesting = 0;
	vBusy = FALSE;
	vHarvest = FALSE;
	vG = -1;
	vGougedOut = FALSE;
	vN = -1;
}

void sPosWork::fInit (sPlaceWork_Type * pPlaceWork2)
{
	if (pPlaceWork2 == NULL) return;
	pPlaceWork = pPlaceWork2;
}

void sPosWork::fClear ()
{
	pDataUnit = NULL;
	vBusy = FALSE;
	vHarvest = FALSE;
	vG = -1;
}

sPosWork::~sPosWork ()
{
	pPlaceWork = NULL;
	pDataUnit = NULL;
}

bool sPosWork::fNewPosWork()
{
	if (vBusy2 == TRUE) return FALSE;
	vBusy2 = TRUE;
	return TRUE;
}

bool sPosWork::fDeletePosWork()
{
	if (vBusy2 == FALSE) return FALSE;
	vBusy2 = FALSE;
	return TRUE;
}

/*void* sPosWork::operator new(size_t size)
{
	return ::operator new(size);
}

void sPosWork::operator delete(void* ptr)
{
    return ::operator delete(ptr);
}

void* sPosWork::operator new[](size_t size)
{
    return ::operator new[](size);
}

void sPosWork::operator delete[](void* ptr)
{
    return ::operator delete[](ptr);
}*/

bool sPosWork::fCopy (sPosWork * pPosWork)
{
	if (pPosWork == NULL) return FALSE;
	pDataUnit = pPosWork->pDataUnit;
	pPlaceWork = pPosWork->pPlaceWork;
	vBusy = pPosWork->vBusy;
	vBusy2 = pPosWork->vBusy2;
	vG = pPosWork->vG;
	vGougedOut = pPosWork->vGougedOut;
	vHarvest = pPosWork->vHarvest;
	vN = pPosWork->vN;
	vPos.X = pPosWork->vPos.X;
	vPos.Y = pPosWork->vPos.Y;
	vPosHarvesting = pPosWork->vPosHarvesting;
	return TRUE;
}

sPosWorkArray::~sPosWorkArray()
{
	//delete[]arr;
	//arr = NULL;
	pPlaceWork = NULL;
}
 
sPosWorkArray::sPosWorkArray(const unsigned size):m_size(size)
{
	//arr = NULL;
	pPlaceWork = NULL;
	if (!size)
	{
		//arr = new sPosWork_Type[1];
	}
	else
	{
		//arr = new sPosWork_Type[size];
	}
}

sPosWorkArray::sPosWork_Type& sPosWorkArray::operator[](const int index)
{
	return *fGet(index);
}

unsigned sPosWorkArray::size() const
{
	return pPlaceWork->vQ_PosWork;
}

void sPosWorkArray::fInit (sPlaceWork_Type * pPlaceWork2)
{
	if (pPlaceWork2 == NULL) return;
	pPlaceWork = pPlaceWork2;
}

sPosWorkArray::sPosWork_Type * sPosWorkArray::fGet( int i )
{
	if (pPlaceWork == NULL) return NULL;
	return pPlaceWork->fGetPosWork(i);
}