Communitas map script

There were screens of the oasis spam. It wasn't just imagined. It's fairly significant, even as progress occurs. Refining the script so that it doesn't look out of whack from realistic effects and doesn't make for a totally imbalanced or predictable game experience is hard. Feedback is bound to be critical at times.

I think the point about removing rivers in deserts and replacing with oasis effects is rather key for both balance and realism as something we should try to avoid as an effect. I don't think it was Thal's goal to alter the balance and appearance of the map and the desert terrain. But that seems to be what was happening.
 
@mystikx21

I agree. They looked all wrong. But I'm not in the position to verify if that is a coding problem, graphical glitch or just some random anomaly. I wish I did know more about Lua code. So in the hope that a greater quantity of maps played will result in a greater quantity of evidence, one way or the other, let's let the matter settle.

If we all come back with reports of oases springing up everywhere, and deserts being unplayable, then a change can be made. If it however proves to be nothing then we can move on.
 
The screenshots of oases show average numbers of desert feature tiles for a vanilla map. It might seem like there's more features, but the overall quantity is the same as maps like Continents Plus. It might be somewhat of an optical illusion because oases are more visible than floodplains.

Cities can work fewer oases than floodplains because oases scatter more than river tiles. The blank deserts separating oases also cost more to expand to than lined-up floodplains. I typically choose the desert faith pantheon when I start near lots of floodplains. Pantheons have most effect in the early game, when cities have low food, and work more floodplains than hills.

The Dutch use floodplains, not oases. Fix one thing for Arabia, break another for the Dutch. =)
 
Well, oases are still spawing in rows, and now with the desert fresh water buff, the problem is even worse.





Can we PLEASE just use stackpointer's code? No-one here has objected to it, plenty of people here think deserts SHOULD be more inhospitable than they are, and this oasis problem refuses to go away.

The flavorful idea of an oasis is that it is a rare source of water in a dry area with none.

I prefer rivers in deserts, and floodplains, over lots of oases. Floodplains are a good terrain and are worth settling. Desert tiles adjacent to oases are still useless without Petra (which is bordering on too strong now).

We have historic counterparts of great civilizations rising on cities in desert (Nile, Niger), but no civilization really arises from desert oases (Arabs were from the coastal areas where it rains, the desert dwellers were always nomads).

It was much worse, I admit. But it's still too high a frequency per desert city. It is still possible to get several per city. 1-2 per desert city might be okay, 3-4 is not. 5-6 was insane. See the difference between albie's and stack's screens for oasis' alone.

We get flood plains and rivers instead and this doesn't imbalance the city, they require improvement to be excellent tiles and are basically like grassland, but with the ability to build Petra.

Wherever a city is founded it surely should NOT have more than 2 oases within its boundary. It just doesn't make sense IMO.

All the great desert based civs of the world were focused around floodplains.

The Nile basin for Egypt and the Fertile Crescent for Babylon, Assyria etc.

Petra is not near a floodplain but rather has an (artificial) oasis. So having deserts without floodplains is good if you want Petra since any desert/floodplain tile is not getting a benefit.

So oases are rare, that's why their yields are better than floodplains.
Now you can, and should, have 2 floodplains together which means your 2 desert tiles are now giving 4 food which is better than a single oasis of 3 food (& 1 gold).

Any attempt to make oases appear more than 2 per city area is going against the concept and mechanics of desert civilization.

You don't build in the desert unless there is a river to flood and fertilize your fields.
If there is no river, there must be a very good reason to build there. Oases should be the very good reason, and if they are very good, they should therefore be rare.
 
This an edit of the 1st post by Thal.

Edit:

Vanilla maps like Continents Plus cover 33% of flat desert tiles in features like oasis or floodplains to make desert regions equally valuable to other areas. This vanilla proportion is identical to the v3.0.6 build of the Communitas map. Deserts are equally valuable in both vanilla and the mod. Vanilla covers deserts in floodplains, which are nearly invisible, so the desert looks barren. Oases are more visible. I'm working on making this visual aspect look more realistic, but gameplay is basically the same.

The BOLD words are done by me.

Which means the maps LOOK all wrong, and I agree they LOOK wrong, but essentially the result is the same as any other vanilla map.

So let's just wait and see what results from extensive BETA testing!

Remember when we see "oasis" on Communitas Map, on a vanilla map that was "floodplain".
 
