Hello everyone,
I have been learning a bit of C++ in order to take a stab at implementing my own suggestions above. My aim is to create a graded invisibility system that is probabilistic—that is, you get a probability of seeing an invisible unit, but not usually with 100% odds. Think of how boring it would be if combat between units were deterministic and the stronger unit defeated the weaker unit 100% of the time! Well, this is the current situation with the invisibility system, and it doesn't look like it will be fixed with Beyond the Sword.
I have made a few attempts at modding primem0ver's code, and have come upon something that seems workable. Now, I am a novice at C++(only a few days of self-study so far), so it is not really a very good mod, nor is it how I would like to implement it. But, it is the best I have come up with so far with my very limited C++. My implementation also has a minor bug that I am attempting to squash, which is why I post here now.
My changes are in the CvPlot section. I shall post primem0ver's code, with my modifications in red:
/*******************************************************************************/
/** Added by primem0ver, 27/10/06 */
/** So that units with graded visibility can see all units with a lower grade */
/*******************************************************************************/
// local variables added by primem0ver
CvInvisibleInfo * invType;
if (eSeeInvisible != NO_INVISIBLE) invType = &GC.getInvisibleInfo(eSeeInvisible);
int iLoopCount = 100; // do not go through grade loop more than 100 times
// while this theoretically limits the number of
// links (grades) in a grade chain, it will prevent
// accidental circular chains
// end local variables
srand((unsigned)time(0));
while (iLoopCount > 0)
{
/*************************************************************************/
/* ORIGINAL CODE STARTS BELOW: */
/*************************************************************************/
if (iRange == 0)
{
changeVisibilityCount(eTeam, ((bIncrement) ? 1 : -1), eSeeInvisible);
return;
}
for (iDX = -(iRange - 1); iDX <= (iRange - 1); iDX++)
{
for (iDY = -(iRange - 1); iDY <= (iRange - 1); iDY++)
{
pLoopPlot = plotXY(getX_INLINE(), getY_INLINE(), iDX, iDY);
if (pLoopPlot != NULL)
{
pLoopPlot->changeVisibilityCount(eTeam, ((bIncrement) ? 1 : -1), eSeeInvisible);
iLevel = pLoopPlot->seeFromLevel(eTeam);
for (iI = 0; iI < NUM_DIRECTION_TYPES; iI++)
{
pAdjacentPlot = plotDirection(pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE(), ((DirectionTypes)iI));
if (pAdjacentPlot != NULL)
{
pAdjacentPlot->changeVisibilityCount(eTeam, ((bIncrement) ? 1 : -1), eSeeInvisible);
pAdjacentPlot->changeSeeFromSight(eTeam, ((DirectionTypes)iI), iLevel, bIncrement, eSeeInvisible);
pAdjacentPlot->changeSeeFromSight(eTeam, GC.getTurnLeftDirection(iI), iLevel, bIncrement, eSeeInvisible);
pAdjacentPlot->changeSeeFromSight(eTeam, GC.getTurnRightDirection(iI), iLevel, bIncrement, eSeeInvisible);
}
}
}
}
}
/*******************************************************************************/
/** Added by primem0ver, 27/10/06 */
/** Section controls loop and picks next lower invisibility grade type */
/*******************************************************************************/
if ((eSeeInvisible == NO_INVISIBLE) || ( ( (rand()) % 2 )< 1) ) iLoopCount = 0; // if we have hit the end of a chain, set the loopcount to end of loop
else
{
eSeeInvisible = (InvisibleTypes) invType->getNextInvisibleGrade();
if (eSeeInvisible != NO_INVISIBLE) invType = &GC.getInvisibleInfo(eSeeInvisible);
}
--iLoopCount;
} // THIS IS AN EXTRA BRACE THAT CLOSES while loop... by primem0ver
/*************************************************************************/
/*************************************************************************/
The first line in red simply sets a seed for the random number generator.
The second (and last) line in red, tells the function that controls whether the loop continues to a deeper level to stop IF it has encountered the end of the chain OR if a random number appears. The chance of the random number appearing is currently set to 50% for testing purposes. So what happens is that the loop stops 50% of the time, even if it has not hit the end of the chain. Since the loops are nested, the odds are 25% that it will have stopped by the second loop, 12.5% by the third, and so on and so forth. This has the effect that units lower in the invisibility chain become harder and harder to see (exponentially so) to units further up in the chain.
Now, here is how I set it up to be workable... I set up 8 invisible grades, from INVISIBLE_00 to INVISIBLE_07. I set the uboat to have Invisible_02 for invisibility and invisible_06 for SeeInvisible. I set the submarine to have Invisible_01 for invisibility and invisibile_04 for SeeInvisible. And the silent sub is set to have Invisible_00 invisibility and Invisible_03 for SeeInvisible.
This all has the effect that the uboats have 1/16 odds of seeing each other, 1/32 odds of seeing a submarine, and 1/64 odds of seeing a Silent Sub. The Submarines have 1/4 odds of seeing Uboats, 1/8 odds of seeing other submarines, and 1/16 odds of seeing Silent Subs. Finally, the Silent Subs have 1/2 odds of seeing uboats, 1/4 odds of seeing submarines, and 1/8 odds of seeing other silent Subs.
It all works fine as long as you do not set a unit to have a SeeInvisible lower than the highest Invisibility. For example, if I set the Silent Sub to have a SeeInvisible=00, then they would not be able to see Submarines or Uboats at all! This is because in the original graded invisibility mod, the higher invisibility levels are supposed to be the better ones.
In any case, my mod seems to be working well so far, except for one little detail. Sometimes, some plots become completely invisible—even when I have a unit in them. However, this happens probabilistically. I assume that the code I inserted is somehow interfering with the plotting code contained in the loop (code which I do not really understand) and preventing it from properly percolating down the levels. It only appears to happen when units that have the ability to see invisible units start overlapping each other's paths. It does not happen with units that have no SeeInvisible abilities. It also does not happen with units with SeeInvisible if it has SeeInvisible=00 (at the end of the chain).
I attach a screenshot of an invisible destroyer to illustrate.
So, I am wondering if anyone can enlighten this C++ novice as to any better ways to implement the probabilistic graded invisibility system, or any ways to resolve this specific problem. In any case, so far this mod seems good enough to use. I can live with this minor bug if it will give me probabilistic invisibility, although I wonder if this little bug might cause serious problems for the AI. I do not post the C++ files yet as I have not fully tested this yet.