bool ContextFreeNewPathValidFunc(CvSelectionGroup* pSelectionGroup, int iFromX, int iFromY, int iToX, int iToY, int iFlags, bool isTerminus, bool bMoveTerminationChecksOnly, int iPathTurns, bool* pbToNodeInvalidity, bool* pbValidAsTerminus)
{
PROFILE_FUNC();
CvPlot* pFromPlot;
CvPlot* pToPlot;
PlayerTypes eOwner = pSelectionGroup->getHeadOwner();
pFromPlot = GC.getMapINLINE().plotSorenINLINE(iFromX,iFromY);
FAssert(pFromPlot != NULL);
pToPlot = GC.getMapINLINE().plotSorenINLINE(iToX, iToY);
FAssert(pToPlot != NULL);
if ( pbValidAsTerminus != NULL )
{
*pbValidAsTerminus = false;
}
if ( !bMoveTerminationChecksOnly )
{
switch(pSelectionGroup->getDomainType())
{
case DOMAIN_SEA:
{
PROFILE("pathValid domain sea");
#if 0
// Optimisation short-circuit some invalid pathing choices quickly
if (!pToPlot->isWater() && !pSelectionGroup->canMoveAllTerrain() && !pToPlot->isCanMoveSeaUnits())
{
if (!pToPlot->isCity())
{
return FALSE;
}
}
#endif
// Can't cross diagonally across 'land'
if (pFromPlot->isWater() && pToPlot->isWater())
{
if (!(GC.getMapINLINE().plotINLINE(pFromPlot->getX_INLINE(), pToPlot->getY_INLINE())->isWater()) && !(GC.getMapINLINE().plotINLINE(pToPlot->getX_INLINE(), pFromPlot->getY_INLINE())->isWater()))
{
if( !(pSelectionGroup->canMoveAllTerrain()) )
{
return FALSE;
}
}
}
}
break;
case DOMAIN_LAND:
if ( (iFlags & MOVE_NO_LAND_UNITS_ACROSS_WATER) != 0 && pToPlot->isWater() )
{
return FALSE;
}
break;
default:
break;
}
// Need to handle ZOCs
// ZOCs don't apply into cities of the unit owner
TeamTypes eTeam = pSelectionGroup->getHeadTeam();
if ( pToPlot->getPlotCity() == NULL || pToPlot->getPlotCity()->getTeam() != eTeam )
{
//Fort ZOC
PlayerTypes eDefender = pFromPlot->controlsAdjacentFort(eTeam);
if (eDefender != NO_PLAYER)
{
const CvPlot* pZoneOfControl = pFromPlot->isInFortControl(true, eDefender, eOwner);
const CvPlot* pForwardZoneOfControl = pToPlot->isInFortControl(true, eDefender, eOwner);
if (pZoneOfControl != NULL && pForwardZoneOfControl != NULL)
{
if (pZoneOfControl == pToPlot->isInFortControl(true, eDefender, eOwner, pZoneOfControl))
{
return false;
}
}
}
//City ZoC
if (pFromPlot->isInCityZoneOfControl(eOwner) && pToPlot->isInCityZoneOfControl(eOwner))
{
return false;
}
}
//Promotion ZoC
if (pFromPlot->isInUnitZoneOfControl(eOwner) && pToPlot->isInUnitZoneOfControl(eOwner))
{
return false;
}
}
if ( isTerminus )
{
// Need to prevent false failures when the terminal
// plot contains an enemy unit (and we don't have the flag to allow movement through enemies
// (which should not prevent attacking enemies in the terminal plot)
return true;
}
if ( pbValidAsTerminus != NULL )
{
*pbValidAsTerminus = true;
}
// KOSHLING MOD - none of the rest of the calculation depends on pFromPlot,
// so we can cache the results from one request for each pToPlot.
bool bCheckNonInvisibleDanger = !(iFlags & MOVE_IGNORE_DANGER) &&
pSelectionGroup->AI_isControlled() &&
bMoveTerminationChecksOnly &&
!(pSelectionGroup->canFight()) &&
!(pSelectionGroup->alwaysInvisible());
[COLOR="Red"] if (!GET_PLAYER(eOwner).isHuman())
{[/COLOR]
if ( bMoveTerminationChecksOnly && !bCheckNonInvisibleDanger )
{
return true;
}
unsigned int iEntityId = 0;
CheckSum(iEntityId, pSelectionGroup->getHeadUnit()->getID());
CheckSum(iEntityId, (int)eOwner);
CheckSum(iEntityId, iFlags);
bool bResult;
if ( !pToPlot->HaveCachedPathValidityResult( (void*)iEntityId, bCheckNonInvisibleDanger, bResult ) )
{
bResult = pathValidInternal(pToPlot, bCheckNonInvisibleDanger, pSelectionGroup, iFlags);
pToPlot->CachePathValidityResult( (void*)iEntityId, bCheckNonInvisibleDanger, bResult );
}
if ( !bCheckNonInvisibleDanger && pbToNodeInvalidity != NULL )
{
*pbToNodeInvalidity = !bResult;
}
return bResult;
[COLOR="Red"] }
else
{
bool bResult = pathValidInternal(pToPlot, bCheckNonInvisibleDanger, pSelectionGroup, iFlags);
return bResult;
}[/COLOR]
}