Seeing an oasis is not the same as seeing a flood plains though, the tile value is very different. The gameplay is not basically the same. Having them clustered into packs of 3 or 4 is not the same as having 3 or 4 flood plains along a river, and they're effectively increasing the value of desert cities, something that I don't think either Thal or any of us intends.

I have no problem with Thals intent as an overall goal of balance and realism and balancing the map is not a simple prospect.

What is being questioned is the oasis=floodplain logic that appears to be behind the frequency or clustering of oasis tiles in the same manner that flood plains do. Frequent or clustered oasis is not the same in balance or psychological terms as a desert river with flood plains. Let's say that the issue is that there are the same number of oasis as before, but they're all popping up in the same place, that's a big problem, and not just a problem of visibility. Alternatively the problem is that there are the same number of features on deserts, but this means that some of the rivers and flood plains are instead oasis tiles. That's also a problem.
 
Which means the maps LOOK all wrong, and I agree they LOOK wrong, but essentially the result is the same as any other vanilla map.

So let's just wait and see what results from extensive BETA testing!

I agree completely. This is a beta and Thal is just trying to balance deserts and try out new things. And this actually might be a simple error. You can see Thal's code below:

Spoiler :
PHP:
function PlacePossibleOasis(plotX,plotY)
	local plot = Map.GetPlot(plotX,plotY)
	if not IsBarrenDesert(plot) or plot:IsHills() then
		return
	end
	
	local odds = 0
	for _, adjPlot in pairs(Plot_GetPlotsInCircle(plot, 3)) do
		local distance = Map.PlotDistance(adjPlot:GetX(), adjPlot:GetY(), plot:GetX(), plot:GetY()) or 1
		local featureID = adjPlot:GetFeatureType()
		
		if featureID == FeatureTypes.FEATURE_OASIS then
			if distance <= 2 then
				-- at least 2 tile spacing between oases
				return
			end
			odds = odds - 200 / distance
		end
		
		if featureID == FeatureTypes.NO_FEATURE and not adjPlot:IsFreshWater() then
			if adjPlot:GetTerrainType() == TerrainTypes.TERRAIN_DESERT then
				odds = odds + 10 / distance
			elseif adjPlot:IsMountain() or adjPlot:IsHills() then
				odds = odds + 10 / distance
			elseif adjPlot:GetTerrainType() == TerrainTypes.TERRAIN_PLAINS then
				odds = odds + 5 / distance
			end
		else
			odds = odds - 5 / distance
		end
	end
	
	if odds >= Map.Rand(100, "PlacePossibleOasis - Lua") then
		plot:SetFeatureType(FeatureTypes.FEATURE_OASIS, -1)
	end
end

If I'm not mistaken the function Plot_GetPlotsInCircle needs you to define a minimum and maximum radius if you want to check tiles between two radii:

Spoiler :
PHP:
function Plot_GetPlotsInCircle(plot, minR, maxR)
	if not plot then
		log:Fatal("plot:GetPlotsInCircle plot=nil")
		return
	end
	maxR = maxR or minR
	...

This would explain why oasis can cluster up to a two tile distance of each other (but not three) even though he has commented in the code that it shouldn't.

Also, would it be possible to use the actual flood plain tile model around an oasis? Like if a desert river had completely surrounded the oasis tile and the oasis tile model could also be enlarged to merge into it too?
 
What's more, the values of tiles have now been changed from vanilla values just to accommodate more oases.

I have absolutely no idea why this needs to be the case. The vast majority of people here have expressed opinions otherwise, and it's a needless change from vanilla, which goes against the two core tenets of this entire mod project - community input and adherence to vanilla gameplay. If we need to start changing values because there are too many oases, the fix, in my opinion, should be to lesser the number of oases. If that means raising the number of floodplains, fine.
 
@albie_123
The oases you screenshotted are created by a basic part of map generation that individual maps do not control. Stackpointer's code would not change this. It's the same in this map as Continents Plus. The unmodded game adds a few extra bonus tiles near start locations that have low value. It does this for all maps, and can result in a few extra oases if someone starts in a desert. It's not something individual map scripts can change.

My goal is to make a map similar to Continents Plus, with a few improvements:

  • Ocean rifts make Astronomy important.
  • Citystates spawn everywhere, instead of only offshore.
  • Terrain looks more realistic.

@AnthonyG
Gem gave industrial-era ships the capability to slowly navigate ice (1 tile per turn). I plan on carrying over this feature to CEP so contents blocked by 1 ice tile won't be completely impassible in the late game, when people would realistically have icebreakers.

@Ahriman
Map generation equalizes terrain everywhere, not by region.

