Celtic Mod v2.0 Release

The core of the problem remains that the English have nowhere to expand, right? The question is why the English AI feels the need to expand beyond the cities they flip/conquer... Maybe you could point them in a less annoying direction with the Settler maps or something? Make northern Africa or something a desirable location to settle, or somewhere they will inevitably get taken over...

Right now they seem to favor areas belonging to other Civs. I wonder why some Civs (like the Russians) tend to turtle up as they do and not found any cities, while the English both build Settlers and use them. They will actually build ships, load those and send eastward! :eek: The Celts certainly wasn't doing that when you had them in Gaul...

I honestly have no idea whatsoever what makes the AI do these bizarre things. Other than the Settler maps or the like. :confused:

In my own Russia scenario the AI is dead set against expanding into Siberia even if I spawn free Settlers for them. They first build any feasible city in European Russia, so that one could have to do with the continents being defined as different "areas" in the game.

edit: Ah, could it be that Rhye has coded the English AI to actually pursuit their UHV? They need to build a number of cities on every continent, right? So they are simply fulfilling the condition of founding cities in Europe, since you took away their home areas.
 
the celts now start with two settlers, which they tend to send to europe (fine). The british settler maps were only changed to increase ireland from "very desirable" to "highly desirable." perhaps they just shy from amphibious invasions with 2-unit galleys...i just wish they'd concentrate on building more culture...it would help them take ireland regardless of whether or not the celts are around, and definitely help them with france...
 
not to mention once they get caravels they can't use them for invasions and have to wait for astronomy
 
i could potentially script "if irish cities are independent or barbarian in 1600 they automatically become english" but 1) that gives away free cities and 2) takes away the fun for the anglophile player in crushing the irish :rolleyes:
 
edit: Ah, could it be that Rhye has coded the English AI to actually pursuit their UHV? They need to build a number of cities on every continent, right? So they are simply fulfilling the condition of founding cities in Europe, since you took away their home areas.
So, if I was to device a solution to this possible issue, I could take one of two available approaches:

1. Try and make city flips count as "founded" cities. This could either be a global change to the code (affecting all spawns for all Civs) - or an exception that only affects the English.

2. Utilize a function sometimes used in Rhye's own code in order to kill everything in an area (like Britain) so that the English AI can settle those cities by itself. This would only happen if the human player hasn't got any cities in that area! Other than that the result as for the setup of Britain would be about the same - the isle would still be populated and the Celts would loose their dominance.

What do you think?
 
the english uhv only specifies founded cities in
bNCAmerica = self.checkFoundedArea(iEngland, tNCAmericaTL, tNCAmericaBR, 3)
bSAmerica = self.checkFoundedArea(iEngland, tSAmericaTL, tSAmericaBR, 3)
bAfrica = self.checkFoundedArea(iEngland, tAfricaTL, tAfricaBR, 3)
bAsia = self.checkFoundedArea(iEngland, tAsiaTL, tAsiaBR, 3)
bOceania = self.checkFoundedArea(iEngland, tOceaniaTL, tOceaniaBR, 3)
if (bNCAmerica and bSAmerica and bAfrica and bAsia and bOceania):
self.setGoal(iEngland, 1, 1)

none in europe or the isles...

I think it's just the ai trying to expand without war before it has the boats to do it. my concern is that even with an empty britain, they would do what the celts were doing and found london and still take their other settlers to the continent...
 
Well, I was also having a problem with the vikings not expanding and leaving scandinavia empty to modern times...they'd go into eastern europe...so I've spawned four cities in scandinavia, one of each indy and two barb...should get them to expand while preventing the english from going there. then i'm done...the russians are on their own...
 
Ok... False alarm. I checked up the UHV code for the English an they are in fact not required to build any cities in Europe. I should just have checked that up right away...

So, no, I don't have a clue about why the English will spam Settlers and settle them in Europe.

Maybe I could create a code that kills any English Settler once it is built - until a certain date or other setting (like Astronomy)? It would surely take care of the problem, but there could also be a actual need for settling cities on the isles (if the spawned ones have been razed). To avoid issues like this the code could just look for English Settlers in Galleys - and kill them off!

Straight forward enough?
 
