Single Player bugs and crashes v39 plus (SVN) - After the 20th of July 2019

It could be that the save contains some kind of corruption from the problematic svn updates. Even if the game doesn't crash there could be some kind of memory corruption beeing caused by bad pointers. This could also happen in python because @Toffer90 fixed my crash problems by fixing python errors.
The plot is owned by the owner of the unit under evaluation. This is a common check for the code to run. It had to have passed this check many many times before now and suddenly now it comes up with a value of 0, even though in other references, the code is showing me that owner has revealed ALL of the plots in that area (and again, even that he owns the city that's on this plot). So what this is telling me is that it's not something in the save corruption because that would have come up as a problem even sooner in the round than this. I could try to prove that with some targeted stop points. But I believe that somewhere in the processing of THIS round, the data (how many plots are revealed by this owner on that area) is somehow wiped out just a little before this check is called for. I'm setting up a stop point that watches for that to occur to see WHY it may be happening, but something (the stage of the game being a major indicator) is telling me that it's a stack overflow that's causing this kind of data chaos.
 
Code:
Traceback (most recent call last):
  File "CvScreensInterface", line 273, in pediaJumpToImprovement
  File "Pedia", line 627, in pediaJump
  File "PediaImprovement", line 95, in interfaceScreen
RuntimeError: unidentifiable C++ exception
ERR: Python function pediaJumpToImprovement failed, module CvScreensInterface

@Toffer90 got this when I clicked on the Asteroid Mine, Colony Extraction Facility, Geothermal Factory, Martian Mine, Supernova Mine, True Vacuum and Venus Surface Mine improvement. Not sure if I goofed it up when changing models for the geothermal one.
 
The plot is owned by the owner of the unit under evaluation. This is a common check for the code to run. It had to have passed this check many many times before now and suddenly now it comes up with a value of 0, even though in other references, the code is showing me that owner has revealed ALL of the plots in that area (and again, even that he owns the city that's on this plot). So what this is telling me is that it's not something in the save corruption because that would have come up as a problem even sooner in the round than this. I could try to prove that with some targeted stop points. But I believe that somewhere in the processing of THIS round, the data (how many plots are revealed by this owner on that area) is somehow wiped out just a little before this check is called for. I'm setting up a stop point that watches for that to occur to see WHY it may be happening, but something (the stage of the game being a major indicator) is telling me that it's a stack overflow that's causing this kind of data chaos.
This is not a stack overflow either.

I'm thinking through some of this still. From what I can tell, a python module is calling for the elimination of every plot revealed for team 11 on a particular landmass(area).

Bill showed me how to look at a data stop point .

When variable( m_aiNumRevealedTiles[10] ) is loaded from the save, Team 11 (index 10) has 1583 revealed plots on area ID 81931 (the area we come up with a result of 0 on for this calculation that results in a divide by 0 error)

Hitting end of turn, it starts encountering changes issued by python:
upload_2019-8-3_20-57-29.png

upload_2019-8-3_20-59-21.png

CvEventInterface
upload_2019-8-3_21-0-3.png

onEvent
upload_2019-8-3_21-1-1.png

yeah... not sure how to look into what this pointer is calling for on the python side but maybe someone has a clue from this?
upload_2019-8-3_21-2-24.png

not sure what to make of this either

Then from there it goes into the python code and I lose the trail then it comes back out of that with a request to invoke CyMap::setRevealedPlots(10, -1, false)

That is what does it right there. This is normally the sort of thing you see when you recalculate - clearing the data for rebuilding it afterward. Or perhaps when deleting the player as a step in that process, which is usually more easily accomplished by just safe deleting the variable.

But this crazy python call coming from I have no idea where is causing a major collapse in the tracking of all revealed plots for the specified player across all of the main map, and it never gets rebuilt so when it comes time to check how many plots are revealed on a particular Area (landmass) the answer is 0, which is then inserted handily into a division problem resulting in a divide by 0 error that should never happen.

This, folks, is caused in python somewhere. From there, I'm hoping someone with more python interfacing knowledge than I can further track the issue.

Spoiler :

Code:
template <class RC, class F, class TC BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class AC)>
inline PyObject* invoke(invoke_tag_<true,true>, RC const&, F& f, TC& tc BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, AC, & ac) )
{
    (tc().*f)(BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, ac, () BOOST_PP_INTERCEPT));
    return none();
}
then
Code:
void CyMap::setRevealedPlots(int /*TeamTypes*/ eTeam, bool bNewValue, bool bTerrainOnly)
{
    if (m_pMap)
        m_pMap->setRevealedPlots((TeamTypes) eTeam, bNewValue, bTerrainOnly);
}
then
Code:
void CvMap::setRevealedPlots(TeamTypes eTeam, bool bNewValue, bool bTerrainOnly)
{
    PROFILE_FUNC();

    int iI;

    for (iI = 0; iI < numPlotsINLINE(); iI++)
    {
        plotByIndexINLINE(iI)->setRevealed(eTeam, bNewValue, bTerrainOnly, NO_TEAM, false);
    }

    GC.getGameINLINE().updatePlotGroups();
}
then
Code:
void CvPlot::setRevealed(TeamTypes eTeam, bool bNewValue, bool bTerrainOnly, TeamTypes eFromTeam, bool bUpdatePlotGroup)
{
    CvCity* pCity;
    int iI;

    FAssertMsg(eTeam >= 0, "eTeam is expected to be non-negative (invalid Index)");
    FAssertMsg(eTeam < MAX_TEAMS, "eTeam is expected to be within maximum bounds (invalid Index)");

/*********************************/
/***** Parallel Maps - Begin *****/
/*********************************/
    if (isNull() && !isRevealed(eTeam, false))
        return;
/*******************************/
/***** Parallel Maps - End *****/
/*******************************/   

    pCity = getPlotCity();

    if (isRevealed(eTeam, false) != bNewValue)
    {
        if (NULL == m_abRevealed)
        {
            m_abRevealed = new bool[MAX_TEAMS];
            for (int iI = 0; iI < MAX_TEAMS; ++iI)
            {
                m_abRevealed[iI] = false;
            }
        }

        m_abRevealed[eTeam] = bNewValue;

        if (area())
        {
            area()->changeNumRevealedTiles(eTeam, ((isRevealed(eTeam, false)) ? 1 : -1));
        }

        if (bUpdatePlotGroup)
@billw2015 (refer to last few lines of the spoiler) I figured out that m_abRevealed[eTeam]=bNewValue; being called in one of those last lines there is where area()->changeNumRevealedTiles(eTeam, ((isRevealed(eTeam, false)) ? 1 : -1)); is getting the false result in isRevealed(eTeam,false) as false from, despite the stepping through showing it to be true for some weird reason. So actually that did make sense though I'm not sure why it looked like it was hitting isRevealed as true. *Shrug*

Anyhow, clearly this is a python call causing the damage. I'm thinking in onEvent in CvInterface... but what event? Can we now search for setRevealedPlots in python to get a clue? I shall try...
 
yep... here it is in CvEventManager.py
upload_2019-8-3_21-14-53.png

MAP.setRevealedPlots(iTeamX, False, False)

I see.
upload_2019-8-3_21-23-24.png

So it's doing exactly what it should be doing, which is causing major bugs, MAJOR bugs.

Now... what would happen here is as soon as a unit moves, it's going to reveal for that player. Now that I KNOW this is actually a desired effect and not some major weird bug, it seems to me the fix is actually to correct the potential for the divide by 0 error. However, I would also like to request that IF this takes place to a rival, (which apparently can only happen to rivals that don't already have satellites?) that the game should cycle through that rival's cities, identify their plots, and call the python equivalent of:
Code:
            if (pPlot->isVisible(((TeamTypes)iI), false))
            {
                setRevealed(((TeamTypes)iI), true);
            }
My python is a bit too weak to know that I'd do this right.




Actually no... I do know a way to do more than this and that's to create a py exposed function that will do the elimination of revealed plots AND reset all revealed plots by if they are currently visible then get the python to call that function instead. Gimme a minute.

I think someone actually reported this wonder's effect as a bug the other day in discord too now that I think about it - they thought they'd hit a hotkey that wiped out their map to full black.
 
yep... here it is in CvEventManager.py
View attachment 531251
MAP.setRevealedPlots(iTeamX, False, False)

I see.
View attachment 531252
So it's doing exactly what it should be doing, which is causing major bugs, MAJOR bugs.

Now... what would happen here is as soon as a unit moves, it's going to reveal for that player. Now that I KNOW this is actually a desired effect and not some major weird bug, it seems to me the fix is actually to correct the potential for the divide by 0 error. However, I would also like to request that IF this takes place to a rival, (which apparently can only happen to rivals that don't already have satellites?) that the game should cycle through that rival's cities, identify their plots, and call the python equivalent of:
Code:
            if (pPlot->isVisible(((TeamTypes)iI), false))
            {
                setRevealed(((TeamTypes)iI), true);
            }
My python is a bit too weak to know that I'd do this right.




Actually no... I do know a way to do more than this and that's to create a py exposed function that will do the elimination of revealed plots AND reset all revealed plots by if they are currently visible then get the python to call that function instead. Gimme a minute.

I think someone actually reported this wonder's effect as a bug the other day in discord too now that I think about it - they thought they'd hit a hotkey that wiped out their map to full black.

@Toffer90 made some changes to that code in PPIO here is what it looked before.
Code:
## Zizkov Start ##
    pPlayer = gc.getPlayer(iPlayer)
    iTeam = pPlayer.getTeam()
    pTeam = gc.getTeam(iTeam)
    bC_Zizkov = gc.getInfoTypeForString("BUILDINGCLASS_ZIZKOV")
    if bC_Zizkov > -1 and pPlayer.getBuildingClassCount(bC_Zizkov) ==1:
        for iPlayer2 in range(gc.getMAX_CIV_PLAYERS()):
            pPlayer2 = gc.getPlayer(iPlayer2)
            iTeam2 = pPlayer2.getTeam()
            pTeam2 = gc.getTeam(iTeam2)
            if pPlayer2.isAlive():
                if pTeam2.isHasTech(gc.getInfoTypeForString("TECH_SATELLITES")) == false:
                    if (iTeam2 != iTeam) and ( gc.getTeam(iTeam2).isVassal(iTeam) == false ):
                        concealchance = CyGame().getSorenRandNum(10, "Conceal")
                        if concealchance ==0:
                            CyMap().setRevealedPlots(iTeam2, false, false)
                            for iCity2 in range(pPlayer2.getNumCities()):
                                pCity2 = pPlayer2.getCity(iCity2)
                                clevel = pCity2.getCultureLevel() + 2
                                iX = pCity2.getX()
                                iY = pCity2.getY()
                                for x in range(iX - clevel, iX+clevel +1):
                                    for y in range(iY - clevel, iY+ clevel +1):
                                        pPlot = CyMap().plot(x,y)
                                        pPlot.setRevealed(iTeam2, true, false, -1)
                            CyInterface().addMessage(iPlayer,true,20,CyTranslator().getText("TXT_ZIZKOV1",(pPlayer2.getCivilizationDescription(iPlayer2),)),'',0,'',-1,-1,-1, false,false)
                            CyInterface().addMessage(iPlayer2,true,20,CyTranslator().getText("TXT_ZIZKOV2",()),'',0,'',-1, -1,-1,false,false)
