bool CvSelectionGroupAI::AI_tradeRoutes()
{
	PROFILE_FUNC();

	const IDInfo kEurope(getOwnerINLINE(), CvTradeRoute::EUROPE_CITY_ID);

	CvCity* pPlotCity = plot()->getPlotCity();
	CvPlayerAI& kOwner = GET_PLAYER(getOwnerINLINE());
	std::set<int>::iterator it;

	std::map<IDInfo, int> cityValues;

	std::vector<CvTradeRoute*> routes;
	std::vector<int> routeValues;

	std::vector<bool> yieldsDelivered(NUM_YIELD_TYPES, false);
	std::vector<bool> yieldsToUnload(NUM_YIELD_TYPES, false);
	std::vector<int> yieldsOnBoard(NUM_YIELD_TYPES, false);

	if (!isHuman() || (getAutomateType() == AUTOMATE_TRANSPORT_FULL))
	{
		std::vector<CvTradeRoute*> aiRoutes;
		kOwner.getTradeRoutes(aiRoutes);
		for (uint i = 0; i < aiRoutes.size(); ++i)
		{
			CvTradeRoute* pRoute = aiRoutes[i];

			// transport feeder - start - Nightinggale
			CvCity* pDestinationCity = ::getCity(pRoute->getDestinationCity());
			if (pDestinationCity != NULL && pDestinationCity->isAutoImportStopped(pRoute->getYield()))
			{
				// ignore trade routes where destination is using feeder service and is full
				continue;
			}
			// transport feeder - end - Nightinggale

			// traderoute fix - start - Nightinggale
			if (isHuman() && pRoute->getDestinationCity().eOwner != getOwnerINLINE())
			{
				// humans can't transport to allied cities with fully automated transports
				continue;
			}
			// traderoute fix - end - Nightinggale

			CvCity* pSourceCity = ::getCity(pRoute->getSourceCity());
			CvArea* pSourceWaterArea = pSourceCity->waterArea();
			if ((pSourceCity != NULL) && ((getDomainType() != DOMAIN_SEA) || (pSourceWaterArea != NULL)))
			{
				int iSourceArea = (getDomainType() == DOMAIN_SEA) ? pSourceWaterArea->getID() : pSourceCity->getArea();
				if (getDomainType() == DOMAIN_SEA ? plot()->isAdjacentToArea(iSourceArea) : (iSourceArea == getArea()))
				{
					if ((getDomainType() == DOMAIN_SEA) || (pRoute->getDestinationCity() != kEurope))
					{
						routes.push_back(pRoute);
						routeValues.push_back(0);

						yieldsDelivered[pRoute->getYield()] = true;

						if (pPlotCity != NULL && ::getCity(pRoute->getDestinationCity()) == pPlotCity)
						{
							yieldsToUnload[pRoute->getYield()] = true;
						}


						cityValues[pRoute->getSourceCity()] = 0;
						cityValues[pRoute->getDestinationCity()] = 0;
					}
				}
			}
		}
	}
	else
	{
		for (it = m_aTradeRoutes.begin(); it != m_aTradeRoutes.end(); ++it)
		{
			CvTradeRoute* pRoute = kOwner.getTradeRoute(*it);
			CvCity* pSourceCity = ::getCity(pRoute->getSourceCity());
			if (pSourceCity != NULL)
			{
				CvArea* pSourceWaterArea = pSourceCity->waterArea();
				if (getDomainType() != DOMAIN_SEA || pSourceWaterArea != NULL)
				{
					int iSourceArea = (getDomainType() == DOMAIN_SEA) ? pSourceWaterArea->getID() : pSourceCity->getArea();
					if (getDomainType() == DOMAIN_SEA ? plot()->isAdjacentToArea(iSourceArea) : (iSourceArea == getArea()))
					{
						if ((getDomainType() == DOMAIN_SEA) || (pRoute->getDestinationCity() != kEurope))
						{
							routes.push_back(pRoute);
							routeValues.push_back(0);

							yieldsDelivered[pRoute->getYield()] = true;

							if (pPlotCity != NULL && ::getCity(pRoute->getDestinationCity()) == pPlotCity)
							{
								yieldsToUnload[pRoute->getYield()] = true;
							}


							cityValues[pRoute->getSourceCity()] = 0;
							cityValues[pRoute->getDestinationCity()] = 0;
						}
					}
					else
					{
						FAssertMsg(false, "Unexpected : Unit can't run trade route it's assigned to");
					}

				}
			}
		}


	}

	if ((pPlotCity != NULL) && hasCargo())
	{
		std::vector<CvUnit*> units;

		//Unload everything which we should unload here, or can't unload anywhere...
		CLLNode<IDInfo>* pUnitNode = plot()->headUnitNode();
		while (pUnitNode != NULL)
		{
			CvUnit* pLoopUnit = ::getUnit(pUnitNode->m_data);
			pUnitNode = plot()->nextUnitNode(pUnitNode);

			if (pLoopUnit != NULL)
			{
				YieldTypes eYield = pLoopUnit->getYield();
				CvUnit* pTransport = pLoopUnit->getTransportUnit();

				if ((eYield != NO_YIELD) && pTransport != NULL && (yieldsToUnload[eYield] || !(yieldsDelivered[eYield])))
				{
					if (pTransport->getGroup() == this && pLoopUnit->canUnload())
					{
						units.push_back(pLoopUnit);
					}
				}
			}
		}

		for (uint i = 0; i < units.size(); ++i)
		{
			units[i]->unload();
		}
	}

	short aiYieldsLoaded[NUM_YIELD_TYPES];
	AI_getYieldsLoaded(aiYieldsLoaded);

	bool bNoCargo = true;
	for (int i = 0; i < NUM_YIELD_TYPES; ++i)
	{
		if (aiYieldsLoaded[i] > 0)
		{
			bNoCargo = false;
			break;
		}
	}

	if (!bNoCargo)
	{
		//We need to iterate over every destination city and see if we can unload.
		for (uint i = 0; i < routes.size(); ++i)
		{
			CvCity* pDestinationCity = ::getCity(routes[i]->getDestinationCity());
			if ((pDestinationCity == NULL) || (pDestinationCity != pPlotCity))
			{
				int iRouteValue = kOwner.AI_transferYieldValue(routes[i]->getDestinationCity(), routes[i]->getYield(), aiYieldsLoaded[routes[i]->getYield()]);

				if (iRouteValue > 0)
				{
					cityValues[routes[i]->getDestinationCity()] += iRouteValue;
					routeValues[i] += iRouteValue;
				}
			}
		}
	}

	//We need to iterate over every source city, and see if there's anything which needs moving to the respective destination city.
	//We apply some bias to the city we are presently at, but not too much - sometimes empty runs need to be made...
	//Basically this looks at the entire NEXT trade run (source-city to dest-city), with some bias given towards
	//starting it from pPlotCity as sourceCity.
	//If we are carrying cargo, only count cities where we can unload.
	for (uint i = 0; i < routes.size(); ++i)
	{
		CvCity* pSourceCity = ::getCity(routes[i]->getSourceCity());

		if ((pSourceCity != NULL) && (bNoCargo || (cityValues[routes[i]->getSourceCity()] > 0)))
		{
			CvCity* pDestinationCity = ::getCity(routes[i]->getDestinationCity());
			YieldTypes eYield = routes[i]->getYield();

			// transport feeder - start - Nightinggale
			//int iAmount = pSourceCity->getYieldStored(eYield) - pSourceCity->getMaintainLevel(eYield);
			int iAmount = pSourceCity->getYieldStored(eYield) - pSourceCity->getAutoMaintainThreshold(eYield);
			// transport feeder - end - Nightinggale

			if (iAmount > 0)
			{

				int iExportValue = kOwner.AI_transferYieldValue(routes[i]->getSourceCity(), routes[i]->getYield(), -iAmount);
				int iImportValue = kOwner.AI_transferYieldValue(routes[i]->getDestinationCity(), routes[i]->getYield(), iAmount);
				int iRouteValue = (iExportValue + iImportValue + 2 * std::min(iExportValue, iImportValue)) / 4;

				if (pSourceCity == pPlotCity)
				{
					cityValues[routes[i]->getDestinationCity()] += 2 * iRouteValue;
				}
				else
				{
					cityValues[routes[i]->getSourceCity()] += iRouteValue;
				}

				routeValues[i] = iRouteValue;
			}
		}
	}

	IDInfo kBestDestination(NO_PLAYER, -1);
	int iBestDestinationValue = 0;

	for (std::map<IDInfo, int>::iterator it = cityValues.begin(); it != cityValues.end(); ++it)
	{
		int iValue = it->second;

		if (iValue > 0)
		{
			CvCity* pCity = ::getCity(it->first);
			if (pCity != NULL)
			{
				FAssert(!atPlot(pCity->plot()));
				if (generatePath(plot(), pCity->plot(), MOVE_NO_ENEMY_TERRITORY, true))
				{
					iValue /= 1 + kOwner.AI_plotTargetMissionAIs(pCity->plot(), MISSIONAI_TRANSPORT, this, 0);
				}
				else
				{
					iValue = 0;
				}
			}

			if (iValue > iBestDestinationValue)
			{
				iBestDestinationValue = iValue;
				kBestDestination = it->first;
			}
		}
	}


	if ((pPlotCity != NULL) && (kBestDestination.eOwner != NO_PLAYER))
	{
		//We need to keep looping and recalculating
		//For example a city might have "101" of an item, we want to move the first 100 but not the 1.
		//But it could also have 200, in which case we might want 2 loads of 100...
		//But it could also have 200 of two resources, and we'd want to move 100 of each...
		///TKs MEd
		int iTestCount = 0;
		while (!isFull())
		{
		    iTestCount++;
		    if (iTestCount == 1000)
		    {
		        FAssert(iTestCount == 0);
		        int iID = pPlotCity->getID();
		        int iIDplayer = GET_PLAYER(kBestDestination.eOwner).getID();
		       // break;
		    }

		    if (iTestCount == 1001)
		    {
		        break;
		    }
		    ///TKe
			int iBestRoute = -1;
			int iBestRouteValue = 0;
			//Now, for any trade routes which this group is assigned to, try to pick up cargo here.
			for (uint i = 0; i < routes.size(); ++i)
			{
				CvCity* pSourceCity = ::getCity(routes[i]->getSourceCity());
				if ((pSourceCity != NULL) && (routes[i]->getDestinationCity() == kBestDestination))
				{
					CvCity* pDestinationCity = ::getCity(routes[i]->getDestinationCity());
					YieldTypes eYield = routes[i]->getYield();

					if ((pPlotCity == pSourceCity))
					{
						// transport feeder - start - Nightinggale
						//int iAmount = pSourceCity->getYieldStored(eYield) - pSourceCity->getMaintainLevel(eYield);
						int iAmount = pSourceCity->getYieldStored(eYield) - pSourceCity->getAutoMaintainThreshold(eYield);
						// transport feeder - end - Nightinggale

						if (iAmount > 0)
						{
							int iExportValue = kOwner.AI_transferYieldValue(routes[i]->getSourceCity(), routes[i]->getYield(), -iAmount);
							int iImportValue = kOwner.AI_transferYieldValue(routes[i]->getDestinationCity(), routes[i]->getYield(), iAmount);
							int iRouteValue = (iExportValue + iImportValue + 2 * std::min(iExportValue, iImportValue)) / 4;

							if (iRouteValue > iBestRouteValue)
							{
								iBestRouteValue = iRouteValue;
								iBestRoute = i;
							}
						}
					}
				}
			}

			if (iBestRouteValue > 0)
			{
				CLLNode<IDInfo>* pUnitNode = headUnitNode();
				while (pUnitNode != NULL)
				{
					CvUnit* pLoopUnit = ::getUnit(pUnitNode->m_data);
					pUnitNode = nextUnitNode(pUnitNode);

					if (pLoopUnit != NULL)
					{
						if (pLoopUnit->canLoadYield(plot(), routes[iBestRoute]->getYield(), false))
						{
							pLoopUnit->loadYield(routes[iBestRoute]->getYield(), false);
							break;
						}
					}
				}
			}
			else
			{
				break;
			}
		}
		//XXX fill hold.
	}

	if ((kBestDestination.eOwner == NO_PLAYER) && hasCargo())
	{
		// Transport group is full and can't find any destination
		CvCity* pCity = kOwner.AI_findBestPort();
		if (pCity != NULL && !atPlot(pCity->plot()))
		{
			kBestDestination = pCity->getIDInfo();
		}
	}

	//As a final step, we could consider loading yields which would be useful as parts of delivery runs...
	if (kBestDestination != kEurope)
	{
		CvCity* pBestDestinationCity = ::getCity(kBestDestination);
		if (pBestDestinationCity != NULL)
		{
			FAssert(!atPlot(pBestDestinationCity->plot()));
			pushMission(MISSION_MOVE_TO, pBestDestinationCity->getX_INLINE(), pBestDestinationCity->getY_INLINE(), MOVE_NO_ENEMY_TERRITORY, false, false, MISSIONAI_TRANSPORT, pBestDestinationCity->plot());
			if (atPlot(pBestDestinationCity->plot()))
			{
				//Unload any goods if required (we can always pick them back up if this is an i+e city).
				std::vector<CvUnit*> units;

				CLLNode<IDInfo>* pUnitNode = plot()->headUnitNode();
				CvUnit* pLoopUnit;
				while (pUnitNode != NULL)
				{
					pLoopUnit = ::getUnit(pUnitNode->m_data);
					pUnitNode = plot()->nextUnitNode(pUnitNode);
					YieldTypes eYield = pLoopUnit->getYield();

					if ((eYield != NO_YIELD) && pLoopUnit->isCargo())
					{
						if (pLoopUnit->getTransportUnit()->getGroup() == this && pLoopUnit->canUnload())
						{
							units.push_back(pLoopUnit);
						}
					}
				}
				for (uint i = 0; i < units.size(); ++i)
				{
					units[i]->unload();
				}
			}

			return true;
		}
	}
	else
	{
		if (isHuman())
		{
			getHeadUnit()->AI_setUnitAIState(UNITAI_STATE_SAIL);
		}
	}

	return false;
}