@Gothic_Empire
The dutch improve marsh and coastlines in the mod. I feel coastlines are more realistic than deserts for Dutch polders. They're basically drained inland seas caused by resource extraction, then refilled or dammed to create farmland. It makes sense to see this along coastlines. I plan on carrying over this feature from Gem to Cep.
 
None of those spots were near start locations, and I have never seen two oases next to one another using Stackpointer's code. I only generated about 5 or so maps, but never having seen a pair of oases next to one another after 5 tries is a pretty good sign. On the other hand, every single large map I have generated with 1.1's communitas script has had at least one 3-tile oasis row, usually more, and not anywhere near a starting point.

Deserts on the whole aren't the oasis-riddled mess they once were but oases are still appearing in packs, which doesn't really make sense from any perspective.
 
The map ensures a minimum 2 tiles of space between oases, unless you see an error in the code below. The screenshots you posted are caused by things I cannot control in this map script. :)

PHP:
function PlacePossibleOasis(plotX,plotY)
	local plot = Map.GetPlot(plotX,plotY)
	if not IsBarrenDesert(plot) or plot:IsHills() then
		return
	end
	
	local odds = 0
	for _, adjPlot in pairs(Plot_GetPlotsInCircle(plot, 3)) do
		local distance = Map.PlotDistance(adjPlot:GetX(), adjPlot:GetY(), plot:GetX(), plot:GetY()) or 1
		local featureID = adjPlot:GetFeatureType()
		
		if featureID == FeatureTypes.FEATURE_OASIS then
			if distance <= 2 then
				-- at least 2 tile spacing between oases
				return
			end
			odds = odds - 200 / distance
		end
		
		if featureID == FeatureTypes.NO_FEATURE and not adjPlot:IsFreshWater() then
			if adjPlot:GetTerrainType() == TerrainTypes.TERRAIN_DESERT then
				odds = odds + 10 / distance
			elseif adjPlot:IsMountain() or adjPlot:IsHills() then
				odds = odds + 10 / distance
			elseif adjPlot:GetTerrainType() == TerrainTypes.TERRAIN_PLAINS then
				odds = odds + 5 / distance
			end
		else
			odds = odds - 5 / distance
		end
	end
	
	if odds >= Map.Rand(100, "PlacePossibleOasis - Lua") then
		plot:SetFeatureType(FeatureTypes.FEATURE_OASIS, -1)
	end
end
 
I'm not sure the problem is being understood at this point.

1) Clustering of oasis should not be happening. It is imbalancing toward deserts, and away from desert river cities in a way that is psychologically undesirable, realism breaking, and increases the value of desert cities by tile imbalance (oasis is a good tile).
2) Stack's code seems to fix that by eliminating the clusters. It works. It does eliminate the clusters.
3) If the design goal is to have the available features in deserts be consistent with vanilla maps, but to have more realistic and interesting maps, that design goal is fine.
4) If the design goal is to increase the likelihood of oasis features relative to flood plains, that's not a desirable goal. I don't think that's the intent. Thal's suggested as much. But it seems to be an effect (even if only psychologically by stacking the oasis tiles together rather than having them spread out as would be expected).
5) Reducing or improving the value of oasis tiles isn't necessary in and of itself. The problem is the frequency and clustering on the map script.
 
@mystikx21
A different file, AssignStartingPlots equalizes terrain across the map, adding food like oases to low-food tiles, and production like stone to low-production tiles. Map scripts like Continents or Communitas do not control this. Nothing we do in a map script would change that code, since it's in a different file and runs after maps are created.

I designed this map script to require 2 tiles of open space between oases, but the AssignStartingPlots equalization code runs later. I could change the other code to prevent adjacent oases - this change would apply to all maps and not specifically this one.


@stackpointer
Floodplains are invisible and don't have a tile model. The GetPlotsInCircle function accepts two types of calls:

GetPlotsInCircle(center, min, max)
GetPlotsInCircle(center, max)

I typically use the second shorter form.

Edit:
However... going through the code it does appear there is a logic error with the second form's variable initialization. It's surprising I never discovered this before, because I've used this function for over two years. I'll correct that, and we'll see how it changes things. :)
 
If that happens outside the map script, why do other maps not have so many (if any at all) oasis clusters? And why do I get not a single oasis next to another if I use Stackpointer's code?
 
He used the function to a distance of 1, while I checked to a distance of 3. It spaces out the oases more. The difference is a logic error in my GetPlotsInCircle function. I used this statement to set maxR:

maxR = maxR or minR