that could work, but I don't want to limit the human. still, i'm sure you're going to tell me that it can be flagged to only affect the ai (am I catching on yet? lol). I'm going to run a test with the four scandinavian cities as that may be killing two birds with one stone. I'll be away for the weekend (Irish language immersion program), and then I'll reassess when I get back...
 
you know...easier than that...why can't i then write code for "if english is AI and X city is indy or on Y turn, city becomes english" with X being either a city name or tile location? That would give them three more cities, hopefully mitigating the need to expand in the event of a celtic collapse (something like Teamhair na Rí on 1400, Corcaigh on 1500 and Gaillimh on 1600), while still making the human conquer Ireland manually
 
Oh, thats very simple. You use this statement to ask the code whether the Celts are controlled by the human:
Code:
if (pCeltia.isHuman()):
...and this code whether the Celts are controlled by the AI (not human):
Code:
if (not pCeltia.isHuman()):
You need to understand how indentation works in Python in order to get it to work though, but thats pretty much the first thing one should learn about Python. :rolleyes:

So if you, as an example, wanna except the Dublin spawn to only happen if the Celtic player is an AI, your Barbs.py code would look like this (changes and additions marked):
Code:
                self.foundCity(iIndependent, lLyon, "Lugodunon", iGameTurn, 2, con.iCelticGallicWarrior, 2)
[COLOR="Red"]                if (not pCeltia.isHuman()):
                        self.foundCity(iIndependent, lDublin, "Teamhair na Rí", iGameTurn, 2, con.iCelticGallicWarrior, 2) [/COLOR]
                self.foundCity(iIndependent, lCardiff, "Caerdydd", iGameTurn, 2, con.iCelticGallicWarrior, 2)
Did you want me to kill off any English AI Settler on the same tile as a Galley (city tiles could be excepted)? Because I could code this for you over the weekend so that you would be able to test it out next week...

Spoiler :
Will the Baldyr finally get to do some Python on this modmod? This is the question. :lol:
 
you know...easier than that...why can't i then write code for "if english is AI and X city is indy or on Y turn, city becomes english" with X being either a city name or tile location? That would give them three more cities, hopefully mitigating the need to expand in the event of a celtic collapse (something like Teamhair na Rí on 1400, Corcaigh on 1500 and Gaillimh on 1600), while still making the human conquer Ireland manually
What you're basically describing is a somewhat enlarged spawn zone for the English, then. This could be done quite easily as an exception affecting only the English AI. (You add or substract some number to their X and/or Y coordinate or coordinates, enlarging or decreasing the spawn area.)

Or would you wanna make cities change hands on specified turns - and not on the third turn after the initial spawn?

Which ever is of course possible to code, its merely a task of finding out which one is simpler to do and which one will be more efficient.
 
lol...alright, you want a custom project, here it is:

on turn i1400ad

see if england is human

if England is AI

see if lDublin (as defined in barbs.py - although this may acutally be one tile south of the celts start, in which case the celts start should be used) is Independent, Independent2 or Barbarian

if yes, flip to england

do the same for lGalway in i1450ad and iCork in i1500ad


It can't be a few turns after the english spawn because sometimes the ai celts don't collapse for centuries (if at all) and i want to give them a chance to make alternate history...it's just that if they do collapse, we're back to real history so we might as well make it look that way. They almost never collapse right away.
 
Dublin is one tile south...in consts.py I defined tTara as 49,57 with Átha Cliath (dublin) at 49,56 in barbs...the english will rename both of them "Dublin" and if they take it back, the celts will rename Dublin "Átha Cliath," which would be historically accurate
 
I could probably use that to fix the russian issue as well, but once i have code to model it on it can do that...something like, "if russia and germany are both ai, and if cities X XX and XXX are german, flip them russian on date YYY"

sort of like a one-time "reality check." i think this was why rhye included a 600 ad start in the first place, because the AIs rarely do what you want them to do in the long term, and if you're interested in endgame the world should at least loosely look like what you'd expect
 
Ok, I'm looking into how to best implement this and there is also the matter of culture presence to consider. I should however have something for you to try out once you come back.

