Are you, in fact, a pregnant lady who lives in the apartment next door to Superdeath's parents? - Commodore

Create an account  

 
Hall of Mirrors Map Script

First question: how to put restrictions on starting plots.

Answer: something like this (warning, the quoted text has its own scrollbar):

Code:
# ADD AND CUSTOMIZE THE FOLLOWING FUNCTION
# EXAMPLE: ONLY ALLOW CAPITALS EXACTLY 6 TILES FROM THE LEFT/RIGHT
def allowStartingPlot(iPlayer, iX, iY):
    return iX == 5
    
def assignStartingPlots():
    gc = CyGlobalContext()
    global sliceCount
    global sliceW
    global mapH

    # Let the game choose one start location
    # PASS YOUR FUNCTION IN AS THE SECOND ARGUMENT (FIRST ONE IS IRRELEVANT, AS BEFORE)
    seedPlot = CyMap().plotByIndex(CvMapGeneratorUtil.findStartingPlot(0, allowStartingPlot)) #id param shouldn't matter

...
Reply

For mirroring and normalizing properly, I think it's tricky. I believe the map script doesn't get called again after normalization, which means that you need to override the normalization itself. You can look at Mirrorland for an example of this - it rolls its own normalization criteria though rather than just re-implementing the BTS ones. Torusland also has its own criteria and I think they are better (but it doesn't mirror).

Rewriting and overriding the normalization isn't that wasteful a thing to do, because IMO the BTS normalization is annoying and ugly and poorly tuned. In addition, mirrored maps have different requirements for what's a valid normalization than unmirrored maps. But it takes some work.

I'll see if I can look into the river stuff later tonight or tomorrow.
Reply

(November 9th, 2014, 20:33)Ruff_Hi Wrote:
(February 19th, 2013, 22:15)Qgqqqqq Wrote: Could someone reupload this?

Thanks!
Erebus in the Balance - a FFH Modmod based around balancing and polishing FFH for streamlined competitive play.

Reply

OK, with the rivers intersecting the middle of the map you have a couple options. First, you can just leave it as is - it's harmless, if ugly.


Second, I've tested the following and it works.
1) After generating the to-be-mirrored plots, fill up the rest of the map with mountains (it's ocean by default).
Code:
        for x in range(sliceW, self.iW):
            for y in range(0, self.iH):
                iWorld = y*self.iW + x
                self.wholeworldPlotTypes[iWorld] = PlotTypes.PLOT_PEAK
2) In the river-mirroring code, put back the code which zeroes out river data.
Code:
                    if pPlot.isNOfRiver():
                        rivDir = pPlot.getRiverWEDirection()
                        if rivDir == CardinalDirectionTypes.CARDINALDIRECTION_WEST:
                            rPlot.setNOfRiver(True, CardinalDirectionTypes.CARDINALDIRECTION_EAST)
                        else:
                            rPlot.setNOfRiver(True, CardinalDirectionTypes.CARDINALDIRECTION_WEST)
                    else:
                        rPlot.setNOfRiver(False, CardinalDirectionTypes.CARDINALDIRECTION_WEST)
(And a similar last two lines added in the NS river copying code.)

The result of all this is that now any rivers that touch the center line have that line as their source instead of their destination. So now you have a different weirdness - rivers that appear in the center of the map and flow in both directions towards bodies of water. Graphically it looks a bit nicer, but maybe it's not that much of an improvement.

This solution might also impact the quantity/distribution/variance of rivers, although it seems like it should have little effect.


The third option is to take the river-placing code I wrote in Mirrorland/Torusland and use it, or a variation, to just redo river placement entirely.
Reply

Another more pragmatic option is to just keep retrying until you randomly come across a configuration that meets your criteria. I did a bit of that when I mucked about with my own map script. Ideally, though, you want to somehow narrow the search space with each attempt so that you are actually guaranteed to terminate at some point. For example, I randomly generated continent shapes until I came up with something satisfactory, slightly reducing the amount of land after each failed attempt.

So in this scenario, you would need to write code to clear all rivers from the map, and code to check if there are any undesired river segments/artifacts caused by mirroring, and a simple loop. If there is also a way to tell the river placement code how many river segments to place, you can reduce that number for each failed attempt, and you have all the ingredients you need.
If you know what I mean.
Reply

Thanks all for the comments. I am going to digest them and see what I get. The re-normalization is nuts as I had a version of the map that didn't to that. I'll see if I still have that and then look at what I changed to 'break' it.
I have finally decided to put down some cash and register a website. It is www.ruffhi.com. Now I remain free to move the hosting options without having to change the name of the site.