This sets maxR when maxR is not passed to the function, but does not set minR, which remains as maxR. This means it checks tiles at a distance of 3, instead of distances from 1 to 3. I've fixed this error and I'm testing it now.


In short, it's an unintended bug, not an intended feature. This is a beta release of the map, and beta tests will usually have bugs. :)
 
@stackpointer
Floodplains are invisible and don't have a tile model. The GetPlotsInCircle function accepts two types of calls:

GetPlotsInCircle(center, min, max)
GetPlotsInCircle(center, max)

I typically use the second shorter form. However...

Sorry I could only find the following function at \Communitas Expansion Pack - Basic (v 3)\Tools\_ClassMethods\MT_Plot.lua and within the mapscript itself:

Spoiler :
PHP:
----------------------------------------------------------------
function Plot_GetPlotsInCircle(plot, minR, maxR)
	if not plot then
		log:Fatal("plot:GetPlotsInCircle plot=nil")
		return
	end
	maxR = maxR or minR
	local plotList	= {}
	local iW, iH	= Map.GetGridSize()
	local isWrapX	= Map:IsWrapX()
	local isWrapY	= Map:IsWrapY()
	local centerX	= plot:GetX()
	local centerY	= plot:GetY()

	x1 = isWrapX and ((centerX-maxR) % iW) or Constrain(0, centerX-maxR, iW-1)
	x2 = isWrapX and ((centerX+maxR) % iW) or Constrain(0, centerX+maxR, iW-1)
	y1 = isHrapY and ((centerY-maxR) % iH) or Constrain(0, centerY-maxR, iH-1)
	y2 = isHrapY and ((centerY+maxR) % iH) or Constrain(0, centerY+maxR, iH-1)

	local x		= x1
	local y		= y1
	local xStep	= 0
	local yStep	= 0
	local rectW	= x2-x1 
	local rectH	= y2-y1
	
	if rectW < 0 then
		rectW = rectW + iW
	end
	
	if rectH < 0 then
		rectH = rectH + iH
	end
	
	local adjPlot = Map.GetPlot(x, y)

	while (yStep < 1 + rectH) and adjPlot ~= nil do
		while (xStep < 1 + rectW) and adjPlot ~= nil do
			if IsBetween(minR, Map.PlotDistance(x, y, centerX, centerY), maxR) then
				table.insert(plotList, adjPlot)
			end
			
			x		= x + 1
			x		= isWrapX and (x % iW) or x
			xStep	= xStep + 1
			adjPlot	= Map.GetPlot(x, y)
		end
		x		= x1
		y		= y + 1
		y		= isWrapY and (y % iH) or y
		xStep	= 0
		yStep	= yStep + 1
		adjPlot	= Map.GetPlot(x, y)
	end
	
	return plotList
end
---------------------------------------------------------------------

Is that function defined in the that function will take the parameters plot, minR, and maxR.


Changing line 2404 from:
PHP:
	for _, adjPlot in pairs(Plot_GetPlotsInCircle(plot, 3)) do
to:
PHP:
	for _, adjPlot in pairs(Plot_GetPlotsInCircle(plot, 1, 3)) do

seems to work in my tests.



EDIT: Nevermind you found it.

It seems like "maxR = maxR or minR" would make it so if the maxR isn't defined in the function call (null?) that maxR would be set to minR. Basically making second initialization GetPlotsInCircle(center, min) instead.

Also, I'm not familiar with how LUA parses non binary types of OR evaluations? When evaluating "maxR or minR" when maxR is a non-zero it could immediately pass maxR without evaluating the other side of the OR statement? Which would have let the function work as intended whenever you passed it a minR and maxR.
 
The bug caused the shorter form to set maxR and minR to the same value. I forgot to set minR to 1. Replace "maxR = maxR or minR" with this:

Code:
    if not maxR then
        maxR = minR
        minR = 1
    end

I'm building the project to release this bugfix, and should have it out within a few minutes. :)
 
This is a beta release of the map, and beta tests will usually have bugs. :)
No problem! I hope I don't seem impatient or angry, I'm just trying to be as hard as possible with these things while we're in such an early stage. :) The average player doesn't generate maps over and over to try and find any anomalies, so chances are this would have gone unnoticed in the end, but it's good to nip these things in the bud while we're still on a level of simplicity.

If I remember correctly, there were a few bugs in GEM that were so entwined with different changes it was a big effort to quash them. I figure, the harder we are on the project now, the more we can enjoy it later. :D
 
Top Bottom