Platyping's Python

By Popular Demand:

Panama Canal
Spoiler :
PanamaCanal.jpg

It has been awhile since I took on a project with challenge :D
Been lazing around too much making simple ones...

What it does:
1) Opens up a new coastal route literally for ships to travel through.
2) It will choose the shortest distance to the opposite shore.
3) It will only choose vertical or horizontal direction because diagonal ones will just make fresh water lakes, where ships still cannot go through.
4) Marine Resources are added randomly as land plots are generally better than water ones, so compensation.

What it takes care of:
1) All non naval units on the transformed plots are thrown to the capital directly.
2) City plots are ignored
3) Bonus are replanted to the nearest city of the plot owner. (I only bothered to make sure they are planted in flatlands/hills appropriately, terrain wise too lazy)

What I have not bothered... yet:
1) Add a restriction to where it can be built. Currently there is a chance nothing happens, like if you build on an island...
2) I was thinking the canal should not be more than X tiles wide, else it becomes stupid as it makes your forces hard to move to the other side

Pictures speak louder than words:
Before1.jpg

After1.jpg

The dye is relocated

Before2.jpg

After2.jpg

So is the banana

Before3.jpg

After3.jpg

Even though there isn't a city directly adjacent to the stone, the nearest city is still found correctly :D
The good thing is some inland cities become coastal cities
The bad thing is some rivers are destroyed as seen in the last screenshot

As you can see, the first 2 cases are still ok.
But the last one, the canal is too long I believe. When it is THAT long, it becomes difficult for forces to cross the canal.

Artwork of canal by Kathy
 
Wow. That looks great!

btw. In the natural wonders thread I´ve seen, that you have made a code by yourself. I already found some posts about it but not the downloadfiles. are they included in one of your packs?
 
what our one? It hasn't been released just yet!
 
I released mine as Columbus' Discoveries.
A simplified version of what Jamie is trying to achieve.
 
So long as you are happy lol

After a good nap, time to wake up and finish off Panama:

Panama updated
Changes:
1) It is now maximum 4 Tiles wide.
When it is too wide like previously, it looks stupid.
If 4 Tiles still too wide, I can always adjust it to 3 Tiles.

2) Restrictions added to where you can build the canal.
In short, you can only build it where it is possible for the canal to spawn.
Requires cannotConstruct callback obviously

3) Removed spawning of Marine Resources.
Since it is max 4 Tiles Wide, I guess the XML benefits are enough to compensate.

4) Codes added for Rivers to flow naturally after the canal is dug.
See Pictures:
Before4.jpg

After4.jpg

Cow is still relocated appropriately.
River below flows nicely into the canal.

Before5.jpg

After5.jpg

The 1 river is cut into 2 rivers, but they both flow nicely into the canal as well.
Thanks to the canal, your ships can now reach the other side faster :D
Oh yeah, there is a cow on top that is relocated as well.

Thus, I can now stamp my name on this wonder and says, "Made by Platyping"
Considered Done :D

P.S.
I like the button pic, don't change it :D
 
Your wish is my command :D
XML effects removed, granted back 20% chance to spawn marine resources
Civ4ScreenShot0000-23.jpg
 
4 tiles? Seems way too much for me. Most world maps are scaled differently IMO
I would rather set it to 1 tile, but I guess it's easily adjustable in the code...

PS: What if you can build a canal both vertically and horizontically from a city?
The land is 4 tile wide in both direction. Which will be built?
 
I don't feel like going in the worldbuilder, but here is a basic example on a medium-sized island:

OOOOOOOOOOOOOOOOOO
OOXXXXXXXXXXXXXXOOO
OXXXXXXXXXXXXXXXXOO
OXXXXXXXXXXXXXXXXXO
OXXXXXXXXXXXXXXXXXO
OXXXXCOXXXXXXXXXXXO
OXXXXOOOXXXXXXXXXXO
OXXXXXOOOXXXXOXXXXO
OXXXXXXOOOOOOOXXXOO
OXXXXOOOOOOOOOXXXOO
OOXXXXXXOOOOOOXXXXO
OOOXXXXXOOOOOOXXXXO
OOOXXXOOOOOOOOXXOOO
OOOXXXXOOOOOOOXXOOO
OOXXXXOOOOOOOOXOOOO
OOOXXOOOOOOOOOOOOOO
OOOOOOOOOOOOOOOOOOO
 