(October 22nd, 2014, 10:52)Caledorn Wrote: And ruff is officially banned from playing in my games as a reward for ruining my big surprise by posting silly and correct theories in the PB18 tech thread.
Reply

I've done some tiding up with the attached. Also added some comments where I changed the code.

I tried the 'restrictions on starting plots' Seven mentioned and it didn't work at all. The game just ignored any option I put in and put the 2nd player where ever it wanted to.

Currently the maps mostly generate mirrored starts. Everyone now and then they are a little different. Where is the code that 'normalizes' the starts?


Attached Files
.zip   Hall_of_Mirrors_Ruff3.zip (Size: 5.26 KB / Downloads: 2)
I have finally decided to put down some cash and register a website. It is www.ruffhi.com. Now I remain free to move the hosting options without having to change the name of the site.

(October 22nd, 2014, 10:52)Caledorn Wrote: And ruff is officially banned from playing in my games as a reward for ruining my big surprise by posting silly and correct theories in the PB18 tech thread.
Reply

The reason it's ignoring your code is that you miscapitalized "iX" as "ix". That causes an error and it falls back to the default functionality.

You can catch errors like this by looking at the debug output. Go to your My Games/beyond the sword folder (or, go to your save games folder and go up levels until you are in beyond the sword). In your CivilizationIV.ini file, find the following text and change the 0 to a 1:

Quote:; Enable the logging system
LoggingEnabled = 0

Now after running your map script you can (still from your beyond the sword folder) look in Logs/PythonErr.log.

PythonDebug.log is also useful. You can add print statements to your code and it will be output there.
Reply

After the map is generated and starting positions are assigned, the last thing your script gets to do is potentially override the default behavior for various normalizeBlahBlahBlah functions. In your script, these functions are listed in the file in the order that the game calls them. For each of these, if you allowDefaultImpl() then the C++ code will run, otherwise it won't.

Some of the C++ functions have random elements. These are normalizeRemoveBadTerrain, normalizeAddFoodBonuses, normalizeAddGoodTerrain, and normalizeAddExtras. If you allow these to run, there can be differences between the starts. The BTS default script Mirror just prevents all the normalizations functions from running at all.

It occurs to me that the only purpose of the last function called, normalizeAddExtras, is to balance between starts of different strengths, which is obviously not needed on a mirrored map. So I think the right solution is to just override normalizeAddExtras with a function that re-applies the mirroring of the map.
Reply

(November 12th, 2014, 16:29)SevenSpirits Wrote: The reason it's ignoring your code is that you miscapitalized "iX" as "ix".

Duh! Thanks for pointing that out.

I use to use logging extensively when we were working on BUG. We even built logging at different levels (user defined) into the BUG code for this very reason. It will be strange to have to revert to a non-BUG version of logging. I'll see if I can code without it for a little longer.

(November 12th, 2014, 16:49)SevenSpirits Wrote: After the map is generated and starting positions are assigned, the last thing your script gets to do is potentially override the default behavior for various normalizeBlahBlahBlah functions. In your script, these functions are listed in the file in the order that the game calls them. For each of these, if you allowDefaultImpl() then the C++ code will run, otherwise it won't.

Some of the C++ functions have random elements. These are normalizeRemoveBadTerrain, normalizeAddFoodBonuses, normalizeAddGoodTerrain, and normalizeAddExtras. If you allow these to run, there can be differences between the starts. The BTS default script Mirror just prevents all the normalizations functions from running at all.

How do you know about these C++ functions? Are they in every map script?

Quote:It occurs to me that the only purpose of the last function called, normalizeAddExtras, is to balance between starts of different strengths, which is obviously not needed on a mirrored map. So I think the right solution is to just override normalizeAddExtras with a function that re-applies the mirroring of the map.

If I understand this correctly ... I think you are saying that I could do this ...

Code:
def afterGeneration():
    return mirrorizePlots()

def mirrorizePlots():
    # MIRRORIZE PLOTS
    map = CyMap()
    etc for the balance of what was in 'def afterGeneration():'

... and then call mirrorizePlots again from normalizeAddExtras() ...

Code:
def normalizeAddExtras():
    return mirrorizePlots()
#    return None

It is a bit redundant, but it should be fairly quick.
I have finally decided to put down some cash and register a website. It is www.ruffhi.com. Now I remain free to move the hosting options without having to change the name of the site.

(October 22nd, 2014, 10:52)Caledorn Wrote: And ruff is officially banned from playing in my games as a reward for ruining my big surprise by posting silly and correct theories in the PB18 tech thread.
Reply



Forum Jump: