12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363 |
- #-----------------------------------------------------------------------------
- # Copyright (c) 2005-2008 Laurent Di Cesare
- # Copyright (c) 2008 Firaxis Games, Inc. All rights reserved.
- #-----------------------------------------------------------------------------
- #
- # FILE: Tectonics.py
- # AUTHOR: Laurent Di Cesare (LDiCesare)
- # PURPOSE: Provide a map with mountain ranges, preferably near the coasts.
- # DESCRIPTION:
- # Provide a map with several continents, possibly some big islands,
- # and simulates some very rough plate tectonics to generate mountain ranges.
- # The map is tuned to generate about 40% land and 60% water but only the
- # number of plates is fixed, not the actual size of the plates, so landmasses
- # sizes may vary quite a bit.
- # It is an adaptation to CivIV of an algorithm originally developped for
- # the Clash of Civilizations (http://clash.apolyton.net)
- # VERSION 1.0 Initial version
- # VERSION 1.1 Changed the moveplates and blur routines to avoid having
- # big lumps of peaks propagating everywhere.
- # Added subduction
- # Hinted continents seeds to avoid the poles
- # VERSION 2.0 Added climate management.
- # VERSION 2.1 Made desert edges rougher.
- # Added first try at rivers.
- # Increased subduction
- # VERSION 3.0 Added various landmasses (Pangaeas, Lakes, Islands).
- # Modified rivers
- # VERSION 3.1 Lost when reinstalling windows and not backing it up.
- # It was great, though.
- # VERSION 3.2 Provided new option for Earthlike, and grouped land masses
- # so 2/3rds are on the same hemisphere. Less ice.
- # VERSION 3.3 Systematic use of climate map because I had bugged it away for
- # the main map type instead of pangaea. Tried to prevent players
- # from starting in the ice. Added hotspots.
- # VERSION 3.4 Minor rewritings.
- # Added fault lines: Some hills and lakes will pop up inside
- # vast flat areas, forming a ridge line, but with lots of flat
- # lands inside. Not always noticeable but has a definite effect.
- # Corrected climate generation which didn't blow enough moisture.
- # VERSION 3.5 Added several climate options. Tuned the starting locations.
- # VERSION 3.6 Roughed the edges of the various climate zones to avoid excess
- # of straight limits.
- # Added Mediterranean land type (inner sea).
- # Added No Ice option that replaces ice with tundra and tundra
- # with grass, otherwise behaves as normal humidity level.
- # VERSION 3.7 Mediterranean map rewrite: East is always land, more and bigger
- # islands, correct latitude used for feature generation.
- # VERSION 3.8 Fixed WrapY error.
- # VERSION 3.9 Fixed subduction error.
- # VERSION 3.10 Shapes of plates are somewhat less square, and rivers in desert
- # are always floodplains even after the default algorithm adds
- # them near players' starting location
- # VERSION 3.11 Climate generation rewritten, rivers less likely to start
- # in desert and more often from hills.
- # VERSION 3.12 Broke east-west climate lines, smoothed desert-grass
- # transitions always through plains.
- # VERSION 3.13 More mountains (second pass of movePlates). Terra option.
- # VERSION 3.14 Fixed starting plot generation errors.
- # VERSION 3.15 Added an option not to group civs on Terra option,
- # Tuned Terra landmasses (mostly Africa, Greenland), removed
- # Antarctic landmass (too many barbs spawning there).
- # VERSION 3.16 Included Firaxis code for translating the options.
- # Kept my copyrights.
- # Added more rivers. (Also aborted try at heghtmap for rivers.)
- # Updated the Terra option to have much better looking Arabia.
- # TODO The shape of the plates should be less polygonal and more random
- # (more round than rectangular)
- # The number of plates could be more tunable.
- # I could also rewrite the whole rivers thing...
- # Modified by Terkhen
- # VERSION 3.19_mst - 21.Sep.2016
- # - Fixed [Planetfall], do not use snow and desert terrain, use their Planetfall equivalents instead.
- #
- # Modified by Terkhen
- # VERSION 3.18_mst - 17.Aug.2016
- # - Fixed, use terrain, feature and improvement definitions from MST.
- #
- # Modified by Terkhen
- # VERSION 3.17_mst - 08.Dic.2014
- # - Added, save/load map options.
- # - Added, compatibility with RandomMap.
- # - Changed, resource balance option.
- # - Changed, use TXT strings instead of hardcoded ones.
- #
- # Modified by Temudjin
- # VERSION 3.16a_mst - 15.Mar.2011
- # - Fixed, the land/water percentages are somewhat more realistic now
- # - Fixed [Planetfall], tried to lumpify normal terrain in 'Planetfall'
- # - Fixed [Planetfall], now compatibile with Planetfalls' 'Scattered Pods' mod option
- # - Fixed [Mars Now!], team start normalization
- # - Added, new map option for expanded coastal waters (like Civ5)
- # - Added [Planetfall], option to use original Planetfall Highlands Generator
- # - Added [Mars Now!], new map option: 'Sands of Mars'/'Terraformed Mars'
- # - Changed, fewer rivers from lakes
- # - Changed, smaller maximum number of BigDent/BigBogs for Island/Terra options
- # - Changed, removed Whale boni for Lakes (30% Water) option
- # - Changed, stratified custom map option process
- # - Changed, stratified normalization process
- # - Changed, reorganised function call sequence within map building process
- # - Changed [Mars Now!], using dedicated terrain generator
- #
- # VERSION 3.16_mst - 15.Jul.2010
- # - use MapScriptTools
- # - compatibility with 'Planetfall'
- # - compatibility with 'Mars Now!'
- # - supports any number of players
- # - add Map Option: TeamStart
- # - add Marsh terrain, if supported by mod
- # - add Deep Ocean terrain, if supported by mod
- # - add rivers on islands
- # - allow more world sizes, if supported by mod
- # - add Map Features ( Kelp, HauntedLands, CrystalPlains )
- # - add Map Regions ( BigDent, BigBog, ElementalQuarter, LostIsle )
- # - better balanced resources
- # - check for Temudjin's Cool Starting Plots
- # - print stats of mod and map
- #
- from CvPythonExtensions import *
- import CvUtil
- import CvMapGeneratorUtil
- gc = CyGlobalContext()
- map = CyMap()
- dice = gc.getGame().getMapRand()
- ##################################################################################
- ## MapScriptTools Interface by Temudjin START
- ##################################################################################
- import MapScriptTools as mst
- balancer = mst.bonusBalancer
- # The following two functions are not exactly neccessary, but they should be
- # in all map-scripts. Just comment them out if they are already in the script.
- # ----------------------------------------------------------------------------
- def getVersion():
- return "3.19_mst"
- def getDescription():
- return "TXT_KEY_MAP_SCRIPT_TECTONICS_DESCR"
- # #################################################################################################
- # ######## randomMapBeforeInit() - Starts the map-generation process, called by RandomMap to set
- # ######## the map options
- # #################################################################################################
- def randomMapBeforeInit(moWorldShape, moResources, moCoastalWaters, moTeamStart, moMarsTheme):
- print "-- randomMapBeforeInit()"
- # Avoid errors while printing custom options.
- global op
- op = {}
- # Map options of this script
- global mapOptionLandmass, mapOptionAridity, mapOptionCoastalWaters, mapOptionResources
- global mapOptionLandscape, mapOptionTeamStart, mapOptionMarsTheme
- # Options chosen in Random Map
- mapOptionResources = moResources
- mapOptionCoastalWaters = moCoastalWaters
- mapOptionTeamStart = moTeamStart
- mapOptionMarsTheme = moMarsTheme
- # All other options are chosen randomly.
- mapOptionLandmass = CyGlobalContext().getGame().getMapRand().get(8, "Tectonics.randomMapBeforeInit(), mapOptionLandmass")
- mapOptionAridity = CyGlobalContext().getGame().getMapRand().get(4, "Tectonics.randomMapBeforeInit(), mapOptionAridity")
- mapOptionLandscape = mst.iif(mst.bPfall, CyGlobalContext().getGame().getMapRand().get(3, "Tectonics.randomMapBeforeInit(), mapOptionLandscape"), None)
- # #################################################################################################
- # ######## beforeInit() - Starts the map-generation process, called after the map-options are known
- # ######## - map dimensions, latitudes and wrapping status are not known yet
- # ######## - handle map specific options
- # #################################################################################################
- def beforeInit():
- print "-- beforeInit()"
- # Selected map options
- global mapOptionLandmass, mapOptionAridity, mapOptionCoastalWaters, mapOptionResources
- global mapOptionLandscape, mapOptionTeamStart, mapOptionMarsTheme
- mapOptionResources = map.getCustomMapOption(0)
- mapOptionLandmass = map.getCustomMapOption(1)
- mapOptionAridity = map.getCustomMapOption(2)
- mapOptionCoastalWaters = mst.iif(mst.bPfall, None, map.getCustomMapOption(3))
- mapOptionLandscape = mst.iif(mst.bPfall, map.getCustomMapOption(3), None)
- mapOptionTeamStart = mst.iif(mst.bMars, None, map.getCustomMapOption(4))
- mapOptionMarsTheme = mst.iif(mst.bMars, map.getCustomMapOption(4), None)
- # #######################################################################################
- # ######## beforeGeneration() - Called from system after user input is finished
- # ######## - define your latitude formula, get the map-version
- # ######## - create map options info string
- # ######## - initialize the MapScriptTools
- # ######## - initialize MapScriptTools.BonusBalancer
- # #######################################################################################
- def beforeGeneration():
- print "-- beforeGeneration()"
- # Create evaluation string for latitudes
- compGetLat = None
- if mapOptionLandmass == 5:
- compLat = "90 * ( 5/18.0 + 4*(%i-y) / (%i*9.0) )" % (map.getGridHeight(),map.getGridHeight())
- # Create mapInfo string
- mapInfo = ""
- # Backup current language
- iLanguage = CyGame().getCurrentLanguage()
- # Force english language for logs
- CyGame().setCurrentLanguage(0)
- for opt in range( getNumCustomMapOptions() ):
- nam = getCustomMapOptionName( [opt] )
- sel = map.getCustomMapOption( opt )
- txt = getCustomMapOptionDescAt( [opt,sel] )
- mapInfo += "%27s: %s\n" % ( nam, txt )
- # Restore current language
- CyGame().setCurrentLanguage(iLanguage)
- # Obtain the map options in use.
- lMapOptions = []
- for opt in range( getNumCustomMapOptions() ):
- iValue = 0 + map.getCustomMapOption( opt )
- lMapOptions.append( iValue )
- # Save used map options.
- mst.mapOptionsStorage.writeConfig(lMapOptions)
- # Initialize MapScriptTools
- mst.getModInfo( getVersion(), None, mapInfo )
- # Initialize MapScriptTools
- mst.getModInfo( getVersion(), compGetLat, mapInfo )
- # Determine global Mars Theme
- mst.bSandsOfMars = (mapOptionMarsTheme == 0)
- # Initialize MapScriptTools.BonusBalancer
- balancer.initialize( mapOptionResources == 1 ) # balance boni if desired, place missing boni, move minerals
- # #######################################################################################
- # ######## generateTerrainTypes() - Called from system after generatePlotTypes()
- # ######## - SECOND STAGE in 'Generate Map'
- # ######## - creates an array of terrains (desert,plains,grass,...) in the map dimensions
- # #######################################################################################
- def generateTerrainTypes():
- print "-- generateTerrainTypes()"
- # Planetfall: more highlands
- mst.planetFallMap.buildPfallHighlands()
- # Prettify the map - change coastal peaks to hills with 50% chance; default: 66%
- mst.mapPrettifier.hillifyCoast( 50 )
- # Prettify map: Connect small islands
- # mst.mapPrettifier.bulkifyIslands()
- # If your active mod is 'Planetfall'/'Mars Now!', you will have to use a different terrainGenerator.
- if mst.bPfall:
- terraingen = mst.MST_TerrainGenerator()
- elif mst.bMars:
- iDesert = mst.iif( mst.bSandsOfMars, 16, 32 )
- terraingen = mst.MST_TerrainGenerator_Mars( iDesert )
- else:
- # Normally use original Tectonics terrain-generator.
- terraingen = ClimateGenerator()
- # Create the terrain and return the result.
- terrainTypes = terraingen.generateTerrain()
- print "-- testtt"
- return terrainTypes
- # #######################################################################################
- # ######## addRivers() - Called from system after generateTerrainTypes()
- # ######## - THIRD STAGE in 'Generate Map'
- # ######## - puts rivers on the map
- # #######################################################################################
- def addRivers():
- print "-- addRivers()"
- # Generate Marsh-terrain within latitude zones (default: 5, 10, (0,18), (45,63) ).
- # The frequency of transformation as well as the zones may be changed by first
- # calling mst.marshMaker.initialize() with the appropriate parameters.
- mst.marshMaker.initialize( 4, 20, (0,25), (50,75) )
- mst.marshMaker.convertTerrain()
- # Solidify marsh between 3 [Arid] and 7 [Tropical] percent.
- if not mst.bPfall:
- if mst.bMarsh:
- iAridity = mst.iif( mapOptionAridity==0, 2, 0 ) # Arid
- iAridity += mst.iif( mapOptionAridity==2, -2, 0 ) # Wet
- marshPer = 5 - iAridity
- mst.mapPrettifier.percentifyTerrain( (mst.etMarsh,marshPer), (mst.etTundra,1), (mst.etGrass,2) )
- # Expand coastal waters
- if mapOptionCoastalWaters == 1:
- mst.mapPrettifier.expandifyCoast()
- nMaxRegions = 3
- if mapOptionLandmass in [4,6,7]: # Islands, Terra, TerraRandom
- nMaxRegions = 1
- # Build between 0..2 mountain-ranges.
- mst.mapRegions.buildBigDents()
- # Build between 0..2 bog-regions.
- mst.mapRegions.buildBigBogs()
- # Generate DeepOcean-terrain if mod allows for it
- mst.deepOcean.buildDeepOcean()
- # Prettify the map - create better connected deserts and plains
- if not mst.bPfall:
- mst.mapPrettifier.lumpifyTerrain( mst.etDesert, mst.etPlains, mst.etGrass )
- if not mst.bMars:
- mst.mapPrettifier.lumpifyTerrain( mst.etPlains, mst.etDesert, mst.etGrass )
- # No standard rivers on Mars
- if not mst.bMars:
- # Tectonics has own river-system
- riverGenerator = riversFromSea()
- riverGenerator.seedRivers()
- # Put rivers on small islands.
- mst.riverMaker.islandRivers() # islands between 6 and 50 tiles
- # #######################################################################################
- # ######## addLakes() - Called from system after addRivers()
- # ######## - FOURTH STAGE in 'Generate Map'
- # ######## - puts lakes on the map
- # #######################################################################################
- def addLakes():
- print "-- addLakes()"
- if not mst.bMars:
- CyPythonMgr().allowDefaultImpl()
- # #######################################################################################
- # ######## addFeatures() - Called from system after addLakes()
- # ######## - FIFTH STAGE in 'Generate Map'
- # ######## - puts features on the map
- # #######################################################################################
- def addFeatures():
- print "-- addFeatures()"
- # Prettify the map - kill off spurious lakes; default: 75% chance
- mst.mapPrettifier.connectifyLakes( 90 )
- # Sprout rivers from lakes.
- mst.riverMaker.buildRiversFromLake( None, 33, 2, 2 ) # all lakes, 33% chance, 2 rivers, lakesize>=2
- # select feature generator
- if mst.bMars:
- featuregen = mst.MST_FeatureGenerator()
- else:
- if (5 == mapOptionLandmass):
- featuregen = MediterraneanFeatureGenerator() # Mediterranean
- elif (3 == mapOptionAridity):
- featuregen = NoIceFeatureGenerator() # Lakes
- else:
- featuregen = mst.MST_FeatureGenerator()
- # generate features
- featuregen.addFeatures()
- # Prettify the map - transform coastal volcanos; default: 66% chance
- mst.mapPrettifier.beautifyVolcanos()
- # Mars Now!: lumpify sandstorms
- if mst.bMars: mst.mapPrettifier.lumpifyFeature( mst.efSandStorm, FeatureTypes.NO_FEATURE )
- # Planetfall: handle shelves and trenches
- if mst.bPfall: mst.planetFallMap.buildPfallOcean()
- # FFH: build ElementalQuarter; default: 5% chance
- mst.mapRegions.buildElementalQuarter()
- # Print featureMap
- mst.mapPrint.buildFeatureMap( True, "normalizeAddExtras()" )
- # ############################################################################################
- # ######## normalizeStartingPlotLocations() - Called from system after starting-plot selection
- # ######## - FIRST STAGE in 'Normalize Starting-Plots'
- # ######## - change assignments to starting-plots
- # ############################################################################################
- def normalizeStartingPlotLocations():
- print "-- normalizeStartingPlotLocations()"
- # build Lost Isle
- # - this region needs to be placed after starting-plots are first assigned
- mst.mapRegions.buildLostIsle( chance=33, minDist=7, bAliens=mst.choose(33,True,False) )
- if mst.bMars:
- # Mars Now! uses no teams
- CyPythonMgr().allowDefaultImpl()
- else:
- if mapOptionTeamStart == 0:
- CyPythonMgr().allowDefaultImpl() # by default civ places teams near to each other
- # mst.teamStart.placeTeamsTogether( True, True ) # use teamStart to place teams near to each other
- elif mapOptionTeamStart == 1:
- mst.teamStart.placeTeamsTogether( False, True ) # shuffle starting-plots to separate teams
- elif mapOptionTeamStart == 2:
- mst.teamStart.placeTeamsTogether( True, True ) # randomize starting-plots (may be near or not)
- else:
- mst.teamStart.placeTeamsTogether( False, False ) # leave starting-plots alone
- # ############################################################################################
- # ######## normalizeAddRiver() - Called from system after normalizeStartingPlotLocations()
- # ######## - SECOND STAGE in 'Normalize Starting-Plots'
- # ######## - add some rivers if needed
- # ############################################################################################
- def normalizeAddRiver():
- print "-- normalizeAddRiver()"
- if not mst.bMars:
- CyPythonMgr().allowDefaultImpl()
- # ############################################################################################
- # ######## normalizeRemovePeaks() - Called from system after normalizeAddRiver()
- # ######## - THIRD STAGE in 'Normalize Starting-Plots'
- # ######## - remove some peaks if needed
- # ############################################################################################
- # A hack. I remove the peaks and I use this as it is the first method called after normalizeAddRiver,
- # which needs a post treatment, so it comes here.
- def normalizeRemovePeaks():
- print "-- normalizeRemovePeaks()"
- # Force flood plains
- mapWidth = map.getGridWidth()
- mapHeight = map.getGridHeight()
- width = map.getGridWidth()
- height = map.getGridHeight()
- for x in range(width):
- for y in range(height):
- addFloodPlains(map.plot(x,y))
- # And now the peaks.
- ########## Temudjin Start
- if mst.bPfall: return
- ########## Temudjin End
- CyPythonMgr().allowDefaultImpl()
- # ############################################################################################
- # ######## normalizeAddLakesRiver() - Called from system after normalizeRemovePeaks()
- # ######## - FOURTH STAGE in 'Normalize Starting-Plots'
- # ######## - add some lakes if needed
- # ############################################################################################
- def normalizeAddLakes():
- print "-- normalizeAddLakes()"
- if not mst.bMars:
- CyPythonMgr().allowDefaultImpl()
- # ############################################################################################
- # ######## normalizeRemoveBadFeatures() - Called from system after normalizeAddLakes()
- # ######## - FIFTH STAGE in 'Normalize Starting-Plots'
- # ######## - remove bad features if needed
- # ############################################################################################
- def normalizeRemoveBadFeatures():
- print "-- normalizeRemoveBadFeatures()"
- return None
- # ############################################################################################
- # ######## normalizeRemoveBadTerrain() - Called from system after normalizeRemoveBadFeatures()
- # ######## - SIXTH STAGE in 'Normalize Starting-Plots'
- # ######## - change bad terrain if needed
- # ############################################################################################
- def normalizeRemoveBadTerrain():
- print "-- normalizeRemoveBadTerrain()"
- if not (mst.bPfall or mst.bMars):
- CyPythonMgr().allowDefaultImpl()
- # ############################################################################################
- # ######## normalizeAddFoodBonuses() - Called from system after normalizeRemoveBadTerrain()
- # ######## - SEVENTH STAGE in 'Normalize Starting-Plots'
- # ######## - add food if needed
- # ############################################################################################
- def normalizeAddFoodBonuses():
- print "-- normalizeAddFoodBonuses()"
- if mst.bMars:
- CyPythonMgr().allowDefaultImpl()
- # ############################################################################################
- # ######## normalizeAddGoodTerrain() - Called from system after normalizeAddFoodBonuses()
- # ######## - EIGHTH STAGE in 'Normalize Starting-Plots'
- # ######## - add good terrain if needed
- # ############################################################################################
- def normalizeAddGoodTerrain():
- print "-- normalizeAddGoodTerrain()"
- if not (mst.bPfall or mst.bMars):
- CyPythonMgr().allowDefaultImpl()
- # This function will be called by the system, after the map was generated, after the
- # starting-plots have been choosen, at the end of the normalizing process and
- # before startHumansOnSameTile() which is the last map-function so called.
- # - balance boni (depending on initialization also place missing boni and move minerals)
- # - give names and boni to special regions
- # - print plot-map and the difference-map to the call before
- # - print other maps
- # - print river-map with plots, rivers and starting-plots
- # - print map and mod statistics
- # --------------------------------------------------------------------------------------
- def normalizeAddExtras():
- print "-- normalizeAddExtras()"
- # Balance boni, place missing boni and move minerals depending on initialization.
- if mapOptionLandmass == 3: # lakes map option
- mst.bonusBalancer.normalizeAddExtras( '-BONUS_WHALE' )
- else:
- mst.bonusBalancer.normalizeAddExtras()
- # Do the default housekeeping
- CyPythonMgr().allowDefaultImpl()
- # Make sure marshes are on flatlands
- mst.marshMaker.normalizeMarshes()
- # Give extras to special regions
- mst.mapRegions.addRegionExtras()
- # Place special features on map
- mst.featurePlacer.placeFeatures()
- # Kill ice on warm edges
- mst.mapPrettifier.deIcifyEdges()
- # Print plotMap and differencePlotMap
- mst.mapPrint.buildPlotMap( True, "normalizeAddExtras()" )
- # Print areaMap
- mst.mapPrint.buildAreaMap( True, "normalizeAddExtras()" )
- # Print terrainMap
- mst.mapPrint.buildTerrainMap( True, "normalizeAddExtras()" )
- # Print featureMap
- mst.mapPrint.buildFeatureMap( True, "normalizeAddExtras()" )
- # Print bonusMap
- mst.mapPrint.buildBonusMap( True, "normalizeAddExtras()" )
- # Print manaMap if FFH
- if mst.bFFH: mst.mapPrint.buildBonusMap( True, "normalizeAddExtras():Mana", None, mst.mapPrint.manaDict )
- # Print riverMap
- mst.mapPrint.buildRiverMap( True, "normalizeAddExtras()" )
- # Print mod and map statistics
- mst.mapStats.mapStatistics()
- # This function will be called at odd times by the system.
- # 'Planetfall' wants nearer starting-plots
- # If the script already has this function, return that result instead of zero or rename it.
- def minStartingDistanceModifier():
- if mst.bPfall: return -25
- if mst.bMars: return -15
- return 0
- ################################################################
- ## Custom Map Option Interface by Temudjin START
- ################################################################
- def setCustomOptions():
- """ Set all custom options in one place """
- global op # { optionID: Name, OptionList, Default, RandomOpt }
- # Initialize options to the default values.
- lMapOptions = [0, 0, 1, 0, 0]
- # Try to read map options from the cfgFile.
- mst.mapOptionsStorage.initialize(lMapOptions, 'Tectonics')
- lMapOptions = mst.mapOptionsStorage.readConfig()
- optionLandmass = [ "TXT_KEY_MAP_SCRIPT_EARTH_70", "TXT_KEY_MAP_SCRIPT_EARTH_60",
- "TXT_KEY_MAP_SCRIPT_PANGAEA", "TXT_KEY_MAP_SCRIPT_LAKES",
- "TXT_KEY_MAP_SCRIPT_ISLANDS", "TXT_KEY_MAP_SCRIPT_MEDITERRANEAN",
- "TXT_KEY_MAP_SCRIPT_TERRA", "TXT_KEY_MAP_SCRIPT_TERRA_OLD_WORLD_START" ]
- optionAridity = [ "TXT_KEY_MAP_SCRIPT_TECTONICS_ARITITY_ARID", "TXT_KEY_MAP_SCRIPT_TECTONICS_ARITITY_NORMAL",
- "TXT_KEY_MAP_SCRIPT_TECTONICS_ARITITY_WET", "TXT_KEY_MAP_SCRIPT_TECTONICS_ARITITY_NO_ICE" ]
- op = {
- 0: ["TXT_KEY_MAP_RESOURCES", ["TXT_KEY_MAP_RESOURCES_STANDARD", "TXT_KEY_MAP_RESOURCES_BALANCED"], lMapOptions[0], True],
- 1: ["TXT_KEY_MAP_SCRIPT_LANDMASS_TYPE", optionLandmass, lMapOptions[1], True],
- 2: ["TXT_KEY_MAP_SCRIPT_TECTONICS_ARITITY", optionAridity, lMapOptions[2], True],
- 3: ["TXT_KEY_MAP_COASTS", ["TXT_KEY_MAP_COASTS_STANDARD", "TXT_KEY_MAP_COASTS_EXPANDED"], lMapOptions[3], True],
- 4: ["TXT_KEY_MAP_TEAM_START", ["TXT_KEY_MAP_TEAM_START_NEIGHBORS", "TXT_KEY_MAP_TEAM_START_SEPARATED", "TXT_KEY_MAP_TEAM_START_RANDOM"], lMapOptions[4], False],
- "Hidden": mst.iif( mst.bPfall, 3, 2 )
- }
- if mst.bMars:
- op[4] = ["TXT_KEY_MAP_MARS_THEME", ["TXT_KEY_MAP_MARS_THEME_SANDS_OF_MARS", "TXT_KEY_MAP_MARS_THEME_TERRAFORMED_MARS"], lMapOptions[4], False]
- elif mst.bPfall:
- op[3] = ["TXT_KEY_MAP_SCRIPT_TECTONICS_LANDSCAPE", ["TXT_KEY_MAP_SCRIPT_TECTONICS_LANDSCAPE_PLANETFALL", "TXT_KEY_MAP_SCRIPT_TECTONICS_LANDSCAPE_DEFAULT"], lMapOptions[3], False]
- mst.printDict(op,"Tectonics Map Options:")
- def isAdvancedMap():
- """ This map should show up in simple mode """
- return 0
- # first function to be called by the map building process
- def getNumHiddenCustomMapOptions():
- """ Default is used for the last n custom-options in 'Play Now' mode. """
- setCustomOptions() # Define Options
- return op["Hidden"]
- def getNumCustomMapOptions():
- """ Number of different user-defined options for this map """
- return len( op ) - 1
- def getCustomMapOptionName(argsList):
- """ Returns name of specified option """
- optionID = argsList[0]
- translated_text = unicode(CyTranslator().getText(op[optionID][0], ()))
- return translated_text
- def getNumCustomMapOptionValues(argsList):
- """ Number of different choices for a particular setting """
- optionID = argsList[0]
- return len( op[optionID][1] )
- def getCustomMapOptionDescAt(argsList):
- """ Returns name of value of option at specified row """
- optionID = argsList[0]
- valueID = argsList[1]
- translated_text = unicode(CyTranslator().getText(op[optionID][1][valueID], ()))
- return translated_text
- def getCustomMapOptionDefault(argsList):
- """ Returns default value of specified option """
- optionID = argsList[0]
- return op[optionID][2]
- def isRandomCustomMapOption(argsList):
- """ Returns a flag indicating whether a random option should be provided """
- optionID = argsList[0]
- return op[optionID][3]
- ################################################################
- ## Interfaces by Temudjin END
- ################################################################
- def isClimateMap():
- """ Does not use the Climate options """
- return False
- def isSeaLevelMap():
- """ Does not use the Sea Level options """
- return False
- def getTopLatitude():
- """ Default is 90. 75 is past the Arctic Circle """
- if (5 == mapOptionLandmass): return 65
- return 90
- def getBottomLatitude():
- """ Default is -90. -75 is past the Antartic Circle """
- if (5 == mapOptionLandmass): return 25
- return -90
- def getWrapX():
- if (5 == mapOptionLandmass): return False
- return True
- def getWrapY():
- return False
- ##########
- class voronoiMap:
- def __init__(self,landPlates,seaPlates,hotspotsF):
- self.dice = gc.getGame().getMapRand()
- self.mapWidth = map.getGridWidth()
- self.mapHeight = map.getGridHeight()
- self.plotTypes = [PlotTypes.PLOT_OCEAN] * (self.mapWidth*self.mapHeight)
- self.heightMap = [0] * (self.mapWidth*self.mapHeight)
- self.plateMap = [0] * (self.mapWidth*self.mapHeight)
- self.numContinents = landPlates
- self.hotSpotFrequency = hotspotsF
- self.numSeaPlates = seaPlates + 1 # plate 0 is for initialisation
- self.plate = [0] * (self.numContinents + self.numSeaPlates)
- # plateSize is a random number which gives the probability of growing a plate
- self.plateSize = [0] * (self.numContinents + self.numSeaPlates)
- self.altitudeVariation = 2
- self.peakAltitude = 12 ########## Temudjin was 12
- self.hillAltitude = 9 ########## Temudjin was 9
- self.landAltitude = 6 ########## Temudjin was 6
- for x in range(self.mapWidth):
- for y in range(self.mapHeight):
- i = y*self.mapWidth + x
- self.plotTypes[i] = PlotTypes.PLOT_OCEAN
- def generate(self):
- self.sowSeeds()
- self.fillPlates()
- self.movePlates(true)
- self.erode()
- self.movePlates(false)
- self.blur()
- self.addFaults()
- self.hotspots()
- self.createMap()
- self.finalizeMap()
- return self.plotTypes
- def sowSeeds(self):
- self.mostLands = self.dice.get(2,"mostland hemisphere")
- for i in range(self.numSeaPlates):
- self.plate[i] = self.dice.get(3,"Sea altitude")
- for i in range(self.numContinents):
- self.plate[self.numSeaPlates + i] = self.landAltitude + self.dice.get(3,"Land altitude")
- for i in range(self.numContinents + self.numSeaPlates):
- x, y = self.getCoord(i)
- while self.plateMap[y*self.mapWidth + x] != 0:
- x, y = self.getCoord(i)
- self.plateMap[y*self.mapWidth + x] = i
- self.plateSize[i] = 3 + self.dice.get(6,"Some randomness in plate sizes") ########## Temidjin was 2
- def getCoord(self,i):
- x = self.dice.get(self.mapWidth,"x seed for plate")
- if (i >= self.numSeaPlates + (self.numContinents/3)):
- y = 2 + self.dice.get(2*self.mapHeight/3,"y seed for plate")
- if (i >= self.numSeaPlates + 1 + (self.numContinents/3)):
- if (self.mostLands == 0):
- y = self.mapHeight - y - 1
- elif (self.mostLands == 1):
- y = self.mapHeight - y - 1
- else:
- y = self.dice.get(self.mapHeight,"y seed for plate")
- return x, y
- def fillPlates(self):
- filled = False
- bufferPlateMap = [0] * (self.mapWidth*self.mapHeight)
- while filled == False:
- filled = True
- for x in range(self.mapWidth):
- for y in range(self.mapHeight):
- i = y*self.mapWidth + x
- bufferPlateMap[i] = self.plateMap[i]
- if (self.plateMap[i] == 0):
- bufferPlateMap[i] = self.neighbour(x,y)
- for x in range(self.mapWidth):
- for y in range(self.mapHeight):
- i = y*self.mapWidth + x
- self.plateMap[i] = bufferPlateMap[i]
- if self.plateMap[i] == 0:
- filled = False
- for x in range(self.mapWidth):
- for y in range(self.mapHeight):
- i = y*self.mapWidth + x
- self.heightMap[i] = self.plate[self.plateMap[i]] + self.dice.get(self.altitudeVariation,"Random variation of altitude")
- def movePlates(self,dontMoveSeaPlates):
- plates = self.numContinents + self.numSeaPlates
- xMoves = [0] * plates
- yMoves = [0] * plates
- subduction = [0] * plates
- min = 0
- if dontMoveSeaPlates:
- min = self.numSeaPlates
- for i in range(min,plates):
- xMoves[i] = self.dice.get(3,"moves") - 2
- yMoves[i] = self.dice.get(3,"moves") - 2
- subduction[i] = self.dice.get(10,"subduction")
- self.doMovePlates(xMoves,yMoves,subduction)
- def doMovePlates(self,xMoves,yMoves,subduction):
- mapSize = self.mapWidth*self.mapHeight
- #FIXME There must be a clone method somewhere?
- oldHeightMap = [0] * mapSize
- for i in range(mapSize):
- oldHeightMap[i] = self.heightMap[i]
- for x in range(self.mapWidth):
- for y in range(self.mapHeight):
- currentCoord = y*self.mapWidth + x
- currentPlate = self.plateMap[currentCoord]
- if (xMoves[currentPlate] != 0 or yMoves[currentPlate] != 0):
- movedX = x + xMoves[currentPlate]
- movedY = y + yMoves[currentPlate]
- if (movedX >= 0 and movedX < self.mapWidth):
- if (movedY >= 0 and movedY < self.mapHeight):
- movedCoord = movedY*self.mapWidth + movedX
- targetPlate = self.plateMap[movedCoord]
- if (targetPlate != currentPlate):
- if (subduction[currentPlate] >= 6):
- sum = oldHeightMap[movedCoord] + oldHeightMap[currentCoord] + 2
- if (self.heightMap[movedCoord] < sum ):
- self.heightMap[movedCoord] = sum
- self.heightMap[currentCoord] = self.heightMap[currentCoord] -1
- else:
- sum = oldHeightMap[movedCoord] + oldHeightMap[currentCoord] -2
- if (self.heightMap[movedCoord] < sum and self.heightMap[movedCoord] >= self.landAltitude):
- self.heightMap[movedCoord] = sum
- if (self.heightMap[currentCoord] < sum and self.heightMap[currentCoord] >= self.landAltitude):
- self.heightMap[currentCoord] = sum
- def addFaults(self):
- "Adds faultlines to break up big flat land masses. Think Rift Valley."
- plates = self.numContinents + self.numSeaPlates
- width = [0] * plates
- height = [0] * plates
- sum = [0] * plates
- lastPlate = 0
- for x in range(self.mapWidth):
- for y in range(self.mapHeight):
- currentCoord = y*self.mapWidth + x
- lastPlate = self.checkFault(currentCoord,sum,height,lastPlate)
- for y in range(self.mapHeight):
- for x in range(self.mapWidth):
- currentCoord = y*self.mapWidth + x
- lastPlate = self.checkFault(currentCoord,sum,width,lastPlate)
- for i in range(plates):
- if (width[i] != 0): self.verticalFault(i,width[i])
- elif (height[i] != 0): self.horizontalFault(i,height[i])
- def checkFault(self,currentCoord,sum,table,lastPlate):
- plates = self.numContinents + self.numSeaPlates
- faultLimit = 7
- if (self.heightMap[currentCoord] <= self.landAltitude):
- return 0
- if (self.heightMap[currentCoord] > self.hillAltitude):
- return 0
- currentPlate = self.plateMap[currentCoord]
- if (lastPlate != currentPlate):
- if (sum[lastPlate] >= 0):
- sum[lastPlate] = 0
- lastPlate = currentPlate
- elif (sum[lastPlate] >= 0):
- sum[lastPlate] = 1 + sum[lastPlate]
- if (sum[lastPlate] > faultLimit):
- table[lastPlate] = currentCoord
- sum[lastPlate] = -1
- return lastPlate
- def verticalFault(self,plateNumber,coord):
- nextCoord = coord - 3 + self.dice.get(6,"Fault position")
- mapSize = self.mapWidth*self.mapHeight
- while (nextCoord >= 0 and nextCoord < mapSize):
- if (self.plateMap[nextCoord] != plateNumber):
- break
- self.fault(nextCoord)
- nextCoord = nextCoord + self.mapWidth + self.dice.get(3,"Fault tilt") - 1
- def horizontalFault(self,plateNumber,coord):
- nextCoord = coord + (self.dice.get(6,"Fault position") - 3) * self.mapWidth
- mapSize = self.mapWidth*self.mapHeight
- max = coord + self.mapWidth
- if (max > mapSize):
- max = mapSize
- while (nextCoord >= 0 and nextCoord < max):
- if (self.plateMap[nextCoord] != plateNumber):
- break
- self.fault(nextCoord)
- nextCoord = nextCoord + 1 + (self.dice.get(3,"Fault tilt") - 1)*self.mapWidth
- def fault(self,coord):
- dieRoll = self.dice.get(20,"Fault line effect")
- if (dieRoll > 11):
- self.heightMap[coord] = self.hillAltitude + 1
- elif (dieRoll > 9):
- self.heightMap[coord] = 0
- def erode(self):
- for x in range(self.mapWidth):
- for y in range(self.mapHeight):
- i = y*self.mapWidth + x
- if self.heightMap[i] > self.peakAltitude:
- self.heightMap[i] -= 2
- if self.heightMap[i] > self.hillAltitude:
- self.heightMap[i] -= 1
- hasSeaNeighbour = False
- hasHillNeighbour = False
- leftX = x-1
- if (leftX < 0):
- leftX = self.mapWidth - 1
- left = self.heightMap[leftX + y*self.mapWidth]
- if (left < self.landAltitude):
- hasSeaNeighbour = True
- elif (left > self.hillAltitude):
- hasHillNeighbour = True
- rightX = x+1
- if (rightX >= self.mapWidth):
- rightX = 0
- right = self.heightMap[rightX + y*self.mapWidth]
- if (right < self.landAltitude):
- hasSeaNeighbour = True
- elif (right > self.hillAltitude):
- hasHillNeighbour = True
- if (y>0):
- top = self.heightMap[x + (y-1)*self.mapWidth]
- if (top < self.landAltitude):
- hasSeaNeighbour = True
- elif (top > self.hillAltitude):
- hasHillNeighbour = True
- if (y<self.mapHeight - 2):
- bottom = self.heightMap[x + (y+1)*self.mapWidth]
- if (bottom < self.landAltitude):
- hasSeaNeighbour = True
- elif (bottom > self.hillAltitude):
- hasHillNeighbour = True
- if (hasSeaNeighbour):
- self.heightMap[i] = self.heightMap[i] - 1
- if (hasHillNeighbour):
- self.heightMap[i] = self.heightMap[i] - 1
- def min( height, left, right, top, bottom ):
- minHeight = height
- if ( minHeight > left ):
- minHeight = left
- if ( minHeight > right ):
- minHeight = right
- if ( minHeight > top ):
- minHeight = top
- if ( minHeight > bottom ):
- minHeight = bottom
- return minHeight
- def blur(self):
- #FIXME There must be a clone method somewhere?
- mapSize = self.mapWidth*self.mapHeight
- oldHeightMap = [0] * (mapSize)
- for i in range(mapSize):
- oldHeightMap[i] = self.heightMap[i]
- for x in range(self.mapWidth):
- for y in range(self.mapHeight):
- i = y*self.mapWidth + x
- height = self.heightMap[i]
- leftX = x-1
- if (leftX < 0):
- leftX = self.mapWidth - 1
- left = oldHeightMap[leftX + y*self.mapWidth]
- rightX = x+1
- if (rightX >= self.mapWidth):
- rightX = 0
- right = oldHeightMap[rightX + y*self.mapWidth]
- top = height
- if (y>0):
- top = oldHeightMap[x + (y-1)*self.mapWidth]
- bottom = height
- if (y<self.mapHeight - 2):
- bottom = oldHeightMap[x + (y+1)*self.mapWidth]
- self.heightMap[i] = (height * 4 + left + right + top + bottom) / 8
- minHeight = min(height,left,right,top,bottom)
- if (minHeight >= self.peakAltitude):
- oldHeightMap[leftX + y*self.mapWidth] = self.hillAltitude + 1
- self.heightMap[leftX + y*self.mapWidth] = self.hillAltitude + 1
- oldHeightMap[rightX + y*self.mapWidth] = self.hillAltitude + 1
- self.heightMap[rightX + y*self.mapWidth] = self.hillAltitude + 1
- if (y>0):
- oldHeightMap[x + (y-1)*self.mapWidth] = self.hillAltitude + 1
- self.heightMap[x + (y-1)*self.mapWidth] = self.hillAltitude + 1
- if (y<self.mapHeight - 2):
- oldHeightMap[x + (y+1)*self.mapWidth] = self.hillAltitude + 1
- self.heightMap[x + (y+1)*self.mapWidth] = self.hillAltitude + 1
- def hotspots(self):
- mapSize = self.mapWidth * self.mapHeight
- hotSpotsNumber = mapSize/self.hotSpotFrequency
- for hotspot in range(hotSpotsNumber):
- i = self.dice.get(mapSize,"Hotspot location")
- self.heightMap[i] = self.heightMap[i] + self.dice.get(self.peakAltitude,"Hotspot altitude")
- def createMap(self):
- for y in range(self.mapHeight):
- for x in range(self.mapWidth):
- i = y*self.mapWidth + x
- height = self.heightMap[i]
- if (height > self.peakAltitude):
- if (self.dice.get(7,"Random pass") == 6):
- self.plotTypes[i] = PlotTypes.PLOT_HILLS
- else:
- self.plotTypes[i] = PlotTypes.PLOT_PEAK
- elif (height > self.hillAltitude):
- if (self.dice.get(20,"Random peak") == 19):
- self.plotTypes[i] = PlotTypes.PLOT_PEAK
- else:
- self.plotTypes[i] = PlotTypes.PLOT_HILLS
- elif (height > self.landAltitude):
- self.plotTypes[i] = PlotTypes.PLOT_LAND
- else:
- self.plotTypes[i] = PlotTypes.PLOT_OCEAN
- def finalizeMap(self):
- return
- def neighbour(self,x,y):
- roll = self.dice.get(10,"Some randomness in plate shapes")
- leftX = x-1
- if (leftX < 0):
- leftX = self.mapWidth - 1
- left = self.plateMap[leftX + y*self.mapWidth]
- if (left != 0):
- if (roll <= self.plateSize[left]):
- return left
- rightX = x+1
- if (rightX >= self.mapWidth):
- rightX = 0
- right = self.plateMap[rightX + y*self.mapWidth]
- if (right != 0):
- if (roll <= self.plateSize[right]):
- return right
- if (y>0):
- top = self.plateMap[x + (y-1)*self.mapWidth]
- if (top != 0):
- if (roll <= self.plateSize[top]):
- return top
- if (y<self.mapHeight - 2):
- bottom = self.plateMap[x + (y+1)*self.mapWidth]
- if (bottom != 0):
- if (roll <= self.plateSize[bottom]):
- return bottom
- return 0
- class voronoiMediterraneanMap(voronoiMap):
- def __init__(self,numPlayers):
- voronoiMap.__init__(self,numPlayers*5/2, numPlayers,150)
- self.peakAltitude = 13
- def movePlates(self,dontMoveSeaPlates):
- if dontMoveSeaPlates:
- return
- voronoiMap.movePlates(self,true)
- def getCoord(self,i):
- mapWidthFraction = self.mapWidth/self.numSeaPlates
- # Sea plates
- if (i < self.numSeaPlates):
- x = mapWidthFraction*i + self.dice.get(mapWidthFraction,"x seed for sea plate")
- y = self.mapHeight/3 + self.dice.get(self.mapHeight/3,"y seed for plate")
- else:
- # One land plate to the east to link north and south
- if (i == self.numSeaPlates + self.numContinents - 1):
- x = self.dice.get(self.mapWidth - 2,"x seed for link land plate")
- y = self.mapHeight/3 + self.dice.get(self.mapHeight/3,"y seed for land plate")
- # Other land plates half north half south
- elif (i < self.numSeaPlates * 2):
- x = mapWidthFraction * (i - self.numSeaPlates) + self.dice.get(mapWidthFraction,"x seed for land plate")
- y = self.getLandY(0)
- elif (i >= self.numSeaPlates * 3):
- x = mapWidthFraction * (i - 2*self.numSeaPlates) + self.dice.get(mapWidthFraction,"x seed for land plate")
- y = self.getLandY(1)
- else:
- x = self.dice.get(self.mapWidth,"x seed for land plate")
- y = self.getLandY(i)
- return x, y
- def getLandY(self,i):
- y = 1 + self.dice.get(self.mapHeight/4,"y seed for land plate")
- if (i == 2*(i/2)):
- y = y + self.mapHeight*3/4 -1
- return y
- def hotspots(self):
- mapSize = self.mapWidth * self.mapHeight
- hotSpotsNumber = mapSize/self.hotSpotFrequency
- minX = 2
- maxX = self.mapWidth*9/10
- minY = self.mapHeight/10
- yRange = self.mapHeight*8/10
- for hotspot in range(hotSpotsNumber):
- x = minX + self.dice.get(maxX,"Hotspot X")
- y = minY + self.dice.get(yRange,"Hotspot Y")
- i = y*self.mapWidth + x
- while (self.plotTypes[i] != PlotTypes.PLOT_OCEAN):
- x = minX + self.dice.get(maxX,"Hotspot X")
- y = minY + self.dice.get(yRange,"Hotspot Y")
- i = y*self.mapWidth + x
- self.heightMap[i] = self.heightMap[i] + self.dice.get(self.peakAltitude,"Hotspot altitude")
- self.spreadHotSpot(i)
- def spreadHotSpot(self,i):
- self.spreadIsland(i+1)
- self.spreadIsland(i-1)
- self.spreadIsland(i+self.mapWidth)
- self.spreadIsland(i-self.mapWidth)
- def spreadIsland(self,i):
- self.heightMap[i] = self.heightMap[i] + self.dice.get(self.peakAltitude,"Hotspot altitude")
- if (self.heightMap[i] > self.landAltitude):
- self.spreadBigIsland(i+1)
- self.spreadBigIsland(i-1)
- self.spreadBigIsland(i+self.mapWidth)
- self.spreadBigIsland(i-self.mapWidth)
- def spreadBigIsland(self,i):
- if (self.heightMap[i] <= self.landAltitude):
- self.heightMap[i] = self.dice.get(self.peakAltitude,"Island altitude")
- def finalizeMap(self):
- # Make sure that the north and south borders are made of land.
- for y in range(self.mapHeight):
- for x in range(self.mapWidth):
- if self.checkY(y):
- i = y*self.mapWidth + x
- if (self.plotTypes[i] == PlotTypes.PLOT_OCEAN):
- self.plotTypes[i] = PlotTypes.PLOT_LAND
- # Make sure that there's a way north/south by foot or galley
- minEastWidth = self.mapWidth * 9 /10
- margin = self.mapWidth/10
- for y in range(self.mapHeight-1):
- for x in range(minEastWidth,self.mapWidth):
- if (x + 3 + self.dice.get(margin,"Border")) > self.mapWidth:
- i = y*self.mapWidth + x
- if (self.plotTypes[i] == PlotTypes.PLOT_OCEAN):
- self.plotTypes[i] = PlotTypes.PLOT_LAND
- def checkY(self,y):
- if (y > 9*self.mapHeight/10):
- y = self.mapHeight - y
- if (y < self.mapHeight/10):
- if (2 + self.dice.get(self.mapHeight/10,"Border")) > y:
- return True
- return False
- class voronoiTerraMap(voronoiMap):
- def __init__(self):
- voronoiMap.__init__(self,12,8,800)
- self.altitudeVariation = 3
- def sowSeeds(self):
- for i in range(0,8):
- self.plate[i] = 2
- for i in range(8,20):
- self.plate[i] = self.landAltitude + 3
- #Pacific Ocean
- for i in range(self.mapHeight):
- self.plateMap[i*self.mapWidth] = 1
- for i in range(self.mapWidth/10):
- self.plateMap[self.mapHeight*self.mapWidth/2 -self.mapWidth/20 + i] = 1
- x = self.mapWidth/10
- y = self.mapHeight/5
- self.plateMap[x + y*self.mapWidth] = 1
- self.plateSize[1] = 7
- #North Atlantic
- x = self.mapWidth/3
- ymin = 2*self.mapHeight/3
- ymax = 7*self.mapHeight/8
- for y in range(ymin,ymax):
- self.plateMap[x + y*self.mapWidth] = 2
- x = 3*self.mapWidth/10
- y = 3*self.mapHeight/5
- self.plateMap[x + y*self.mapWidth] = 2
- self.plateSize[2] = 7
- #South Atlantic
- x = self.mapWidth/3
- yMin = self.mapHeight/5
- yMax = self.mapHeight/3
- for y in range(yMin,yMax):
- self.plateMap[x + y*self.mapWidth] = 3
- for x in range(self.mapWidth/4,self.mapWidth/2):
- self.plateMap[self.mapWidth/3 + self.mapHeight/5*self.mapWidth] = 3
- x = self.mapWidth/3
- y= 5*self.mapHeight/12
- self.plateMap[x + y*self.mapWidth] = 3
- x = self.mapWidth/4 +1
- y = self.mapHeight/4
- self.plateMap[x + y*self.mapWidth] = 3
- self.plateSize[3] = 7
- #Arctic Ocean
- for i in range(self.mapWidth):
- self.plateMap[self.mapWidth*(self.mapHeight-2) + i] = 4
- self.plateSize[4] = 3
- #Mediterranean
- x = 4*self.mapWidth/9
- y = 3*self.mapHeight/4
- self.plateMap[x + y*self.mapWidth] = 5
- self.plateSize[5] = 4
- #Indian Ocean
- x = 3*self.mapWidth/4
- y = self.mapHeight/3
- self.plateMap[x + y*self.mapWidth] = 6
- x = 3*self.mapWidth/5
- y = self.mapHeight/3
- self.plateMap[x + y*self.mapWidth] = 6
- x = 2*self.mapWidth/3
- y = 9*self.mapHeight/20
- self.plateMap[x + y*self.mapWidth] = 6
- self.plateSize[6] = 7
- #Antarctic Ocean
- y = self.mapHeight/8
- for i in range(self.mapWidth):
- self.plateMap[i+y*self.mapWidth] = 7
- self.plateSize[7] = 4
- #North America
- x = self.mapWidth/5
- yMin = 4*self.mapHeight/5
- yMax = 6*self.mapHeight/7
- for y in range(yMin,yMax):
- self.plateMap[x + y*self.mapWidth] = 8
- self.plateMap[self.mapWidth/20 + yMax*self.mapWidth] = 8
- self.plateSize[8] = 8
- #South America
- x = self.mapWidth/5
- y = self.mapHeight/4
- self.plateMap[x + y*self.mapWidth] = 9
- y = self.mapHeight/3
- self.plateMap[x + y*self.mapWidth] = 9
- x = self.mapWidth/4 +1
- y = 2*self.mapHeight/5
- self.plateMap[x + y*self.mapWidth] = 9
- self.plateSize[9] = 5
- #Europe
- x = self.mapWidth/2
- y = 6*self.mapHeight/7
- self.plateMap[x + y*self.mapWidth] = 10
- x = 3*self.mapWidth/7
- y = 4*self.mapHeight/5
- self.plateMap[x + y*self.mapWidth] = 10
- self.plateSize[10] = 6
- #Asia
- x = 3*self.mapWidth/4
- y = 7*self.mapHeight/10
- self.plateMap[x + y*self.mapWidth] = 11
- x = 4*self.mapWidth/5
- y = 4*self.mapHeight/5
- self.plateMap[x + y*self.mapWidth] = 11
- x = 2*self.mapWidth/3
- y = 4*self.mapHeight/5
- self.plateMap[x + y*self.mapWidth] = 11
- self.plateSize[11] = 9
- #Africa
- x = 7*self.mapWidth/20
- y = 2*self.mapHeight/3 -1
- for i in range(self.mapWidth/12):
- self.plateMap[x + i + y*self.mapWidth] = 12
- x = self.mapWidth/2
- y = 2*self.mapHeight/5
- self.plateMap[x + y*self.mapWidth] = 12
- self.plateSize[12] = 6
- #India
- x = 3*self.mapWidth/4
- y = 5*self.mapHeight/9
- self.plateMap[x + y*self.mapWidth] = 13
- self.plateSize[13] = 3
- #Oceania
- x = 4*self.mapWidth/5
- y = self.mapHeight/4 +1
- self.plateMap[x + y*self.mapWidth] = 14
- self.plateSize[14] = 4
- #Middle East
- x = 3*self.mapWidth/5
- y = 4*self.mapHeight/7
- self.plateMap[x + y*self.mapWidth] = 15
- self.plateSize[15] = 2
- self.plate[15] = self.landAltitude + 1
- #South East Asia
- x = 17*self.mapWidth/20
- y = 4*self.mapHeight/7
- self.plateMap[x + y*self.mapWidth] = 16
- self.plateSize[16] = 3
- self.plate[16] = self.landAltitude
- #Greenland
- x = 3*self.mapWidth/10
- y = 7*self.mapHeight/8
- self.plateMap[x + y*self.mapWidth] = 17
- self.plateSize[17] = 4
- #Scandinavia
- x = 3*self.mapWidth/7 -1
- y = 7*self.mapHeight/8
- self.plateMap[x + y*self.mapWidth] = 18
- self.plateSize[18] = 3
- self.plate[18] = self.landAltitude
- #Bering
- x = 9*self.mapWidth/10
- y = 5*self.mapHeight/6
- self.plateMap[x + y*self.mapWidth] = 19
- self.plateSize[19] = 5
- def finalizeMap(self):
- #Force Gibraltar straits
- x = 4*self.mapWidth/9
- y = 3*self.mapHeight/4
- for i in range(self.mapWidth/5):
- self.plotTypes[x + y*self.mapWidth - i] = PlotTypes.PLOT_OCEAN
- #Force cut between India and Oceania
- x = 7*self.mapWidth/10
- y = 4*self.mapHeight/9 -1
- for i in range(self.mapWidth/5):
- self.plotTypes[x + y*self.mapWidth + i] = PlotTypes.PLOT_OCEAN
- #Force Greenland to be an island
- for x in range(self.mapWidth):
- for y in range(self.mapHeight):
- if (self.plateMap[x + y*self.mapWidth] == 17):
- if (self.plateMap[x-1 + y*self.mapWidth] != 17):
- self.plotTypes[x + y*self.mapWidth] = PlotTypes.PLOT_OCEAN
- self.plotTypes[x + (y-1)*self.mapWidth] = PlotTypes.PLOT_OCEAN
- #Force Arabia
- for x in range(self.mapWidth):
- for y in range(self.mapHeight):
- if self.plateMap[x + y*self.mapWidth] == 15:
- if self.plateMap[x + (y-1)*self.mapWidth] != 15:
- self.plotTypes[x + y*self.mapWidth] = PlotTypes.PLOT_OCEAN
- self.plotTypes[x + (y-1)*self.mapWidth] = PlotTypes.PLOT_OCEAN
- if self.plateMap[x+1 + y*self.mapWidth] != 15:
- self.plotTypes[x + y*self.mapWidth] = PlotTypes.PLOT_OCEAN
- self.plotTypes[x+1 + y*self.mapWidth] = PlotTypes.PLOT_OCEAN
- #Force Central America
- baseX = self.mapWidth/6
- x = baseX
- width = 2
- if (self.dice.get(10,"Width variation") > 8):
- width += 1
- if (width > 1 and self.dice.get(10,"Width variation") > 8):
- width -= 1
- for y in range(self.mapHeight/5,self.mapHeight*3/4):
- x = x + self.dice.get(3,"Not too straight") - 1
- if ( x - baseX > 4):
- x = baseX + 4
- if ( x - baseX < -4):
- x = baseX - 4
- if (self.plotTypes[x + y*self.mapWidth ] == PlotTypes.PLOT_OCEAN):
- for plot in range( width ):
- self.plotTypes[x + y*self.mapWidth + plot ] = PlotTypes.PLOT_LAND
- if (self.dice.get(10,"Some hills") > 5):
- self.plotTypes[x + y*self.mapWidth + plot ] = PlotTypes.PLOT_HILLS
- def movePlates(self,dontMoveSeaPlates):
- plates = self.numContinents + self.numSeaPlates
- if dontMoveSeaPlates:
- xMoves = [0, 1, 0, 0, 0, 0, 0, 0, -1,-1, 0,-1, 0, 0,-1, 0,-1, 1, 1, 0, 0]
- yMoves = [0, 0, 0, 0,-1, 1, 1, 0, 0, 1,-1,-1, 0, 1, 0, 0, 0, 1, 0, 0, 0]
- subduction = [0, 9, 9, 0, 9, 0, 0, 0, 9, 9, 9, 0, 0, 9, 9, 9, 0, 9, 9, 0, 0]
- else:
- xMoves = [0, 1, 0, 0, 0, 1,-1, 0, -1,-1, 0, 1, 1,-1, 1, 0, 0,-1,-1, 1,-1]
- yMoves = [0, 0, 0, 0, 1,-1, 0, 0, -1, 1,-1,-1, 1,-1,-1,-1,-1,-1, 0, 1, 1]
- subduction = [0, 9, 9, 0, 9, 9, 9, 0, 9, 9, 9, 9, 0, 9, 9, 9, 0, 0, 9, 0, 0]
- self.doMovePlates(xMoves,yMoves,subduction)
- class voronoiPangaeaMap(voronoiMap):
- def __init__(self,numPlayers):
- voronoiMap.__init__(self,numPlayers,1,1600)
- self.peakAltitude = 11
- self.hillAltitude = 7
- self.landAltitude = 3
- self.altitudeVariation = 3
- def sowSeeds(self):
- self.yTilt = self.dice.get(4,"YTilt")
- self.plate[0] = 0
- self.plate[1] = 0
- for x in range(self.mapWidth):
- self.plateMap[x] = 1
- self.plateMap[self.mapWidth + x] = 1
- self.plateMap[(self.mapHeight - 2)*self.mapWidth + x] = 1
- self.plateMap[(self.mapHeight - 1)*self.mapWidth + x] = 1
- for y in range(self.mapHeight):
- self.plateMap[y*self.mapWidth] = 1
- self.plateMap[y*self.mapWidth + 1] = 1
- self.plateMap[y*self.mapWidth + self.mapWidth - 2] = 1
- self.plateMap[y*self.mapWidth + self.mapWidth - 1] = 1
- for i in range(self.numContinents):
- self.plate[i + self.numSeaPlates] = 4 + self.dice.get(3,"Land altitude")
- x, y = self.getCoord(i)
- while self.plateMap[y*self.mapWidth + x] != 0:
- x, y = self.getCoord(i)
- self.plateMap[y*self.mapWidth + x] = i + 2
- def getCoord(self,i):
- step = self.mapWidth/(2*self.numContinents)
- x = self.mapWidth/4 + i*step + self.dice.get(step,"x seed for plate")
- quarterHeight = self.mapHeight/4
- eigthHeight = self.mapHeight/8
- y = quarterHeight + self.dice.get(self.mapHeight/2,"y seed for plate")
- if (self.yTilt == 0):
- y += i*(self.mapHeight/(self.numContinents*4)) - eigthHeight
- elif (self.yTilt == 1):
- y += eigthHeight - i*quarterHeight/self.numContinents
- elif (self.yTilt == 2):
- if (i%2 == 0):
- y += eigthHeight
- else:
- y -= eigthHeight
- # else: Let it be the way it was generated
- return x, y
- class ClimateGenerator:
- def __init__(self):
- self.climate = mapOptionAridity
- self.map = gc.getMap()
- self.mapWidth = self.map.getGridWidth()
- if (self.climate == 0): # Arid
- self.maxWindForce = self.mapWidth / 12
- elif (self.climate == 1): # Normal
- self.maxWindForce = self.mapWidth / 8
- elif (self.climate == 2): # Wet
- self.maxWindForce = self.mapWidth / 6
- elif (self.climate == 3): # No ice
- self.maxWindForce = self.mapWidth / 8
- self.mapHeight = self.map.getGridHeight()
- self.terrainDesert = mst.etDesert
- self.terrainPlains = mst.etPlains
- self.terrainIce = mst.etSnow
- self.terrainTundra = mst.etTundra
- self.terrainGrass = mst.etGrass
- if (self.climate == 3): # No ice
- self.terrainIce = mst.etTundra
- self.terrainTundra = mst.etGrass
- self.terrain = [0] * (self.mapWidth*self.mapHeight)
- self.moisture = [0] * (self.mapWidth*self.mapHeight)
- self.dice = gc.getGame().getMapRand()
- def getLatitudeAtPlot(self, iX, iY):
- "returns a value in the range of 0-90 degrees"
- if (mapOptionLandmass == 5): # "Mediterranean"
- return 65 - (40 * (self.mapHeight - iY) / self.mapHeight)
- return self.map.plot(iX,iY).getLatitude()
- def generateTerrain(self):
- self.blowWinds()
- self.blur()
- self.computeTerrain()
- return self.terrain
- def computeTerrain(self):
- terrain = [0] * (self.mapWidth*self.mapHeight)
- for x in range(self.mapWidth):
- for y in range(self.mapHeight):
- if (self.map.plot(x,y).isWater()):
- self.terrain[y*self.mapWidth+x] = self.map.plot(x,y).getTerrainType()
- else:
- terrain[y*self.mapWidth+x] = self.getTerrain(self.getLatitudeAtPlot(x,y),self.moisture[y*self.mapWidth + x])
- for x in range(self.mapWidth):
- for y in range(self.mapHeight):
- if (not self.map.plot(x,y).isWater()):
- i = y*self.mapWidth+x
- self.terrain[i] = terrain[i]
- bias = self.dice.get(3,"Random terrain")
- if bias == 0 and y > 1:
- self.terrain[i] = terrain[i-self.mapWidth]
- if bias == 2 and y < self.mapHeight - 1:
- self.terrain[i] = terrain[i+self.mapWidth]
- for x in range(self.mapWidth):
- for y in range(self.mapHeight):
- if (not self.map.plot(x,y).isWater()):
- i = y*self.mapWidth+x
- if self.terrain[i] == self.terrainDesert:
- if y > 1 and y < self.mapHeight - 1:
- if self.terrain[i-self.mapWidth] == self.terrainGrass:
- self.terrain[i-self.mapWidth] = self.terrainPlains
- if self.terrain[i+self.mapWidth] == self.terrainGrass:
- self.terrain[i+self.mapWidth] = self.terrainPlains
- if self.terrain[i-1] == self.terrainGrass:
- self.terrain[i-1] = self.terrainPlains
- if self.terrain[i+1] == self.terrainGrass:
- self.terrain[i+1] = self.terrainPlains
- def getArcticTerrain(self, climate, latitude, moisture):
- polar = 0
- if (latitude > 70):
- polar = latitude - 70
- climate.ice += polar * polar * 3
- climate.tundra += polar * (2 + moisture)
- def getColdTerrain(self, climate, latitude, moisture):
- if (latitude > 60):
- polar = latitude - 60
- climate.tundra += polar * (5 + moisture) + self.dice.get(polar*3,"more tundra")
- if (moisture > 10):
- climate.plains += polar * (moisture - 10)
- def getTemperateTerrain(self, climate, latitude, moisture):
- temperate = 45 - abs(45 - latitude)
- climate.plains += temperate * (3 + moisture/2)
- climate.grass += temperate * (1 + moisture) + self.dice.get(temperate,"more grass")
- def getTropicalTerrain(self, climate, latitude, moisture):
- tropical = 0
- if (latitude < 40):
- tropical = 20 - abs(20 - latitude)
- climate.plains += tropical * (12 - self.climate + moisture/2) + self.dice.get(tropical,"more plains")
- climate.grass += tropical * (moisture + self.climate)
- climate.desert += tropical * (4 - self.climate) * 6
- def getEquatorialTerrain(self, climate, latitude, moisture):
- equator = 0
- if (latitude < 25):
- equator = 25 - latitude
- climate.plains += equator * 7
- climate.grass += equator * (3 + moisture) + self.dice.get(equator,"more grass")
- #I compute latitude as in the maputil but wtf is there a plot.latitude then?
- def getTerrain(self, latitude, moisture):
- class climates:
- def __init__(self):
- self.ice = 0
- self.tundra = 0
- self.plains = 0
- self.grass = 0
- self.desert = 0
- climate = climates()
- self.getArcticTerrain(climate, latitude, moisture)
- self.getColdTerrain(climate, latitude, moisture)
- self.getTemperateTerrain(climate, latitude, moisture)
- self.getTropicalTerrain(climate, latitude, moisture)
- self.getEquatorialTerrain(climate, latitude, moisture)
- if (climate.ice >= climate.tundra) and (climate.ice >= climate.plains) and (climate.ice >= climate.grass) and (climate.ice >= climate.desert):
- return self.terrainIce
- if (climate.tundra >= climate.plains) and (climate.tundra >= climate.grass) and (climate.tundra >= climate.desert):
- return self.terrainTundra
- if (climate.plains >= climate.grass) and (climate.plains >= climate.desert):
- return self.terrainPlains
- if (climate.grass >= climate.desert):
- return self.terrainGrass
- return self.terrainDesert
- def blowWinds(self):
- #Must find where the wind blows from and add moisture from there.
- #If there is a mountain in between, then terrain must become more arid:
- # Tundra -> ice (mmmh?), and grass -> plain -> desert.
- for x in range(self.mapWidth):
- for y in range(self.mapHeight):
- if (self.map.plot(x,y).isWater()):
- self.windBlowsFrom(x,y)
- def windBlowsFrom(self,x,y):
- latitude = self.getLatitudeAtPlot(x,y)
- horizontal = 0
- if (latitude > 80):
- horizontal = 1
- elif (latitude > 45):
- horizontal = -1
- elif (latitude > 30):
- horizontal = 1
- elif (latitude > 10):
- horizontal = -1
- else:
- horizontal = 1
- vertical = self.getVerticalWind(latitude,y)
- windForce = 1 + self.dice.get(self.maxWindForce,"Wind force")
- localMoisture = 5 + self.maxWindForce
- self.blow(localMoisture,windForce,horizontal,vertical,x,y)
- def getVerticalWind(self,latitude,y):
- if (latitude>70):
- vertical = -1
- elif (latitude>30):
- vertical = 1
- else:
- vertical = -1
- if (2*y < self.mapHeight):
- vertical *= -1
- return vertical
- def blow(self,localMoisture,maxHorizontal,horizontal,vertical,x,y):
- plotType = self.map.plot(x,y).getPlotType()
- if (y+vertical > 0 and y+vertical < self.mapHeight):
- if (plotType != PlotTypes.PLOT_PEAK):
- if (plotType == PlotTypes.PLOT_HILLS):
- self.blow(localMoisture - 7,maxHorizontal-2,horizontal,vertical,x,y+vertical)
- else:
- self.blow(localMoisture - 1,maxHorizontal-2,horizontal,vertical,x,y+vertical)
- for i in range(-1,maxHorizontal):
- adjustedX = x + i*horizontal
- if (adjustedX < 0):
- adjustedX += self.mapWidth
- elif (adjustedX >= self.mapWidth):
- adjustedX -= self.mapWidth
- self.moisture[y*self.mapWidth + adjustedX] = self.moisture[y*self.mapWidth + adjustedX] + localMoisture
- plotType = self.map.plot(adjustedX,y).getPlotType()
- if (plotType == PlotTypes.PLOT_PEAK):
- return
- elif (plotType == PlotTypes.PLOT_HILLS):
- localMoisture -= 7
- else:
- localMoisture -= 1
- if (localMoisture <= 0):
- return
- def blur(self):
- max = 1
- for y in range(self.mapHeight):
- for x in range(self.mapWidth):
- i = y*self.mapWidth + x
- if (max < self.moisture[i]):
- max = self.moisture[i]
- for y in range(1,self.mapHeight-2):
- for x in range(self.mapWidth):
- i = y*self.mapWidth + x
- self.moisture[i] = self.moisture[i]*100/max
- #
- # Main landmass/landscape generation function
- #
- def generatePlotTypes():
- "Generates a map with several continents and a few islands."
- print "-- generatePlotTypes()"
- numPlayers = gc.getGame().countCivPlayersEverAlive()
- surface = gc.getMap().getGridWidth() * gc.getMap().getGridHeight()
- numPlayers = (numPlayers + surface / 400) / 2
- numContinents = 1
- numSeaPlates = 1
- hotspotsFrequency = 900
- if (mapOptionLandmass == 0): # "Earthlike (70% water)"
- numContinents = 1 + numPlayers*2
- numSeaPlates = numPlayers*3 - 1
- hotspotsFrequency = 900
- generator = voronoiMap(numContinents,numSeaPlates,hotspotsFrequency)
- elif (mapOptionLandmass == 1): # "Continental (60% water)"
- numContinents = 1 + numPlayers*5/2
- numSeaPlates = numPlayers*5/2 - 1
- hotspotsFrequency = 1100
- generator = voronoiMap(numContinents,numSeaPlates,hotspotsFrequency)
- elif (mapOptionLandmass == 3): # "Lakes (30% water")
- numContinents = 1 + numPlayers*5
- numSeaPlates = numPlayers - 1
- hotspotsFrequency = 1900
- generator = voronoiMap(numContinents,numSeaPlates,hotspotsFrequency)
- elif (mapOptionLandmass == 2): # "Pangaea"
- generator = voronoiPangaeaMap(numPlayers)
- elif (mapOptionLandmass == 4): # "Islands (85% Water)"
- numContinents = 1 + numPlayers
- numSeaPlates = numPlayers*6 - 1
- hotspotsFrequency = 700
- generator = voronoiMap(numContinents,numSeaPlates,hotspotsFrequency)
- elif (mapOptionLandmass == 5): # "Mediterranean"
- generator = voronoiMediterraneanMap(numPlayers)
- elif (mapOptionLandmass == 6 or mapOptionLandmass == 7): # "Terra"
- generator = voronoiTerraMap()
- plotTypes = generator.generate()
- # Print plotMap and differencePlotMap
- mst.mapPrint.buildPlotMap( True, "generatePlotTypes()", data=plotTypes )
- if mapOptionLandscape == 0: # option Planetfall Highlands
- # 'Planetfall' uses ridges/highlands, the original Planetfall landscape generator will be used
- plotTypes = planetfallGenerateHighlands( plotTypes )
- elif mapOptionLandscape == 1: # option Tectonic Highlands
- # 'Planetfall' uses ridges/highlands, some hills and peaks will be added
- plotTypes = mst.planetFallMap.buildPfallHighlands( data=plotTypes )
- return plotTypes
- # Generate highland terrain for Planetfall - from planetfall.py mostly
- def planetfallGenerateHighlands( plotTypes ):
- print "-- planetfallGenerateHighlands()"
- NiTextOut("Setting Plot Types (Python PlanetFall Highlands) ...")
- #-------------------------------------------------------------------------
- # Finetuning Constants
- #
- # Amount of Highlands.
- # Range [1, 100] (I think)
- # Higher number means LESS.
- h_highlands = 60
- # Lower grain will i.g. produce more coherent areas.
- # Range [1, ->].
- # Values below 4 are likey to produce just one big blobb...
- h_grain = 4
- # Amount of Peaks. Is derived from amount of highlands, hence as fraction
- # Range [0, 1]
- # 0 ~ no Peaks. 1 will probably cover all the map with them.
- # Here more means more. Sorry.
- h_peaks = 0.25
- iW = map.getGridWidth()
- iH = map.getGridHeight()
- # plotTypes = [PlotTypes.PLOT_OCEAN] * (iW*iH)
- terrainFrac = CyFractal()
- # fractal_world = PFHL_MultilayeredFractal()
- # plotTypes = fractal_world.generatePlotsByRegion()
- terrainFrac.fracInit(iW, iH, h_grain, dice, 0, -1, -1)
- iHighlandThreshold = terrainFrac.getHeightFromPercent(h_highlands)
- iPeaksThreshold = iHighlandThreshold - (iHighlandThreshold * h_peaks)
- # Now the main loop, which will assign the plot types.
- for x in range(iW):
- for y in range(iH):
- i = y*iW + x
- val = terrainFrac.getHeight(x,y)
- if plotTypes[i] == PlotTypes.PLOT_OCEAN:
- continue # Water plots already set.
- if val >= iHighlandThreshold:
- plotTypes[i] = PlotTypes.PLOT_HILLS
- elif val >= iPeaksThreshold and val < iHighlandThreshold:
- plotTypes[i] = PlotTypes.PLOT_PEAK
- else:
- pass
- return plotTypes
- #Rivers map second try...
- class riversMap:
- def __init__(self):
- self.gc = CyGlobalContext()
- self.dice = gc.getGame().getMapRand()
- self.map = CyMap()
- self.mapWidth = self.map.getGridWidth()
- self.mapHeight = self.map.getGridHeight()
- self.file = open( "d:\\tmp\\toto.txt", 'w' )
- self.generateHeightMap()
- def initHeightMap(self,currentLands):
- #initialize with high altitudes on peaks and hills
- for x in range(self.mapWidth):
- for y in range(self.mapHeight):
- plot = self.map.plot(x,y)
- if (plot.getPlotType() == PlotTypes.PLOT_PEAK):
- currentLands[x + y*self.mapWidth] = 1
- self.heightMap[x + y*self.mapWidth] = 10000
- elif (plot.getPlotType() == PlotTypes.PLOT_HILLS):
- currentLands[x + y*self.mapWidth] = 1
- self.heightMap[x + y*self.mapWidth] = 1000
- elif (plot.getPlotType() == PlotTypes.PLOT_LAND):
- currentLands[x + y*self.mapWidth] = 1
- self.heightMap[x + y*self.mapWidth] = 1
- def generateHeightMap(self):
- self.heightMap = [0] * (self.mapWidth*self.mapHeight)
- currentLands = [0] * (self.mapWidth*self.mapHeight)
- self.initHeightMap(currentLands)
- finished = false
- #make sure there's a slope towards seas and lakes
- while not finished:
- finished = true
- buffer = [1] * (self.mapWidth*self.mapHeight)
- for x in range(self.mapWidth):
- for y in range(self.mapHeight):
- plot = x + y*self.mapWidth
- if currentLands[plot] == 0:
- buffer[plot] = 0
- for i in self.neighbours(x, y):
- buffer[i] = 0
- for x in range(self.mapWidth):
- for y in range(self.mapHeight):
- plot = x + y*self.mapWidth
- currentLands[plot] = buffer[plot]
- if buffer[plot] == 1:
- finished = false
- self.heightMap[plot] = 1 + self.heightMap[plot]
- #make sure there's a slope going downwards away from mountains
- for i in range(20):
- increase = []
- for x in range(self.mapWidth):
- for y in range(self.mapHeight):
- if self.heightMap[x + y*self.mapWidth] > 20 - i:
- for j in self.neighbours(x, y):
- increase.append(j)
- for plot in increase:
- self.heightMap[plot] = self.heightMap[plot] + 2
- for y in range(self.mapHeight):
- for x in range(self.mapWidth):
- plot = x + y*self.mapWidth
- self.file.write( str( self.heightMap[plot] ) + "\t" )
- self.file.write( "\n" )
- def neighbours(self, x, y):
- result = []
- if x == 0:
- result.append(y*self.mapWidth)
- else:
- result.append(x-1 + y*self.mapWidth)
- if x == self.mapWidth - 1:
- result.append(y*self.mapWidth)
- else:
- result.append(x+1 + y*self.mapWidth)
- if y > 0:
- result.append(x + (y-1)*self.mapWidth)
- if y < self.mapHeight - 1:
- result.append(x + (y+1)*self.mapWidth)
- return result
- def seedRivers(self):
- climate = mapOptionAridity
- if (climate == 0): # Arid
- divider = 6
- elif (climate == 1): # Normal
- divider = 3
- elif (climate == 2): # Wet
- divider = 2
- elif (climate == 3): # No ice
- divider = 3
- probability = 30/divider
- seeds = []
- for x in range(self.mapWidth):
- for y in range(self.mapHeight):
- plot = self.map.plot(x,y)
- if (plot.getPlotType() == PlotTypes.PLOT_HILLS):
- if self.dice.get(100,"Start river") < probability:
- seeds.append( plot )
- elif (plot.getPlotType() == PlotTypes.PLOT_LAND):
- if self.dice.get(1000,"Start river in flatland") < probability + self.heightMap[x + y*self.mapWidth]:
- seeds.append( plot )
- for plot in seeds:
- riverID = self.gc.getMap().getNextRiverID()
- self.startRiver(riverID, plot)
- self.file.close()
- def startRiver(self, riverID, plot):
- if plot.isWater():
- return true
- x = plot.getX()
- y = plot.getY()
- height = self.heightMap[x + y * self.mapWidth]
- ns = self.checkNorthSouth(x, y, height)
- ew = self.checkEastWest(x, y, height)
- if ns == CardinalDirectionTypes.NO_CARDINALDIRECTION and ew == CardinalDirectionTypes.NO_CARDINALDIRECTION:
- self.file.write( "End river false\n" )
- return false
- self.file.write( "Will flow\n" )
- if ns != CardinalDirectionTypes.NO_CARDINALDIRECTION and ew != CardinalDirectionTypes.NO_CARDINALDIRECTION:
- if self.dice.get(self.mapHeight + self.mapWidth,"direction") < self.mapHeight:
- self.flow(riverID, plot, ns)
- else:
- self.flow(riverID, plot, ew)
- elif ns != CardinalDirectionTypes.NO_CARDINALDIRECTION:
- self.flow(riverID, plot, ns)
- elif ew != CardinalDirectionTypes.NO_CARDINALDIRECTION:
- self.flow(riverID, plot, ew)
- self.file.write( "End river true\n" )
- return true
- #checks for isWOfRiver
- def checkNorthSouth(self, x, y, height):
- if x == self.mapWidth - 1:
- delta = 1 - self.mapWidth
- else:
- delta = 1
- west = x + delta + y*self.mapWidth
- northSouthHeight = height + self.heightMap[west]
- result = CardinalDirectionTypes.NO_CARDINALDIRECTION
- plot = self.map.plot(x,y)
- if plot.isWOfRiver():
- return result
- if y > 0:
- nHeight = self.heightMap[x + (y-1)*self.mapWidth] + self.heightMap[x + delta + (y-1)*self.mapWidth]
- self.file.write( " For " + str(x) + ", " + str(y) + ", heights: " + str(nHeight) + " <? " + str(northSouthHeight) + "\n" )
- if nHeight < northSouthHeight:
- result = CardinalDirectionTypes.CARDINALDIRECTION_SOUTH
- if y < self.mapHeight -1:
- sHeight = self.heightMap[x + (y-1)*self.mapWidth] + self.heightMap[x + delta + (y-1)*self.mapWidth]
- self.file.write( " For " + str(x) + ", " + str(y) + ", heights: " + str(sHeight) + " <? " + str(northSouthHeight) + "\n" )
- if sHeight < northSouthHeight:
- if result == CardinalDirectionTypes.NO_CARDINALDIRECTION or sHeight < nHeight:
- result = CardinalDirectionTypes.CARDINALDIRECTION_NORTH
- return result
- #checks for isNOfRiver
- def checkEastWest(self, x, y, height):
- result = CardinalDirectionTypes.NO_CARDINALDIRECTION
- plot = self.map.plot(x,y)
- if plot.isNOfRiver():
- return result
- if y < self.mapHeight -1:
- south = x + (y+1)*self.mapWidth
- eastWestHeight = height + self.heightMap[south]
- if x == self.mapWidth - 1:
- west = y*self.mapWidth
- swest = (y+1)*self.mapWidth
- else:
- west = x + 1 + y*self.mapWidth
- swest = x + 1 + (y+1)*self.mapWidth
- wHeight = self.heightMap[west] + self.heightMap[swest]
- self.file.write( " For " + str(x) + ", " + str(y) + ", heights: " + str(wHeight) + " <? " + str(eastWestHeight) + "\n" )
- if wHeight < eastWestHeight:
- result = CardinalDirectionTypes.CARDINALDIRECTION_WEST
- if x == 0:
- east = y*self.mapWidth
- seast = (y+1)*self.mapWidth
- else:
- east = x - 1 + y*self.mapWidth
- seast = x - 1 + (y+1)*self.mapWidth
- eHeight = self.heightMap[east] + self.heightMap[seast]
- self.file.write( " For " + str(x) + ", " + str(y) + ", heights: " + str(eHeight) + " <? " + str(eastWestHeight) + "\n" )
- if eHeight < eastWestHeight:
- if result == CardinalDirectionTypes.NO_CARDINALDIRECTION or eHeight < wHeight:
- result = CardinalDirectionTypes.CARDINALDIRECTION_EAST
- return result
- def joins(self, riverPlot, riverID):
- return (riverPlot.isWOfRiver() or riverPlot.isNOfRiver()) and riverPlot.getRiverID() != riverID
- def flow(self, riverID, plot, direction):
- x = plot.getX()
- y = plot.getY()
- self.file.write( "Flow to " + str(x) + ", " + str(y) + "\n" )
- if direction == CardinalDirectionTypes.CARDINALDIRECTION_EAST:
- if x < self.mapWidth - 1:
- riverPlot = self.map.plot(x+1,y)
- if y == self.mapHeight - 1 or self.map.plot(x+1,y+1).isWater() or riverPlot.isWater():
- return
- else:
- riverPlot = self.map.plot(0,y)
- if y == self.mapHeight - 1 or self.map.plot(0,y+1).isWater() or riverPlot.isWater():
- return
- joinRiver = self.joins(riverPlot, riverID)
- riverPlot.setNOfRiver(True,direction)
- if direction == CardinalDirectionTypes.CARDINALDIRECTION_WEST:
- if x > 0:
- riverPlot = self.map.plot(x-1,y)
- if y == self.mapHeight - 1 or self.map.plot(x-1,y+1).isWater() or riverPlot.isWater():
- return
- else:
- riverPlot = self.map.plot(self.mapWidth-1,y)
- if y == self.mapHeight - 1 or self.map.plot(self.mapWidth-1,y+1).isWater() or riverPlot.isWater():
- return
- joinRiver = self.joins(riverPlot, riverID)
- riverPlot.setNOfRiver(True,direction)
- if direction == CardinalDirectionTypes.CARDINALDIRECTION_NORTH:
- riverPlot = self.map.plot(x,y-1)
- if ( x == self.mapWidth - 1 and self.map.plot(0,y).isWater() ) or ( x < self.mapWidth - 1 and self.map.plot(x+1,y).isWater() ) or riverPlot.isWater():
- return
- joinRiver = self.joins(riverPlot, riverID)
- riverPlot.setWOfRiver(True,direction)
- if direction == CardinalDirectionTypes.CARDINALDIRECTION_SOUTH:
- riverPlot = self.map.plot(x,y+1)
- if ( x == self.mapWidth - 1 and self.map.plot(0,y).isWater() ) or ( x < self.mapWidth - 1 and self.map.plot(x+1,y).isWater() ) or riverPlot.isWater():
- return
- joinRiver = self.joins(riverPlot, riverID)
- riverPlot.setWOfRiver(True,direction)
- if joinRiver:
- self.file.write( "Joining rivers\n" )
- return
- riverPlot.setRiverID(riverID)
- self.startRiver(riverID,riverPlot)
- #if not self.startRiver(riverID,riverPlot):
- #self.file.write( "Add ocean in " + str(riverPlot.getX()) + ", " + str(riverPlot.getY()) + "\n" )
- #riverPlot.setPlotType(PlotTypes.PLOT_OCEAN,true,true)
- # This whole class is needlessly complex. It would be better to rewrite it by first defining
- # a new map, which is the map of the places between squares, giving them an altitude which would be the max
- # of the surrounding squares. This would simplify this a lot but I'm too lazy for now to rewrite all.
- class riversFromSea:
- def __init__(self):
- self.gc = CyGlobalContext()
- self.dice = self.gc.getGame().getMapRand()
- self.map = CyMap()
- self.width = self.map.getGridWidth()
- self.height = self.map.getGridHeight()
- self.straightThreshold = 4
- self.riverLength = {}
- self.riverTurns = {}
- self.minRiverLength = self.height/6
- if (self.width * self.height > 400):
- self.straightThreshold = 3
- def seedRivers(self):
- climate = mapOptionAridity
- if (climate == 0): # Arid
- divider = 4
- elif (climate == 1): # Normal
- divider = 2
- elif (climate == 2): # Wet
- divider = 1
- elif (climate == 3): # No ice
- divider = 2
- maxNumber = (self.width + self.height) / divider
- riversNumber = 1 + maxNumber
- if (mapOptionLandmass == 1): # Pangaea
- riversNumber = maxNumber/2
- self.coasts = self.collateCoasts()
- coastsNumber = len(self.coasts)
- if (coastsNumber == 0):
- return
- coastShare = coastsNumber/riversNumber
- for i in range(riversNumber):
- flow = CardinalDirectionTypes.NO_CARDINALDIRECTION
- tries = 0
- while flow == CardinalDirectionTypes.NO_CARDINALDIRECTION and tries < 6:
- tries = tries + 1
- (x,y,flow) = self.generateRiver(i,coastShare)
- if flow != CardinalDirectionTypes.NO_CARDINALDIRECTION:
- riverID = self.gc.getMap().getNextRiverID()
- self.riverLength[riverID] = 0
- self.riverTurns[riverID] = 0
- self.addRiverFrom(x,y,flow,riverID)
- def collateCoasts(self):
- result = []
- for x in range(self.width):
- for y in range(self.height):
- plot = self.map.plot(x,y)
- if (plot.isCoastalLand()):
- result.append(plot)
- return result
- def generateRiver(self,i,coastShare):
- choiceCoast = coastShare * i + self.dice.get(coastShare,"Pick a coast for the river")
- plot = self.coasts[choiceCoast]
- FlowDirection = CardinalDirectionTypes.NO_CARDINALDIRECTION
- x = plot.getX()
- y = plot.getY()
- if ((y < 1 or y >= self.height - 1) or plot.isNOfRiver() or plot.isWOfRiver()):
- return (x,y,FlowDirection)
- eastX = self.eastX(x)
- westX = self.westX(x)
- otherPlot = True
- eastPlot = self.map.plot(eastX,y)
- if (eastPlot.isCoastalLand()):
- seaPlot = self.map.plot(x,y+1)
- if ((self.map.plot(x,y+1).isWater()) or (self.map.plot(eastX,y+1).isWater())):
- landPlot1 = self.map.plot(x,y-1)
- landPlot2 = self.map.plot(eastX,y-1)
- if (landPlot1.isWater() or landPlot2.isWater()):
- otherPlot = True
- else:
- FlowDirection = CardinalDirectionTypes.CARDINALDIRECTION_NORTH
- otherPlot = False
- if (otherPlot == True):
- if ((self.map.plot(x,y-1).isWater()) or (self.map.plot(eastX,y-1).isWater())):
- landPlot1 = self.map.plot(x,y+1)
- landPlot2 = self.map.plot(eastX,y+1)
- if (landPlot1.isWater() or landPlot2.isWater()):
- otherPlot = True
- else:
- FlowDirection = CardinalDirectionTypes.CARDINALDIRECTION_SOUTH
- otherPlot = False
- if (otherPlot == True):
- southPlot = self.map.plot(x,y-1)
- if (southPlot.isCoastalLand()):
- if ((self.map.plot(eastX,y).isWater()) or (self.map.plot(eastX,y-1).isWater())):
- landPlot1 = self.map.plot(westX,y)
- landPlot2 = self.map.plot(westX,y-1)
- if (landPlot1.isWater() or landPlot2.isWater()):
- otherPlot = True
- else:
- FlowDirection = CardinalDirectionTypes.CARDINALDIRECTION_EAST
- otherPlot = False
- if (otherPlot == True):
- if ((self.map.plot(westX,y).isWater()) or (self.map.plot(westX,y-1).isWater())):
- landPlot1 = self.map.plot(eastX,y)
- landPlot2 = self.map.plot(eastX,y-1)
- if (landPlot1.isWater() or landPlot2.isWater()):
- otherPlot = True
- else:
- FlowDirection = CardinalDirectionTypes.CARDINALDIRECTION_WEST
- return (x,y,FlowDirection)
- # prevent rivers from crossing each other
- def preventRiversFromCrossing(self,x,y,flow,riverID):
- plot = self.map.plot(x,y)
- eastX = self.eastX(x)
- westX = self.westX(x)
- if (flow == CardinalDirectionTypes.CARDINALDIRECTION_WEST):
- if (plot.isNOfRiver()):
- return true
- if (self.map.plot(eastX,y).isNOfRiver()):
- return true
- southPlot = self.map.plot(x,y-1)
- if (southPlot.isWOfRiver() and southPlot.getRiverNSDirection() == CardinalDirectionTypes.CARDINALDIRECTION_SOUTH):
- return true
- if (plot.isWOfRiver() and plot.getRiverNSDirection() == CardinalDirectionTypes.CARDINALDIRECTION_NORTH):
- return true
- if (self.map.plot(eastX,y).isWater()):
- return true
- if (self.map.plot(x,y-1).isWater()):
- return true
- if (self.map.plot(eastX,y-1).isWater()):
- return true
- if (flow == CardinalDirectionTypes.CARDINALDIRECTION_EAST):
- if (plot.isNOfRiver()):
- return true
- if (self.map.plot(westX,y).isNOfRiver()):
- return true
- southPlot = self.map.plot(westX,y-1)
- if (southPlot.isWOfRiver() and southPlot.getRiverNSDirection() == CardinalDirectionTypes.CARDINALDIRECTION_SOUTH):
- return true
- westPlot = self.map.plot(westX,y)
- if (westPlot.isWOfRiver() and westPlot.getRiverNSDirection() == CardinalDirectionTypes.CARDINALDIRECTION_NORTH):
- return true
- if (self.map.plot(westX,y).isWater()):
- return true
- if (self.map.plot(x,y-1).isWater()):
- return true
- if (self.map.plot(westX,y-1).isWater()):
- return true
- if (flow == CardinalDirectionTypes.CARDINALDIRECTION_NORTH):
- if (plot.isWOfRiver()):
- return true
- eastPlot = self.map.plot(eastX,y)
- if (eastPlot.isNOfRiver() and eastPlot.getRiverWEDirection() == CardinalDirectionTypes.CARDINALDIRECTION_EAST):
- return true
- if (plot.isNOfRiver() and plot.getRiverWEDirection() == CardinalDirectionTypes.CARDINALDIRECTION_WEST):
- return true
- if (self.map.plot(x,y-1).isWOfRiver()):
- return true
- if (self.map.plot(x,y-1).isWater()):
- return true
- if (self.map.plot(x+1,y).isWater()):
- return true
- if (self.map.plot(x+1,y-1).isWater()):
- return true
- if (flow == CardinalDirectionTypes.CARDINALDIRECTION_SOUTH):
- if (plot.isWOfRiver()):
- return true
- eastPlot = self.map.plot(eastX,y+1)
- if (eastPlot.isNOfRiver() and eastPlot.getRiverWEDirection() == CardinalDirectionTypes.CARDINALDIRECTION_EAST):
- return true
- northPlot = self.map.plot(x,y+1)
- if (northPlot.isNOfRiver() and northPlot.getRiverWEDirection() == CardinalDirectionTypes.CARDINALDIRECTION_WEST):
- return true
- if (self.map.plot(x,y+1).isWOfRiver()):
- return true
- if (self.map.plot(x,y+1).isWater()):
- return true
- if (self.map.plot(x+1,y).isWater()):
- return true
- if (self.map.plot(x+1,y+1).isWater()):
- return true
- return false
- def addRiverFrom(self,x,y,flow,riverID):
- plot = self.map.plot(x,y)
- if (plot.isWater()):
- return
- self.riverLength[riverID] = self.riverLength[riverID] + 1
- eastX = self.eastX(x)
- westX = self.westX(x)
- if (self.preventRiversFromCrossing(x,y,flow,riverID)):
- return
- plot.setRiverID(riverID)
- if ((flow == CardinalDirectionTypes.CARDINALDIRECTION_WEST) or (flow == CardinalDirectionTypes.CARDINALDIRECTION_EAST)):
- plot.setNOfRiver(True,flow)
- else:
- plot.setWOfRiver(True,flow)
- xShift = 0
- yShift = 0
- if (flow == CardinalDirectionTypes.CARDINALDIRECTION_WEST):
- xShift = 1
- if (flow == CardinalDirectionTypes.CARDINALDIRECTION_EAST):
- xShift = -1
- if (flow == CardinalDirectionTypes.CARDINALDIRECTION_NORTH):
- yShift = -1
- if (flow == CardinalDirectionTypes.CARDINALDIRECTION_SOUTH):
- yShift = 1
- nextX = x + xShift
- nextY = y + yShift
- if (nextX >= self.width):
- nextX = 0
- if (nextY >= self.height):
- return
- nextI = nextY*self.width + nextX
- if (self.canFlowFrom(plot,self.map.plot(nextX,nextY)) == False):
- return
- if not mst.bPfall and plot.getTerrainType() == mst.etSnow and self.dice.get(10,"Stop on ice") > 3:
- return
- if mst.bPfall and (plot.getTerrainType() == mst.etFlatPolar or plot.getTerrainType() == mst.etRockyPolar) and self.dice.get(10,"Stop on ice") > 3:
- return
- flatDesert = plot.getPlotType() == PlotTypes.PLOT_LAND and \
- ((not mst.bPfall and plot.getTerrainType() == mst.etDesert) or\
- (mst.bPfall and (plot.getTerrainType() == mst.etFlatArid or plot.getTerrainType() == mst.etRockyArid)))
- #Prevent Uturns in rivers
- turnThreshold = 13
- if flatDesert:
- turnThreshold = 17
- turned = False
- northY = y + 1
- southY = y - 1
- if ((flow == CardinalDirectionTypes.CARDINALDIRECTION_WEST) or (flow == CardinalDirectionTypes.CARDINALDIRECTION_EAST)):
- if ((northY < self.height) and (self.dice.get(20,"branch from north") > turnThreshold)):
- nextI = northY*self.width + x
- if (self.canFlowFrom(plot,self.map.plot(x,northY)) and self.canFlowFrom(self.map.plot(self.eastX(x),y),self.map.plot(self.eastX(x),northY))):
- turned = True
- self.riverTurns[riverID] = self.riverTurns[riverID] + 1
- if (flow == CardinalDirectionTypes.CARDINALDIRECTION_WEST):
- self.addRiverFrom(x,y,CardinalDirectionTypes.CARDINALDIRECTION_SOUTH,riverID)
- else:
- westPlot = self.map.plot(westX,y)
- westPlot.setRiverID(riverID)
- self.addRiverFrom(westX,y,CardinalDirectionTypes.CARDINALDIRECTION_SOUTH,riverID)
- if ((not turned) and (southY >= 0) and (self.dice.get(20,"branch from south") > turnThreshold)):
- nextI = southY*self.width + x
- if (self.canFlowFrom(plot,self.map.plot(x,southY)) and self.canFlowFrom(self.map.plot(self.eastX(x),y),self.map.plot(self.eastX(x),southY))):
- turned = True
- self.riverTurns[riverID] = self.riverTurns[riverID] + 1
- if (flow == CardinalDirectionTypes.CARDINALDIRECTION_WEST):
- southPlot = self.map.plot(x,y-1)
- southPlot.setRiverID(riverID)
- self.addRiverFrom(x,southY,CardinalDirectionTypes.CARDINALDIRECTION_NORTH,riverID)
- else:
- westPlot = self.map.plot(westX,southY)
- westPlot.setRiverID(riverID)
- self.addRiverFrom(westX,southY,CardinalDirectionTypes.CARDINALDIRECTION_NORTH,riverID)
- else:
- nextI = y*self.width + eastX
- if (self.canFlowFrom(plot,self.map.plot(eastX,y)) and self.canFlowFrom(self.map.plot(x,southY),self.map.plot(eastX,y)) and (self.dice.get(20,"branch from east") > turnThreshold)):
- turned = True
- self.riverTurns[riverID] = self.riverTurns[riverID] + 1
- if (flow == CardinalDirectionTypes.CARDINALDIRECTION_NORTH):
- eastPlot = self.map.plot(eastX,y)
- eastPlot.setRiverID(riverID)
- self.addRiverFrom(eastX,y,CardinalDirectionTypes.CARDINALDIRECTION_WEST,riverID)
- else:
- northEastPlot = self.map.plot(eastX,y+1)
- northEastPlot.setRiverID(riverID)
- self.addRiverFrom(eastX,y+1,CardinalDirectionTypes.CARDINALDIRECTION_WEST,riverID)
- nextI = y*self.width + westX
- if ((not turned) and self.canFlowFrom(plot,self.map.plot(westX,y)) and self.canFlowFrom(self.map.plot(x,southY),self.map.plot(westX,southY)) and (self.dice.get(20,"branch from west") > turnThreshold)):
- turned = True
- if (flow == CardinalDirectionTypes.CARDINALDIRECTION_NORTH):
- self.addRiverFrom(x,y,CardinalDirectionTypes.CARDINALDIRECTION_EAST,riverID)
- else:
- northPlot = self.map.plot(x,y+1)
- northPlot.setRiverID(riverID)
- self.addRiverFrom(x,y+1,CardinalDirectionTypes.CARDINALDIRECTION_EAST,riverID)
- spawnInDesert = (not turned) and flatDesert
- if ((self.dice.get(10,"straight river") > self.straightThreshold) or spawnInDesert):
- if (not turned) or (self.riverTurns[riverID] * 5 < self.riverLength[riverID]):
- self.addRiverFrom(nextX,nextY,flow,riverID)
- else:
- if (not turned):
- if self.riverLength[riverID] < self.minRiverLength:
- self.addRiverFrom(nextX,nextY,flow,riverID)
- else:
- plot = self.map.plot(nextX,nextY)
- if ((plot.getPlotType() == PlotTypes.PLOT_LAND) and (self.dice.get(10,"Rivers start in hills") > 3)):
- plot.setPlotType(PlotTypes.PLOT_HILLS,true,true)
- if ((flow == CardinalDirectionTypes.CARDINALDIRECTION_WEST) or (flow == CardinalDirectionTypes.CARDINALDIRECTION_EAST)):
- if southY > 0:
- self.map.plot(nextX,southY).setPlotType(PlotTypes.PLOT_HILLS,true,true)
- else:
- self.map.plot(eastX,nextY).setPlotType(PlotTypes.PLOT_HILLS,true,true)
- def canFlowFrom(self,plot,upperPlot):
- if (plot.isWater()):
- return False
- if (plot.getPlotType() == PlotTypes.PLOT_PEAK):
- return False
- if (plot.getPlotType() == PlotTypes.PLOT_HILLS):
- if ((upperPlot.getPlotType() == PlotTypes.PLOT_HILLS) or (upperPlot.getPlotType() == PlotTypes.PLOT_PEAK)):
- return True
- else:
- return False
- if (plot.getPlotType() == PlotTypes.PLOT_LAND):
- if (upperPlot.isWater()):
- return False
- return True
- def westX(self,x):
- westX = x - 1
- if (westX < 0):
- westX = self.width
- return westX
- def eastX(self,x):
- eastX = x + 1
- if (eastX >= self.width):
- eastX = 0
- return eastX
- # ------------------------------
- # Temudjins Cool Starting Plots
- # ------------------------------
- # ensures that there are more than 3 land/hill plots within the central 3x3 grid
- # and more than ok land/hill plots in the 5x5 grid around the starting-plot
- def okLandPlots(xCoord, yCoord, ok=10):
- land1 = 0
- if ok >= 0:
- for x in range( -2, 3 ):
- for y in range( -2, 3 ):
- plot = plotXY( xCoord, yCoord, x, y )
- if not plot.isNone():
- if plot.isHills() or plot.isFlatlands():
- land1 += 1
- if land1 > ok:
- land2 = 0
- for x in range( -1, 2 ):
- for y in range( -1, 2 ):
- plot = plotXY( xCoord, yCoord, x, y )
- if not plot.isNone():
- if plot.isHills() or plot.isFlatlands():
- land2 += 1
- if land2 > 3:
- return True
- return False
- # ensures that plot isn't within ok plots from edge of the world
- def okMapEdge( x, y, ok=3 ):
- if not map.isWrapX():
- if ( x < ok ) or ( x > (mst.iNumPlotsX-1-ok) ):
- return False
- if not map.isWrapY():
- if ( y < ok ) or ( y > (mst.iNumPlotsY-1-ok) ):
- return False
- return True
- # ----------------------------------
- # END Temudjin's Cool Starting Plots
- # ----------------------------------
- # ######################################################################################################
- # ######## assignStartingPlots() - Called from system
- # ######## - assign starting positions for each player after the map is generated
- # ######## - Planetfall has GameOption 'SCATTERED_LANDING_PODS' - use default implementation
- # ######################################################################################################
- def assignStartingPlots():
- iPlayers = gc.getGame().countCivPlayersEverAlive()
- if mst.bPfall:
- CyPythonMgr().allowDefaultImpl()
- else:
- map.recalculateAreas()
- areas = CvMapGeneratorUtil.getAreas()
- areaValue = {}
- allOnBest = false
- isolatedStarts = false
- if (mapOptionLandmass == 4): # "Islands"
- isolatedStarts = true
- if (mapOptionLandmass == 7): # "Terra"
- allOnBest = true
- for area in areas:
- if area.isWater(): continue
- areaValue[area.getID()] = area.calculateTotalBestNatureYield() + area.getNumRiverEdges() + 2 * area.countCoastalLand() + 3 * area.countNumUniqueBonusTypes()
- # Shuffle players so the same player doesn't always get the first pick.
- player_list = []
- ########## Temudjin START
- #for plrCheckLoop in range(18):
- for plrCheckLoop in range( gc.getMAX_CIV_PLAYERS() ):
- ########## Temudjin END
- if gc.getPlayer(plrCheckLoop).isEverAlive():
- player_list.append(plrCheckLoop)
- shuffledPlayers = []
- for playerLoop in range(iPlayers):
- iChoosePlayer = dice.get(len(player_list), "Shuffling Players - Highlands PYTHON")
- shuffledPlayers.append(player_list[iChoosePlayer])
- del player_list[iChoosePlayer]
- # Loop through players, assigning starts for each.
- for assign_loop in range(iPlayers):
- playerID = shuffledPlayers[assign_loop]
- player = gc.getPlayer(playerID)
- if (allOnBest):
- #-----
- def isValid(playerID, x, y):
- pPlot = map.plot(x, y)
- if (pPlot.getArea() != map.findBiggestArea(False).getID()):
- return False
- ########## Temudjin START
- #return True
- # Also check for Temudjin's cool starting plots
- return ( okLandPlots(x,y,10) and okMapEdge(x,y,3) )
- ########## Temudjin END
- #-----
- else:
- bestAreaValue = 0
- global bestArea
- bestArea = -1
- for area in areas:
- if area.isWater(): continue
- players = 2*area.getNumStartingPlots()
- #Avoid single players on landmasses:
- if (false == isolatedStarts and players == 0):
- if (assign_loop == iPlayers - 1):
- players = 4
- else:
- players = 2
- value = areaValue[area.getID()] / (1 + 2*players )
- if (value > bestAreaValue):
- bestAreaValue = value;
- bestArea = area.getID()
- #-----
- def isValid(playerID, x, y):
- global bestArea
- plot = map.plot(x,y)
- if (plot.getArea() != bestArea):
- return false
- if (plot.getLatitude() >= 75):
- return false
- ########## Temudjin START
- #return True
- # Also check for Temudjin's cool starting plots
- return ( okLandPlots(x,y,10) and okMapEdge(x,y,3) )
- ########## Temudjin END
- #-----
- findstart = CvMapGeneratorUtil.findStartingPlot(playerID,isValid)
- sPlot = map.plotByIndex(findstart)
- player.setStartingPlot(sPlot,true)
- class MediterraneanFeatureGenerator(CvMapGeneratorUtil.FeatureGenerator):
- def getLatitudeAtPlot(self, iX, iY):
- "returns 0.0 for tropical, up to 1.0 for polar"
- # 25/90 to 65/90:
- lat = 5/float(18) + 4*(self.iGridH - iY)/float(9*self.iGridH)
- return lat
- class NoIceFeatureGenerator(CvMapGeneratorUtil.FeatureGenerator):
- def addIceAtPlot(self, pPlot, iX, iY, lat):
- return
- def addFloodPlains(plot):
- if plot.isRiverSide() and plot.isFlatlands():
- if (plot.getFeatureType() == FeatureTypes.NO_FEATURE):
- for iI in range(gc.getNumFeatureInfos()):
- if plot.canHaveFeature(iI):
- if 10000 == gc.getFeatureInfo(iI).getAppearanceProbability():
- plot.setFeatureType(iI, -1)
|