If it is 1 tile, I will just build a fort and both ships and land units can pass through.
Then what is the point of building it to cut a coastal route and only ships can pass through?

What happens if there are 2 available directions with the same distance?
Depends how you arrange the codes.
Currently, it is W, E, N, S.
So if West is 3 tiles, East has to be 1 or 2 before it replaces West.
Can I add codes such that if West and East are both 3 tiles, then the choice is randomised?
Yes, if necessary

Edits:
Columbus' Discoveries:
Updated Sugarloaf graphics with Hrochland's lighter version

Crazy Horse Memorial:
Removed Peak Requirements, no longer need callback.
Although it is more accurate to have the peak, it doesn't really add value to the game, so might as well remove it for better performance.
 
I just wondered if you would check that these work "correctly" in your opinion (especially the mongol one):

Spoiler :

Code:
##Functions
def england(*args):
        "Power of the Church - State religion autospread to new/conquored cities"
        if len(args) == 3: #onCityAcquired
                pCity, eOwner, eNewOwner = args
        else: #onCityBuilt
                pCity, eOwner = args
                eNewOwner = eOwner
        if eOwner != eEngland != eNewOwner: return
        eEnglishReligion = pointer("England", CyPlayer).getStateReligion()
        bHasReligion = pCity.isHasReligion(eEnglishReligion)
        if eNewOwner == eEngland and not bHasReligion:
                pCity.setHasReligion(eEnglishReligion, True, True, True)                

def france(*args): 
        "Power of Chivalry - +1 relations with Civs of state religion"
        if args: #onChangeStateReligion
                iPlayer, iNewReligion, iOldReligion = args
                pPlayer = gc.getPlayer(iPlayer)
                if iPlayer != eFrance:
                        pFrance = pointer("France", CyPlayer)
                        if iNewReligion == pFrance.getStateReligion():
                                pPlayer.AI_setAttitudeExtra(eFrance, iFrenchRelations)
                        elif iOldReligion == pFrance.getStateReligion():
                                pPlayer.AI_setAttitudeExtra(eFrance, max(pPlayer.AI_getAttitudeExtra(eFrance)-iFrenchRelations, 0))
                else:
                        for pPlayer in CivPlayer.getPlayers(True, CyPlayer):
                                ePlayerReligion = pPlayer.getStateReligion()
                                if ePlayerReligion == iNewReligion:
                                        pPlayer.AI_setAttitudeExtra(eFrance, iFrenchRelations)
                                elif ePlayerReligion == iOldReligion:
                                        pPlayer.AI_setAttitudeExtra(eFrance, max(pPlayer.AI_getAttitudeExtra(eFrance)-iFrenchRelations, 0))
                return

        for iPlayer in CivPlayer.getPlayers(False, playerID):
                if iPlayer != eFrance:
                        pFrance = pointer("France", CyPlayer)
                        pPlayer = gc.getPlayer(iPlayer)
                        if pPlayer.getStateReligion() == pFrance.getStateReligion():
                                pPlayer.AI_setAttitudeExtra(eFrance, iFrenchRelations)
        
def spain(): #onGameStart
        "Power of Exploration - +1 movement for all naval units"
        pointer("Spain", CyTeam).changeExtraMoves(eDomainSea, iSpainMoves)

def hre(*args):
        "Power of the Empire - -10% courthouse cost, -10% maintenance"
        if args: #onCityBuildingBuilding
                pCity, iBuildingType = args
                if pCity.getOwner() == eHolyRomanEmpire and (iBuildingType == eCourthouse or iBuildingType == eRathaus):
                        iProduction = int(round((gc.getBuildingInfo(iBuildingType).getProductionCost()/100.0) * iHolyCourthouseCost))
                        pCity.changeBuildingProduction(iBuildingType, iProduction)
                return
        #onGameStart
        pHoly = pointer("Holy Rome", CyPlayer)
        pHoly.changeDistanceMaintenanceModifier(iHolyMaintenance)
        pHoly.changeNumCitiesMaintenanceModifier(iHolyMaintenance)
        

