How to forbid diagonal move?

Inyah

Chieftain
Joined
Jan 28, 2012
Messages
48
hi experts,

i am trying to make a mod where seeunits can move on rivers (rivermasks). It actually works, including river-side-cities producing seeunits. Now I am trying to make the units stick to the flow of the river and not being able to take shortcuts by going diagonal (so basically only allowing the units to go north, east, west and south and not northeast etc.). Can someone give me a hint on how to do this? This is what I got (in "unitcanmoveinto" at cvUnit.cpp):

Spoiler :
switch (getDomainType())
{
case DOMAIN_SEA:
// River Mod start
if (pPlot->isRiverMask() == true || pPlot->isFriendlyCity(*this, true))

{
return true;
break;
}

else
{
//River Mod end
if (!pPlot->isWater() && !canMoveAllTerrain())
{
if (!pPlot->isFriendlyCity(*this, true) ||!pPlot->isCoastalLand())
{
return false;
}

}
}
break;


I was thinking about adding something like this:

Spoiler :

if (pPlot->isRiverMask() == true || pPlot->isFriendlyCity(*this, true))
{
if (plotDirection == DIRECTION_NORTH)
{
return true;
}

if (plotDirektion == DIRECTION_SOUTHEAST)
{
return false;
} //etc.

break;
}



but i dont know how to get that direction. And I am not sure, if that would actually work, if then the program would understand to take the longer path via south and then east. (forgive my poor english, hope you can still understand what I mean...)

Any ideas for this? :)
 
Since I don't do SDK, I can only give you in pesudo code form.

Add another if statement to check:
If newplot.getX() == oldplot.getX() or newplot.getY() == oldplot.getY():

Since moving left/right or up/down means either the X or the Y has to be the same
 
Since I don't do SDK, I can only give you in pesudo code form.

Add another if statement to check:
If newplot.getX() == oldplot.getX() or newplot.getY() == oldplot.getY():

Since moving left/right or up/down means either the X or the Y has to be the same

thanx - it helped. I did manage to forbid diagonal moves, but now the game isnt able to find a path to a distant plot, so I have to move the ships plotbyplot. well - taking it step by step :)

if anyone is interested in the solution - its quite simple:
Spoiler :

if ((pPlot->getX_INLINE() == plot()->getX_INLINE()) || (pPlot->getY_INLINE() == plot()->getY_INLINE()))
{
return true;
}

else
{
return false;
}
 
The path finding algorithm uses a few functions in CvGameCoreUtils.cpp:
pathValid(), pathDestValid() and a few more.
(You can see them being passed to the algorithm in CvMap::setup())

Try debugging them and see where it fails.
 
The path finding algorithm uses a few functions in CvGameCoreUtils.cpp:
pathValid(), pathDestValid() and a few more.
(You can see them being passed to the algorithm in CvMap::setup())

Try debugging them and see where it fails.

thanks for those functions. I tried a bit, but those are real tough ones. I cannot seem to find any way to tell the game to check if moving east and then north to get to northeast is a valid option. Somehow it doesnt seem to even consider that option but just breaks the path (or sometimes worse: just keeps moving between two tiles back and forth). If anyone has any ideas - I would be grateful.
 