What should happen to the units in the city, by the way. Would they be killed off, or flip also? In the units don't flip also there would have to be units spawning - those would also have to be specified for each city. Or maybe they should always be the default city defender for that Civ at that juncture? How many units are sufficient? Or would this be set on a case by case basis?

I imagine you wanna keep things as simple and straight forward as possible...
 
I'm actually thinking you need something to use for flipping entire areas on the map, since you wouldn't know exactly where those German cities in Russia would be located. So you could basically search the Russian Core Area for any German cities, then.

This would be quite different from simply checking if Dublin is owned by a minor Civ.

It wouldn't be so practical to use the same code or function for both purposes, so I think I'll just focus on the city flips on the Isles for now. If you need another one to correct the ownership in Russia... then I could always give them a second spawn at a specified date! :D
 
on turn i1400ad

see if england is human

if England is AI

see if lDublin (as defined in barbs.py - although this may acutally be one tile south of the celts start, in which case the celts start should be used) is Independent, Independent2 or Barbarian

if yes, flip to england

do the same for lGalway in i1450ad and iCork in i1500ad
So I took a closer look at what Rhye had already done with this mod, and he has defined (each starting with "def") literary 100s of functions! I believe the flipCity function in RFCUtils.py do what you want to achieve, so there should be no need for me to make my own function for this particular task.

So in order to get the city flips you requested, add this piece of line somewhere after "def checkTurn(...):" in Barbs.py:
Code:
                #Minor secessions to England
                pEngland = gc.getPlayer(con.iEngland)
                if (pEngland.isAlive() and not pEngland.isHuman()):
                        if (iGameTurn == con.i1300AD):
                                utils.flipCity(lDublin, True, True, con.iEngland, lMinors) #Teamhair
                                utils.flipCity(con.tCapitals[iCeltia], True, True, con.iEngland, lMinors) #Tara
                        if (iGameTurn == con.i1450AD):
                                utils.flipCity(lGalway, True, True, con.iEngland, lMinors)
                        if (iGameTurn == con.i1500AD):
                                utils.flipCity(lCork, True, True, con.iEngland, lMinors)
I included a separate flip for both locations of Dublin, but you could probably delete one of them. You could also add more flips if you like - it should be pretty straight forward. Just follow the indentation modeled above and you should be fine.

Note that I reused your list variables for the cities in order to get their coordinates, but I could have added them manually like "[49, 57]" also. Speaking of which, you also need to define the last argument, which is another list variable called "lMinors". Add this definition somewhere at the beginning of Barbs.py:
Code:
lMinors = [iIndependent, iIndependent2, iBarbarian]
Or you could just add the contents of the list directly to each utils.flipCity() function like: "[iIndependent, iIndependent2, iBarbarian]"

The utils.flipCity() function has some features to it, if you wanna learn how to get the most of it. If you take a look at the function itself you'll find that Rhye has actually supplied documentation! (The red text doesn't apply. By the way, the "!=" bit is the opposite of "==" (equal) to and thus means basically "not".)
Spoiler :
Code:
        def flipCity(self, tCityPlot, bFlipType, bKillUnits, iNewOwner, iOldOwners):
                [COLOR="Green"]"""Changes owner of city specified by tCityPlot.
                bFlipType specifies if it's conquered or traded.
                If bKillUnits != 0 all the units in the city will be killed.
                [COLOR="Red"]iRetainCulture will determine the split of the current culture between old and new owner. -1 will skip[/COLOR]
                iOldOwners is a list. Flip happens only if the old owner is in the list.
                An empty list will cause the flip to always happen."""[/COLOR]
                pNewOwner = gc.getPlayer(iNewOwner)
                city = gc.getMap().plot(tCityPlot[0], tCityPlot[1]).getPlotCity()
                if (gc.getMap().plot(tCityPlot[0], tCityPlot[1]).isCity()):
                        if not city.isNone():
                                iOldOwner = city.getOwner()
                                if (iOldOwner in iOldOwners or not iOldOwners):

                                        if (bKillUnits):
                                                killPlot = gc.getMap().plot( tCityPlot[0], tCityPlot[1] )
                                                for i in range(killPlot.getNumUnits()):
                                                        unit = killPlot.getUnit(0)
                                                        unit.kill(False, iNewOwner)
                                                        
                                        if (bFlipType): #conquest
                                                if (city.getPopulation() == 2):
                                                        city.setPopulation(3)
                                                if (city.getPopulation() == 1):
                                                        city.setPopulation(2)
                                                pNewOwner.acquireCity(city, True, False)
                                        else: #trade
                                                pNewOwner.acquireCity(city, False, True)
                                                
                                        return True
                return False