def byzantium(*args): #onCityBuilt
        "Power of Constantinople - New cities get free border pop"
        pCity, iOwner = args
        if iOwner == eByzantium:
                pCity.setCulture(eByzantium, (int(round(gc.getGameSpeedInfo(Game.getGameSpeedType()).getCulturePercent() * (iByzantineCulture/100.0)))), True)

def egypt(*args):
        "Power of Faith - +15% boost vs non state religion civs"    
        if args: #onUnitBuilt
                pUnit = args[0]
                if pUnit.getOwner() == eEgypt:
                        if gc.getUnitInfo(pUnit.getUnitType()).getCombat():
                                pUnit.setReligiousModifier(iEgyptianBoost)
        else: #onGameStart
                pEgypt = pointer("Egypt", CyPlayer)
                for iUnit in xrange(pEgypt.getNumUnits()):
                        pUnit = pEgypt.getUnit(iUnit)
                        if gc.getUnitInfo(pUnit.getUnitType()).getCombat():
                                pUnit.setReligiousModifier(iEgyptianBoost)
        
def turkey(*args): #onCityAcquiredAndKept
        "Power of Culture - Majority of foreign culture converted to turkish"
        iOwner, pCity = args
        if iOwner == eTurkey:
                iTurkishCulture = max((pCity.countTotalCultureTimes100()/100) * iTurkeyConvertPercent, pCity.getCultureTimes100(eTurkey))
                pCity.setCultureTimes100(eTurkey, iTurkishCulture, True)
                
def italy(*args):
        "Power of Trade - +2 trade routes in costal cities"
        if args:
                if len(args) == 3: #onCityAcquired
                        pCity, eOwner, eNewOwner = args
                else: #onCityBuilt
                        pCity, eOwner = args
                        eNewOwner = eOwner
                if eOwner != eItaly != eNewOwner: return
                iExtraRoutes = pCity.getExtraTradeRoutes()
                if eNewOwner == eItaly:
                        if pCity.isCoastal(-1):
                                pCity.changeExtraTradeRoutes(iItalianTradeRoutes)
                elif eOwner == eItaly != eNewOwner:
                        if pCity.isCoastal(-1):
                                pCity.changeExtraTradeRoutes(-iItalianTradeRoutes)
        else: #onGameStart
                for pCity in (city.GetCy() for city in pointer("Italy", PyPlayer).getCityList()):
                        if pCity.isCoastal(-1):
                               pCity.changeExtraTradeRoutes(iItalianTradeRoutes) 

def vikings(*args):
        "Power of Raiders - More gold from capturing/razing cities and pillaging"
        if len(args) == 2: #onUnitPillage
                iImprovement, iOwner = args
                if iOwner == eVikings:
                        iGold = int(round((gc.getImprovementInfo(iImprovement).getPillageGold()/100.0) * iVikingPercentMoney))
                        giveGold(iGold, eVikings)
                        if Game.getActivePlayer() == eVikings:
                                addMessage(sVikingMessage1, (str(iGold),), eGreen)
                        
        else: #onCityAquired
                iNewOwner, pCity, bConquest = args
                if iNewOwner == eVikings and bConquest:
                        iGold = pCity.getPopulation() * iVikingCityGold
                        giveGold(iGold, eVikings)
                        if Game.getActivePlayer() == eVikings:
                                addMessage(sVikingMessage2, (str(iGold), pCity.getName()), eGreen)

def mongols(*args): #onCityAcquired
        "Power of the Horde - Horse always present at capital"
        iPreviousOwner, iNewOwner, pCity = args
        if iPreviousOwner != eMongols != iNewOwner: return
        if iNewOwner == eMongols and pCity.isCapital():
                lPlots = getCityRadiusTiles(pCity)
                for pPlot in lPlots:
                        if pPlot.getBonusType(-1) == eHorse: return
                tCoords = getRandomCoords([pPlot for pPlot in lPlots if pPlot.getBonusType(-1) == -1])
                pPlot = getPlot(tCoords)
                pPlot.setScriptData("Mongol Horse")
                pPlot.setBonusType(eHorse)

        elif iPreviousOwner == eMongols:
                for pPlot in getCityRadiusTiles(pCity):
                        if pPlot.getScriptData() == "Mongol Horse":
                                pPlot.setScriptData("")
                                pPlot.setBonusType(-1)
                                pMongols = pointer("Mongolia", CyPlayer)
                if pMongols.isAlive():
                        lPlots = getCityRadiusTiles(pMongols.getCapitalCity())
                        for pPlot in lPlots:
                                if pPlot.getBonusType(-1) == eHorse: return
                        pPlot = getPlot(getRandomCoords([pPlot for pPlot in lPlots if pPlot.getBonusType(-1) == -1]))
                        pPlot.setScriptData("Mongol Horse")
                        pPlot.setBonusType(eHorse)
 
@England
Not sure why you have to define new args
Isn't it enough to just use "iPreviousOwner,iNewOwner,pCity,bConquest,bTrade = argsList" provided?
Also, I won't bother to check if city has the religion or not, I will just cut some if statements and add the religion to the city without checking if the city has it or not.
If the city has the religion, then nothing is going to change when you try to add the religion to it anyway, why bother to check.
Spiritual Trait

@France
I assume iFrenchRelation is 1?
It is hard to judge whether the codes are correct or not because, it depends what you want.
If France has no religion, and England has no religion, do they have +1 relation?
Also, is it supposed to be one-sided boost or 2 ways?
Means if France has Hindu, and England has hindu.
England definitely has +1 towards France, but does France have +1 towards England?
Something similar may be Lotus Temple, although that one uses Happiness

@Spain
As I mentioned before, Traits should not use "Team" because they will go haywire if you have games where there are > 1 member in the same team.
For example, if I start a game where Spain, England and France are in the same team, not only will Spain get the movement bonus, England and France will get it as well.
Edits:
Also, codes are in on GameStart only.
This means that if Spain does not exist initially, but is later liberated as a new colony, Spain gets nothing
Of course, if your mod is only playable as a scenario where neither of these will happen, then that's fine.


@HRE
onCityBuildingBuilding will trigger every time you choose to build the particular building.
In this case, you are adding production to the city every time the city chooses to build XXX.
So if I choose to build XXX, Y hammers are added.
Then I just switch to build YYY, cancel the XXX, hammers are still kept. Exploit number 1.
Then I switch back to XXX, hammers are added again. Exploit number 2...

You might as well use getBuildingCost and reduce it.
changeDistanceMaintenanceModifier and changeNumCitiesMaintenanceModifier, are there such functions? I assume these are new ones you defined, so how I know if they work lol

@Byzantine
Since I dunno what is iByzantineCulture, no idea
Creative Trait

@Egypt
Same, no idea what setReligiousModifier is supposed to do, so can't tell.
Edit:
Although I not sure what setReligiousModifier does, an obvious error is that this is defined in on Unit Built.
There are cases where you get Units without Building. Drafting is one example.
Use on Unit Created, although that requires callback.

But for the GameStart part, it is always better to use the while loop method rather than for loop.
Sometimes for loop point to units which are None, reason I don't know :D

@Turkey
Never use countTotalCultureTimes100 before, so not sure of the outcome.
But looking at the max comparison, there is definitely a logic error.
If pCity.getCultureTimes100(eTurkey) is the bigger number, like Turkey owns 90% of the culture, then max will choose this number.
Then pCity.setCultureTimes100 is going to set it to the same culture that Turkey has already owned.
In other words, none of the 10% of foreign culture is going to be converted.
Helsinki Cathedral

@Italy
You know... there is this changeCoastalTradeRoutes function, which adds the coastal trade route to ALL Coastal cities of the player itself.
Just do it once on Game Start, and on First Contact for newly liberated ones, and you are done.
Organized Trait

@Viking
def doPillageGold and def doCityCaptureGold
You may want to use these in CvGameUtils instead.
Then you can adjust the captured/pillage gold by a % easier
Himiji Castle

