[MODCOMP]Vehem's Quick and Dirty Map Decay

Vehem

Modmod Monkey
Joined
Nov 22, 2005
Messages
3,219
Vehem's Quick and Dirty Map Decay

There have been numerous discussions regarding the fact that a couple of scouts can explore the whole continent pre-AD and that explorers generally have little purpose. Given that accurate map-making of large geographical areas was a rather late development, I put together the following to represent the "forgetfulness" of a Civilisation in the pre-cartography era.

Spoiler Python Code :
Added to OnBeginPlayerTurn in CvEventManager.py
Code:
# Vehem Quick and Dirty Map Decay START
		pPlayer = gc.getPlayer(CyGame().getActivePlayer())
		eTeam = gc.getTeam(pPlayer.getTeam())
		aTeam = CyGame().getActiveTeam()
		
		if (not eTeam.isHasTech(gc.getInfoTypeForString('TECH_PAPER'))):

			if (eTeam.isHasTech(gc.getInfoTypeForString('TECH_WRITING'))):
				iMapDecayPercentage = 10
			else:
				iMapDecayPercentage = 20

			for i in range (CyMap().numPlots()):
				pPlot = CyMap().plotByIndex(i)
				if (not pPlot.isVisible(aTeam, false)):
					if (CyGame().getSorenRandNum(100, "MapDecay") <= iMapDecayPercentage):
						pPlot.setRevealed(aTeam, false, false, TeamTypes.NO_TEAM)
			pPlot.updateVisibility()
# Vehem Quick and Dirty Map Decay END

As coded, this will "unreveal" a map-tile that is currently non-visible by any unit with a chance per turn of 20%. This chance is halved (to 10%) by the discovery of Writing and negated by the discovery of Paper.

The net result is that if you don't visit an area for a period of time, you will forget what is over there. Naturally the player will have a recollection of what he saw there, but will probably need to re-explore in order to make any firm plan regarding expansion in that area.

In my personal collection of Mods, I have also renamed Paper to Cartography as this tech now controls both Map Trading and Map Decay. Incidentally, I have also added the Sentry promotion to Explorers to aid rapid re-exploration when needed.

The AI explore algorithm tends to double back on itself to re-explore forgotten regions, quite frequently before Writing is discovered. This means that if you rely on clicking the "Automate Explore" button to uncover the map, you may find your first few scouts working hard just to keep the local area up-to-date. Additional automated scouts or taking an active role in exploration will counter this effect (which is intentional). AI players are not significantly impacted by this mod (beyond the scouting behaviour) as they tend to cheat a little when it comes to selecting city locations anyway.
 
This is a little bit too quick and dirty for my tastes, but I'll certainly build upon this. Personally I think it should also be very much dependent on the distance from your territory as well. I don't think squares immediately outside of view should become "unrevealed".

I like the idea of techs affecting the probability of tiles becoming hidden again.

Also, I think you should attach a python file or something because I'm not sure if telling us how to do this would be a modcomp or a tutorial and it might get moved otherwise.
 
This is a little bit too quick and dirty for my tastes, but I'll certainly build upon this. Personally I think it should also be very much dependent on the distance from your territory as well. I don't think squares immediately outside of view should become "unrevealed".

Aye - I did have a toy around with that as well, but decided to go with the simplest effective implementation in the end. I have reduced the odds to 8% and 4% on my own copy however, simply as it feels more natural. It also fixes the issue you mentioned to an extent, as nearby areas are rarely out of sight for 10-20 turns.

If you did want to stop tiles right next to a visible tile being unrevealed however, it should be a minor change, either using isAdjacentVisible or isAdjacentTeam (the latter should only block it for the area outside cultural borders if memory serves).

Also, I think you should attach a python file or something because I'm not sure if telling us how to do this would be a modcomp or a tutorial and it might get moved otherwise.

I was wondering about this when I first posted it, but figured it was redundant. The component totals less than 20 lines including the bounding comments and is a simple copy-and-paste job into the most frequently editted Python file. If I had posted it embedded in a file, most people would download it, then copy it out of the file and into their own to merge with other python mods anyway.

If a file-attachment is a requirement, I can happily supply the CvEventManager, though I'd maintain the code itself constitutes a ModComponent, complete and ready to be integrated into larger mods.
 
Aye - I did have a toy around with that as well, but decided to go with the simplest effective implementation in the end. I have reduced the odds to 8% and 4% on my own copy however, simply as it feels more natural. It also fixes the issue you mentioned to an extent, as nearby areas are rarely out of sight for 10-20 turns.

If you did want to stop tiles right next to a visible tile being unrevealed however, it should be a minor change, either using isAdjacentVisible or isAdjacentTeam (the latter should only block it for the area outside cultural borders if memory serves).

Good point... I wrote some additional code in which it checked the tiles in a 3-tile radius to see if it was visible, but that will probably have a noticeable impact on processing time. The "isAdjacentVisible" would be a good alternative even if it would only keep those tiles immediately beyond sight from reverting to unrevealed.

Is there also a method for finding the distance to the nearest city? And would that add more processing time than a check of all tiles within a certain radius? You could probably have it so that if the tile is less than 5 tiles from a city plot, it would have a 5% chance and if it were between five and ten it would have X% and so on... That way, those far out regions are likely to be rendered unexplored again while local areas will be much more likely to remain known.

Ultimately though it's the question of how much processing time this will add that concerns me since it obviously has to check through every single tile.
 
Is there also a method for finding the distance to the nearest city? And would that add more processing time than a check of all tiles within a certain radius? You could probably have it so that if the tile is less than 5 tiles from a city plot, it would have a 5% chance and if it were between five and ten it would have X% and so on... That way, those far out regions are likely to be rendered unexplored again while local areas will be much more likely to remain known.

Ultimately though it's the question of how much processing time this will add that concerns me since it obviously has to check through every single tile.



I've got a feeling that FindCity will find the closest one to the start point, and CalculatePathDistance will get the distance from that. I haven't played around with FindCity's functionality much to check that yet though.

As for the additional processing required, FFH has a nice trick, whereby instead of checking every tile every turn with a 5% chance, they'd check every 5th tile, every turn, with a 25% chance. Then they offset the start tile by 1 and go again - such that after 5 turns every tile has had a single 25% chance. This won't lead to strictly the same effect, but it'll drop processing time nicely if that becomes an issue.
 
Ah nice one. Finaly someone (maybe) used some of my ideas. But to the AI problem (and maybe others functionality) I would think only adjustant plots to unexplored should be able to become unexplored.
 
I like this idea, if someone would pick it up.

Just a thought, perhaps between Cartography and Scientific Method, some decay might still occur. Perhaps in that 'era' in between, major land forms are remembered, as well as major terrain features---lakes, rivers, mountains, but all bonuses, forests, and tile disposition would be forgotten, replaced with something else (perhaps desert or plains?) and for extra credit, the exact shape of land would morph into blobs (so the exact shape of the coast would be forgotten).
 
Here's the SDK code to do the same without the lag and with a few extra rules like only affecting tiles with at least one unrevealed tile adjacent to them. I also exclude water tiles so I don't have to re-explore the entire map, just the land.

The following code should be place in CvPlayer.cpp in the doTurn() method, I placed it just below the line that reads- doEspionagePoints()
Code:
/*** Seven05 Begin ***/
// Deteriorate the players map until they discover paper.  Once writing is
// discovered the effect lessens.
	CvPlot* pPlot;
	int iI;

	if (GET_TEAM(getTeam()).isHasTech((TechTypes)GC.getInfoTypeForString("TECH_PAPER")) == false)
	{
		int iMapDecay = 0;

		if (GET_TEAM(getTeam()).isHasTech((TechTypes)GC.getInfoTypeForString("TECH_WRITING")) == false)
			iMapDecay = 6;
		else
			iMapDecay = 3;

		for (iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
		{
			pPlot = GC.getMapINLINE().plotByIndexINLINE(iI);
			FAssert(pPlot != NULL);
			if (pPlot->isAdjacentNonrevealed(getTeam()) && !pPlot->isVisible(getTeam(),false) && !pPlot->isWater())
			{
				if (GC.getGameINLINE().getSorenRandNum(100, "Map Decay") <= iMapDecay)
					pPlot->setRevealed(getTeam(), false, false, NO_TEAM, true);
			}
		}
		pPlot->updateVisibility();
	}
/*** Seven05 End ***/

Fixe the missing declarations for iI and pPlot, sorry about that :)
 
Seven05

I tried putting in the above code in the suggested place but the files wouldn't compile (something about undeclared indentifiers that seem to be the bane of my life). What have I missed out?

I am using standard VS 2003, using Unofficial patch BTS 3.13 source provided by Bhruic, which compiles fine on its own, and employing the much coveted 'typewriters and monkeys' technique for my coding.
 
These lines are missing some brackets and won't work:
Spoiler :
Code:
		if (GET_TEAM(getTeam()).isHasTech((TechTypes)GC.getInfoTypeForString("TECH_WRITING")) == false)
			iMapDecay = 6;
		else
			iMapDecay = 3;

... and ...
				if (GC.getGameINLINE().getSorenRandNum(100, "Map Decay") <= iMapDecay)
					pPlot->setRevealed(getTeam(), false, false, NO_TEAM, true);
This should work:
Spoiler :
Code:
		if (GET_TEAM(getTeam()).isHasTech((TechTypes)GC.getInfoTypeForString("TECH_WRITING")) == false)
		{
			iMapDecay = 6;
		}
		else
		{
			iMapDecay = 3;
		}

... and ...
				if (GC.getGameINLINE().getSorenRandNum(100, "Map Decay") <= iMapDecay)
				{
					pPlot->setRevealed(getTeam(), false, false, NO_TEAM, true);
				}
 
Strange, compiles fine for me without the braces in there and I've never had problems before whe skipping braces for single line statements in many other apps. Did I miss something else? :)

However, It is broken for another reason that makes more sense with the whole undeclared identifier bit. I had two lines outside of my begin & end comments... silly n00b error on my part, anyway if you add the two following lines before the rest of that code it'll work, really :)

Code:
	CvPlot* pPlot;
	int iI;

I instinctively stuck them up with the other declarations in the method but they don't need to be there. Alternative you can drop the declaration for iI and change the loop itself to, not sure why I had it outside of that staement but I'm sure I had a good reason for it, maybe I was reusing iI in testing:
Code:
	for (int iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
(note the declaration inside the for statement)

Well, the original code a few posts up has been fixed so you can just use that again, sorry about the mess.
 
Brilliant stuff, all of you. Once I have finished porting my Civics Mod to BtS, I am doing a Modpack in which this would be IDEAL!!

Aussie_Lurker.
 
Top Bottom