## Zizkov End ##

It did at least reveal some plots again but this is still wrong it should check the plot visibility and reveal every visible plot.

EDIT:
That code could also be changed to unreveal only the plots which aren't visible this would be a faster solution.
 
Last edited:
That code could also be changed to unreveal only the plots which aren't visible this would be a faster solution.
Jeez why didn't I think of that??? Brilliant! (Seriously, duh - but thank you for mentioning it!)

A quick change to method and we'll have this running right in moments here.
 
Code:
  File "PediaImprovement", line 95, in interfaceScreen
RuntimeError: unidentifiable C++ exception

@Toffer90 got this when I clicked on the Asteroid Mine, Colony Extraction Facility, Geothermal Factory, Martian Mine, Supernova Mine, True Vacuum and Venus Surface Mine improvement. Not sure if I goofed it up when changing models for the geothermal one.
Noted.
So it's doing exactly what it should be doing, which is causing major bugs, MAJOR bugs.
Huh, never actually got a chance to test it in game as Zizkov was a commented out building until after v39 I think. I didn't think the reveal part was nessesarry as I assumed the dll would do that anyway if that call was made by python.

I'll rethink the code having in mind that it's bad practice to hide the entire map for a player.
Albert had a good Idea there, will you do this in the dll code for the setRevealedPlots(iTeam2, false, false) function TB?
 
Last edited:
Noted.
Huh, never actually got a chance to test it in game as Zizkov was a commented out building until after v39 I think. I didn't think the reveal part was nessesarry as I assumed the dll would do that anyway if that call was made by python.

I'll rethink the code having in mind that it's bad practice to hide the entire map for a player.
Albert had a good Idea there, will you do this in the dll code for the setRevealedPlots(iTeam2, false, false) function TB?
I created a new function:
resetRevealedPlots(iTeam)

It goes through and checks all revealed plots and removes them from being revealed if they are not visible. It's been exposed to python and the python has been adjusted. Bug resolved and new functionality engaged. :D
 
Nice, thanks for doing all the work there. ^^
It didn't take long really. It's a simple function.

What's funny about this is I had no idea this wonder was even in the game...
 
Code:
  File "PediaImprovement", line 95, in interfaceScreen
RuntimeError: unidentifiable C++ exception
ERR: Python function pediaJumpToImprovement failed, module CvScreensInterface

@Toffer90 got this when I clicked on the Asteroid Mine, Colony Extraction Facility, Geothermal Factory, Martian Mine, Supernova Mine, True Vacuum and Venus Surface Mine improvement. Not sure if I goofed it up when changing models for the geothermal one.
This error is happening when python asks the exe to set up the 3D graphical window for it.
CyGInterfaceScreen.addImprovementGraphicGFC(...)
The error is in the exe, so you may have broken some rules with the nif file.
 
This error is happening when python asks the exe to set up the 3D graphical window for it.
CyGInterfaceScreen.addImprovementGraphicGFC(...)
The error is in the exe, so you may have broken some rules with the nif file.

How come it also affects others I haven't modified, all of them pepper's content?

EDIT: Found the issue: if you try to define a nonexistent KFM (responsible for the animation) it does that.
 
Last edited:
Added ability to display an era icon to the right of finance info in the upper left corner. Simply add a <Button>art/...</Button> to an era in CIV4EraInfos.xml to give the era an icon. I only gave prehistoric and the ancient era an icon for now.

thought u said u already HAD the ancient era icon??
 

Attachments

  • era.JPG
    era.JPG
    290.7 KB · Views: 76
Back
Top Bottom