Well, I see a basic problem with your implementation (I don't know if it has anything to do with the path finding specific problem):
canMoveInto() is built such that it has 'filters' along the way - you keep testing for all kinds of conditions, and if any fails the function returns false.
The only place where this function returns true is at the end, after all tests were made. This is done so you don't skip any condition when testing if a unit can move into a plot.

In your code you return true under a certain condition, and that way you might skip a few important conditions. I suggest you change it such that your condition only prevents the code from returning false on the 'iswater' condition, if needed.

It might even solve your problem.
 
Well, I see a basic problem with your implementation (I don't know if it has anything to do with the path finding specific problem):
canMoveInto() is built such that it has 'filters' along the way - you keep testing for all kinds of conditions, and if any fails the function returns false.
The only place where this function returns true is at the end, after all tests were made. This is done so you don't skip any condition when testing if a unit can move into a plot.

In your code you return true under a certain condition, and that way you might skip a few important conditions. I suggest you change it such that your condition only prevents the code from returning false on the 'iswater' condition, if needed.

It might even solve your problem.

hmm I tried that, it didnt help with the path-problem. I must be a problem with the diagonal move forbidding. There seems to be a problem with the AI aswell, since it gets a bug when calling "candefend()" which also links to "canmoveinto()".

This is the code I used now:

Spoiler :

switch (getDomainType())
{
case DOMAIN_SEA:
// River Mod start
if (pPlot->isRiverMask() == true || pPlot->isFriendlyCity(*this, true))
{
if (plot()->isRiverMask() == true || plot()->isFriendlyCity(*this, true))
{
if (pPlot->getX_INLINE() == (plot()->getX_INLINE()-1) && pPlot->getY_INLINE() == ((plot()->getY_INLINE()) -1))

{
return false;
}

if (pPlot->getX_INLINE() == (plot()->getX_INLINE()-1) && pPlot->getY_INLINE() == ((plot()->getY_INLINE()) +1))

{
return false;
}

if (pPlot->getY_INLINE() == (plot()->getY_INLINE()+1) && pPlot->getX_INLINE() == ((plot()->getX_INLINE()) +1))

{
return false;
}

if (pPlot->getY_INLINE() == (plot()->getY_INLINE()-1) && pPlot->getX_INLINE() == ((plot()->getX_INLINE()) +1))

{
return false;
}

}

}

else
{
//River Mod end
if (!pPlot->isWater() && !canMoveAllTerrain())
{
if (!pPlot->isFriendlyCity(*this, true) || !pPlot->isCoastalLand())
{
return false;
}

}
}



I tried several versions of this. with this code the path sometimes workes for a bit, but at some point it always starts to loop. Maybe I missunderstood something in the code? Or else I'll just have to allow diagonal moving again...
 
hmm I tried that, it didnt help with the path-problem. I must be a problem with the diagonal move forbidding. There seems to be a problem with the AI aswell, since it gets a bug when calling "candefend()" which also links to "canmoveinto()".

This is the code I used now:

Spoiler :

switch (getDomainType())
{
case DOMAIN_SEA:
// River Mod start
if (pPlot->isRiverMask() == true || pPlot->isFriendlyCity(*this, true))
{
if (plot()->isRiverMask() == true || plot()->isFriendlyCity(*this, true))
{
if (pPlot->getX_INLINE() == (plot()->getX_INLINE()-1) && pPlot->getY_INLINE() == ((plot()->getY_INLINE()) -1))

{
return false;
}

if (pPlot->getX_INLINE() == (plot()->getX_INLINE()-1) && pPlot->getY_INLINE() == ((plot()->getY_INLINE()) +1))

{
return false;
}

if (pPlot->getY_INLINE() == (plot()->getY_INLINE()+1) && pPlot->getX_INLINE() == ((plot()->getX_INLINE()) +1))

{
return false;
}

if (pPlot->getY_INLINE() == (plot()->getY_INLINE()-1) && pPlot->getX_INLINE() == ((plot()->getX_INLINE()) +1))

{
return false;
}

}

}

else
{
//River Mod end
if (!pPlot->isWater() && !canMoveAllTerrain())
{
if (!pPlot->isFriendlyCity(*this, true) || !pPlot->isCoastalLand())
{
return false;
}

}
}



I tried several versions of this. with this code the path sometimes workes for a bit, but at some point it always starts to loop. Maybe I missunderstood something in the code? Or else I'll just have to allow diagonal moving again...


ok I managed to get this thing done (took some sleepless nights ;)). The solution is to put the code into "pathvalid" (and not "canmoveinto"). Just in case anyone is interested in trying this themselves.

this is the code:

Spoiler :

if (pSelectionGroup->getDomainType() == DOMAIN_SEA)
{//RiverMod start
if ((pFromPlot->isRiverMask() && pToPlot->isRiverMask()) || ((pFromPlot->isCoastalLand()&& pFromPlot->isRiverMask()) && pToPlot->isWater()) || ((pToPlot->isCoastalLand() && pToPlot->isRiverMask()) && pFromPlot->isWater()))
{
if ((node->m_iX == (parent->m_iX)-1) && (node->m_iY == ((parent->m_iY) -1)))
{
return FALSE;
}


if ((node->m_iX == (parent->m_iX)-1) && (node->m_iY == ((parent->m_iY) +1)))
{
return FALSE;
}

if ((node->m_iY == (parent->m_iY) +1) && (node->m_iX == ((parent->m_iX) +1)))
{
return FALSE;
}


if ((node->m_iY == (parent->m_iY) -1)&& (node->m_iX == ((parent->m_iX) +1)))
{
return FALSE;
}

}//RiverMod End

 
ok I managed to get this thing done (took some sleepless nights ;)). The solution is to put the code into "pathvalid" (and not "canmoveinto"). Just in case anyone is interested in trying this themselves.

Can you please share this mod. I do not have any experience with CIV IV python, so I have no clue where to put the code you left. The completed mod is what I want, though, can you share it please?
 
Back
Top Bottom