There is also a function for creating era appropriate defensive units in cities (like after a flip):
Spoiler :
Code:
[COLOR="SeaGreen"]        def createGarrisons(self, tCityPlot, iNewOwner, iNumUnits):[/COLOR]
                plotCity = gc.getMap().plot(tCityPlot[0], tCityPlot[1])
                city = plotCity.getPlotCity()    
                iNumUnitsInAPlot = plotCity.getNumUnits()
                pCiv = gc.getPlayer(iNewOwner)

                if (gc.getTeam(pCiv.getTeam()).isHasTech(con.iAssemblyLine) and gc.getTeam(pCiv.getTeam()).isHasTech(con.iRifling)):
                        iUnitType = con.iInfantry
                elif (gc.getTeam(pCiv.getTeam()).isHasTech(con.iRifling)):
                        if (iNewOwner != con.iEngland):
                                iUnitType = con.iRifleman
                        else:
                                iUnitType = con.iEnglishRedcoat
                elif (gc.getTeam(pCiv.getTeam()).isHasTech(con.iGunpowder)):
                        if (iNewOwner != con.iFrance):
                                iUnitType = con.iMusketman
                        else:
                                iUnitType = con.iFrenchMusketeer
                else:
                        iUnitType = con.iLongbowman

                self.makeUnit(iUnitType, iNewOwner, [tCityPlot[0], tCityPlot[1]], iNumUnits)
Ask for support if you can't figure out for yourself how to use it. (Because you should, by comparing the definition line of both functions. You can always ignore the "self" argument, by the way.)

There is no reason for you not to understand how I used the function and why my code looks like it does. If something in particular is unclear I could explain.
 
I actually have some custom code you could use in your modmod if you like. :king:

Since the limitations built into Rhye's own foundCity() function wasn't allowing me to do what I needed to achieve in my own modmod I created my own custom function. While Rhye's function is located in the Barbs.py file (and thus called with the prefix "self."), mine is located on another file altogether called Custom.py and need therefore to be imported into the Barbs.py file. This is achieved by adding this line somewhere after "from CvPythonExtensions import *" (line #3):
Code:
import Custom
And by adding this definition after the "# globals" comment line (#11) you can use the prefix "custom." to call on my function like "custom.foundCity()":
Code:
custom = Custom.Custom()
The actual Custom.py file can be downloaded from this post - and there is also full documentation available.

The reason you might wanna use my function instead of Rhye's is that it gives you more options (like pre-building Duns in your spawned cities) and also the power to force spawns regardless of the normal limitations. (This setting is enabled or disabled on a city by city basis, so you could still use it to achieve exactly what the default function will give you, plus any extra feature you'd wanna use.)

One benefit from the custom.foundCity() function to your modmod could be to make all the Celtic city spawns actually belong to the Celtic Civ. It should be noted however that when the Celts are controlled by a human player these spawns actually become random independents instead. What this would give you is a greater challenge for the Roman, English and other players in your mod - when played by the human.

Once the Celts collapse - and they will whenever they lose at least half of their cities within a short period of time - you still get the fragmentation into independents that you have now by default. Its just a suggestion, but don't be surprised if I post this very setup as a, well... modmod to your modmod :rolleyes: once you've done your definitive release. :mischief: (Note how non-consolidated peoples like the Germans or the Vikings get to show a united front in RFC and in Civ in general. Why should an AI Celtia be any different?)

Lastly, you could just use the Barbs.py file included in the download (link above) as it already has the stuff you need to use the custom function. Then you could transfer all the settings for your city spawns to the new file, as you need to reformat everything to fit into the new function anyway. I also suggest you add the two Viking spawns included as examples into your modmod, as they are historical spawns. (Cities like Oslo, Göteborg or Stockholm are actually relatively modern and not as suitable in the Middle-Ages.)
 
Back
Top Bottom