@Mongol
I don't really get this part.
You are defining it on City Acquire
if iNewOwner == eMongols and pCity.isCapital():
Then when will this be true?
I don't think on CA codes are activated when you build a city.
Thus, when will you ever capture a city and that city is actually a capital?
It will not be YOUR capital because you obviously have one.
It will not be THEIR capital because it is shifted before on CA codes are activated.

Anyway, this "Horse always present at capital" is hard to code.
Because when I build my first city, it is my capital, so lets say a horse is now planted in one of the plots there, yeah happy.
Now I build a palace in my second city, the capital is now shifted.
So what now, do I lose my horse in the first city, and do I get a new source of horse in the second city?

Anyway, there are only codes in on CA, no codes elsewhere.
So, shifting of capital is not going to trigger any of the codes
 
HI , I have one question. My desert mountain to appear occasionally on peak. How can I disable it ? thanks, Hroch

Sorry, I don't understand this one.
Is it referring to any of the works I done?
 
just so you know, these powers relate to a senario.

Code:
##Constants
iSpainMoves = 1
iFrenchRelations = 1
iHolyCourthouseCost = 10
iHolyMaintenance = -10
iByzantineCulture = 10 #Fledgling
iEgyptianBoost = 15
iItalianTradeRoutes = 2
iVikingPercentMoney = 25
iVikingCityGold = 10
sVikingMessage1 = "You have received %s1 extra gold from pillaging!"
sVikingMessage2 = "You have received %s1 extra gold from the capture of %s2!"
iTurkeyConvertPercent = 75

anyway the reason I define new args is so I can differentiate between different events (and only use what I need, somethin gI learnt from baldyr way back when :p)

the realtions are onesided, france will not like england more just england likes france more. and yes if both are non state religion france is liked.

though your comment about teams making sense, I think that the CyPlayer class doesn't provide changeExtraMoves unfortunatly. But as it's a senario teams can't be formed so it should be fine I guess they can share their knowledge of better ships

I forgot about the maintenance cost methods. It was something asaf exposed to python years ago. Not sure what you mean when you suggest how to fix the exploits?

you didn't need to worry about the setReligiousModifer, it is a new feature that allows units to get a combat boost vs opposite state religions :evil: anyway, surely if it is the start of the game then no units will have been lost so all the indexes would not be None? I did have you in mind when I wrote that :p

nice catch on the Turkey power!!! Thanks! yeah the Times100 method as I described somehwere around here is just the value timed by 100. The theory I had is that it allows decimal culture values by setting to 231 (instead of illegal 2.31) it can work. So the question is... How do I get the remaining foreign culture?

Thanks for the italy catch, gonna have to try that one out. Not sure what do with the onFirstContact? does it work when a city is captured?

I will take a look at those two methods

The mongol power is a bit of an odd one. It actually works as far as I can see. The idea is in the senario the mongols are dead. They become alive as part of an event and spawn with an army. therefore the iNewOwner and capital represents their first captured city (they cannot build settlers). but I didn't think about if the mongol AI actually moves their capital... gotta fix that at somepoint once again thanks
 
Sorry, I don't understand this one.
Is it referring to any of the works I done?

ah, sorry. Desert mountain is one from my natural wonders.
this line
"FEATURE_HORAPOUST":["TERRAIN_DESERT", False, None, None, None, None, None, None, False],\

the fifth position is bpeak - I have NONE, but my the desert mountain sometimes appears on. We can prevent it somehow , please?
 
@France
If it works for No Religion as well, then shouldn't there be codes on GameStart, as well as First Contact for newly liberated ones, since everyone starts with no Religion anyway.

@Egypt
The edited comments in red

@Building Cost
Use the part in CvGameUtils
That one requires callback though.
If Granary is 60 Hammers, and you adjust it to 10% Discount, it will correctly display it as 54 Hammers, rather than all these additions of free hammers and exploits.
 
@hrochland

None means it doesn't matter You need to set it to false so it doesn't ever spawn on peaks!
 
Back
Top Bottom