1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805 |
- ## File: Erebus_mst.py (Creation.py)
- ## Author: Rich Marinaccio
- ## Copyright 2007 Rich Marinaccio
- ##############################################################################
- ## This map script is intended for use with the Fall from Heaven 2 mod for
- ## Civilization 4
- ##############################################################################
- ## Version History
- ## 1.07 - Added the sea level option. This option also changes the map size
- ## so that the play area remains the same. Added climate options. Added marsh
- ## terrain. Fixed a bug from 1.05 that created an unreachable ocean in the
- ## corner of the map somtimes.
- ##
- ## 1.06 - Added some of the new preferences for FfH 0.32 unique improvements.
- ## Improved the choke point code to choose more valueable choke points for
- ## watchtowers and a new unique improvement coming in 0.33.
- ##
- ## 1.05 - Cleaned up peak generation so that peaks on the map edge aren't
- ## always on desert. This prevents large amounts of flames slowing down the
- ## framerate. Added the 'scrubs' feature to map generation. Fixed a bug that
- ## prevented valleys from growing enough to find a neighbor.
- ##
- ## 1.04 - Added a tuning variable called SoftenPeakPercent which allows you to
- ## turn a percentage of peaks into hills to perforate the valleys and make
- ## them less like fortresses. Fixed a bug in detecting network games.
- ##
- ## 1.03 - Cleared forest and jungle from 1 tile around starting plot. This mod
- ## requires high tech levels to clear them and this can be a large hindrance.
- ## Civ preference with allowForestStart = True(Elves) will not clear the forest.
- ##
- ## 1.02 - Added a new civ placement scheme for FFH2 civs. Added a similar scheme
- ## for FFH2 unique improvements. Improved the way ancient towers are placed.
- ## Shrank the map yet again due the high percentage of playable land. Softened
- ## the effect of non-sea level land touching coast.
- ##
- ## 1.01 - Improved water area generation to more consistently make interesting
- ## map shapes. Water spread used to paint itself into a corner, this has been
- ## fixed. Prevented seas from being divided by small isthmuses. Only peaks and
- ## ocean will touch the map edge. Filled unreachable areas with peaks, we
- ## don't want Hyborem spawning there and you know he will if you let him.
- ## Shrank each map size, as there was too much room to expand for the default
- ## number of civs for each map size, resulting in no reason to go to war until
- ## late game. Temporarily added David Reichert's flavour map mod until I can
- ## do something with starting regions.
- #---
- # 1.07f Terkhen 12.Sep.2016
- # - changed, the map size is now proportional to the actual world sizes defined by the mod.
- # - changed, use grid definitions from the active mod instead of using hardcoded ones.
- # - fixed, correct reference to efJungle.
- # 1.07e Terkhen 17.Aug.2016
- # - fixed, use terrain, feature and improvement definitions from MST.
- # 1.07d Terkhen 08.Dic.2014
- # - added, save/load map options.
- # - added, allow to select between the map script starting point placer and the default one when using Fall from Heaven.
- # - added, compatibility with RandomMap.
- # - added, resource balance option.
- # - added, tubular wrapping.
- # - fixed, Erebus unique feature placer would not take into account changes to terrain made by MapScriptTools.
- # - fixed, use Erebus starting points only when using Fall from Heaven 2 based mods.
- # - fixed, prevention of assert errors.
- # - changed, use TXT strings instead of hardcoded ones.
- # - changed, the MapScript no longer needs to convert peaks from desert to tundra.
- # 1.07c Temudjin 15.Mar.2011
- # - fixed [Planetfall], compatibility to Planetfalls 'Scattered Pods' mod option
- # - fixed [Mars Now!], team start normalization
- # - added, new map option: expanded coastal waters (like Civ5)
- # - added [Mars Now!], new map option: 'Sands of Mars'/'Terraformed Mars'
- # - changed, stratified custom map option process
- # - changed, stratified normalization process
- # - changed [Mars Now!], using dedicated terrain generator
- # - add reefs if allowed by mod
- # 1.07b Temudjin 15.Jul.2010 - MapScriptTools
- # - compatibility with 'Planetfall'
- # - compatibility with 'Mars Now!'
- # - add Map Option: TeamStart
- # - add Marsh terrain, if supported by mod
- # - add Deep Ocean terrain, if supported by mod
- # - add some rivers on islands and from lakes
- # - allow more world sizes, if supported by mod
- # - add Map Regions ( BigDent, BigBog, ElementalQuarter, LostIsle )
- # - better bonus balancer
- # - print stats of mod and map
- # - add getVersion(), change getDescription()
- # 1.07a Opera
- # - add Map Features ( Kelp, HauntedLands, CrystalPlains ) - for Orbis
- #
- from CvPythonExtensions import *
- import CvUtil
- import CvMapGeneratorUtil
- from array import array
- from random import random,randint,seed
- import math
- import sys
- map = CyMap()
- ################################################################
- ## MapScriptTools Interface by Temudjin START
- ################################################################
- import MapScriptTools as mst
- balancer = mst.bonusBalancer
- def getVersion():
- return "1.07f_mst"
- def getDescription():
- return "TXT_KEY_MAP_SCRIPT_EREBUS_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 mapOptionWorldShape, mapOptionMountains, mapOptionStartingMethod
- global mapOptionCoastalWaters, mapOptionTeamStart, mapOptionMarsTheme, mapOptionResources
- # Options chosen in Random Map
- mapOptionWorldShape = moWorldShape
- mapOptionResources = moResources
- mapOptionCoastalWaters = moCoastalWaters
- mapOptionTeamStart = moTeamStart
- mapOptionMarsTheme = moMarsTheme
- # All other options are chosen randomly.
- # Give no softening a greater chance than other options.
- mapOptionMountains = CyGlobalContext().getGame().getMapRand().get(18, "Erebus.randomMapBeforeInit(), mapOptionMountains")
- if mapOptionMountains > 11:
- mapOptionMountains = 0
- if mst.bFFH:
- mapOptionStartingMethod = CyGlobalContext().getGame().getMapRand().get(2, "Erebus.randomMapBeforeInit(), mapOptionStartingMethod")
- else:
- mapOptionStartingMethod = 1
- # FF: Added by Jean Elcard 11/20/2008
- mc.initialize()
- mc.WrapX = (mapOptionWorldShape in [1, 3])
- mc.WrapY = (mapOptionWorldShape in [2, 3])
- mc.SoftenPeakPercent = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0][mapOptionMountains]
- # FF: End
- # #################################################################################################
- # ######## 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 mapOptionWorldShape, mapOptionMountains, mapOptionStartingMethod
- global mapOptionCoastalWaters, mapOptionTeamStart, mapOptionMarsTheme, mapOptionResources
- mapOptionWorldShape = map.getCustomMapOption(0)
- mapOptionResources = map.getCustomMapOption(1)
- mapOptionMountains = map.getCustomMapOption(2)
- if mst.bFFH:
- mapOptionStartingMethod = map.getCustomMapOption(3)
- else:
- mapOptionStartingMethod = 1
- mapOptionCoastalWaters = mst.iif(mst.bPfall, None, map.getCustomMapOption(4))
- mapOptionTeamStart = mst.iif(mst.bMars, None, map.getCustomMapOption( mst.iif(mst.bPfall,4,5) ))
- mapOptionMarsTheme = mst.iif(mst.bMars, map.getCustomMapOption(5), None)
- # FF: Added by Jean Elcard 11/20/2008
- mc.initialize()
- mc.WrapX = (mapOptionWorldShape in [1, 3])
- mc.WrapY = (mapOptionWorldShape in [2, 3])
- mc.SoftenPeakPercent = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0][mapOptionMountains]
- # FF: End
- def beforeGeneration():
- print "-- beforeGeneration()"
- # 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 )
- # Determine global Mars Theme
- mst.bSandsOfMars = (mapOptionMarsTheme == 0)
- # Initialize bonus balancing
- balancer.initialize( mapOptionResources == 1 ) # balance boni if desired, place missing boni, move minerals
- def addRivers():
- print "-- addRivers()"
- mst.mapPrint.buildRiverMap( True, "addRivers()" )
- # Generate marsh-terrain
- mst.marshMaker.convertTerrain()
- # Expand coastal waters
- if mapOptionCoastalWaters == 1:
- mst.mapPrettifier.expandifyCoast()
- # 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()
- # No standard rivers on Mars
- if not mst.bMars:
- # Put rivers on the map.
- CyPythonMgr().allowDefaultImpl()
- # addRivers2() # can't use this; doesn't understand the mapRegions changes
- # Put rivers on small islands
- mst.riverMaker.islandRivers()
- def addLakes():
- print "-- addLakes()"
- return None
- def addFeatures():
- print "-- addFeatures()"
- mst.mapPrint.buildRiverMap( True, "addFeatures()" )
- # Kill of spurious lakes
- mst.mapPrettifier.connectifyLakes( 33 )
- # Sprout rivers from lakes.
- mst.riverMaker.buildRiversFromLake( None, 50, 2, 3 )
- if mst.bPfall or mst.bMars:
- # Planetfall / Mars Now! use default featureGenerator
- featuregen = mst.MST_FeatureGenerator()
- featuregen.addFeatures()
- else:
- # Use scripts featureGenerator
- addFeatures2() # call renamed script function
- # Prettify the map - transform coastal volcanos; default: 66% chance
- # mst.mapPrettifier.beautifyVolcanos()
- # Mars Now!: lumpify sandstorms
- if mst.bMars: mst.mapPrettifier.lumpifyTerrain( 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()
- def afterGeneration():
- print "-- afterGeneration()"
- spf.initialize()
- if not mst.bFFH: return
- count = spf.collectAllWatchtowers()
- spf.replaceWatchtowers(count)
- spf.replaceUniqueImprovements()
- def assignStartingPlots():
- if mapOptionStartingMethod == 1: # Planetfall uses default (Temudjin)
- CyPythonMgr().allowDefaultImpl() # Flat World uses default (Jean Elcard 15/12/2008)
- else:
- spf.assignStartingPlots()
- def normalizeStartingPlotLocations():
- print "-- normalizeStartingPlotLocations()"
- mst.mapPrint.buildRiverMap( True, "normalizeStartingPlotLocations()" )
- # build Lost Isle
- # - this region needs to be placed after starting-plots are first assigned
- mst.mapRegions.buildLostIsle()
- if mst.bMars:
- # Mars Now! uses no teams
- CyPythonMgr().allowDefaultImpl()
- elif mapOptionTeamStart == 0:
- # by default civ places teams near to each other
- CyPythonMgr().allowDefaultImpl()
- elif mapOptionTeamStart == 1:
- # shuffle starting-plots to separate teams
- mst.teamStart.placeTeamsTogether( False, True )
- else:
- # randomize starting-plots to ignore teams
- mst.teamStart.placeTeamsTogether( True, True )
- # ############################################################################################
- # ######## normalizeAddRiver() - Called from system after normalizeStartingPlotLocations()
- # ######## - SECOND STAGE in 'Normalize Starting-Plots'
- # ######## - add some rivers if needed
- # ############################################################################################
- def normalizeAddRiver():
- print "-- normalizeAddRiver()"
- return None
- # ############################################################################################
- # ######## normalizeRemovePeaks() - Called from system after normalizeAddRiver()
- # ######## - THIRD STAGE in 'Normalize Starting-Plots'
- # ######## - remove some peaks if needed
- # ############################################################################################
- def normalizeRemovePeaks():
- print "-- normalizeRemovePeaks()"
- return None
- # ############################################################################################
- # ######## normalizeAddLakesRiver() - Called from system after normalizeRemovePeaks()
- # ######## - FOURTH STAGE in 'Normalize Starting-Plots'
- # ######## - add some lakes if needed
- # ############################################################################################
- def normalizeAddLakes():
- print "-- normalizeAddLakes()"
- return None
- # ############################################################################################
- # ######## normalizeRemoveBadFeatures() - Called from system after normalizeAddLakes()
- # ######## - FIFTH STAGE in 'Normalize Starting-Plots'
- # ######## - remove bad features if needed
- # ############################################################################################
- def normalizeRemoveBadFeatures():
- print "-- normalizeRemoveBadFeatures()"
- if mst.bFFH:
- gc = CyGlobalContext()
- gameMap = CyMap()
- civPrefList = GetCivPreferences()
- playerList = list()
- for playerIndex in range(gc.getMAX_CIV_PLAYERS()):
- player = gc.getPlayer(playerIndex)
- if player.isEverAlive():
- civType = player.getCivilizationType()
- civPref = spf.getCivPreference(civPrefList,civType)
- if civPref.allowForestStart == True:
- continue
- plot = player.getStartingPlot()
- featureType = plot.getFeatureType()
- if featureType == mst.efForest or \
- featureType == mst.efJungle:
- plot.setFeatureType(FeatureTypes.NO_FEATURE,0)
- for direction in range(1,9,1):
- xx,yy = plotMap.getXYFromDirection(plot.getX(),plot.getY(),direction)
- nPlot = gameMap.plot(xx,yy)
- featureType = nPlot.getFeatureType()
- if featureType == mst.efForest or \
- featureType == mst.efJungle:
- nPlot.setFeatureType(FeatureTypes.NO_FEATURE,0)
- return None
- # ############################################################################################
- # ######## normalizeRemoveBadTerrain() - Called from system after normalizeRemoveBadFeatures()
- # ######## - SIXTH STAGE in 'Normalize Starting-Plots'
- # ######## - change bad terrain if needed
- # ############################################################################################
- def normalizeRemoveBadTerrain():
- print "-- normalizeRemoveBadTerrain()"
- return None
- # ############################################################################################
- # ######## 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()"
- return None
- def normalizeAddExtras():
- print "-- normalizeAddExtras()"
- # Balance boni, place missing boni, move minerals
- balancer.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. Erebus does not have extra ice when using toroidal wrapping.
- mst.mapPrettifier.deIcifyEdges(66, False)
- # 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( False, "normalizeAddExtras()" )
- # Print manaMap if FFH
- if mst.bFFH: mst.mapPrint.buildBonusMap( False, "normalizeAddExtras():Mana", None, mst.mapPrint.manaDict )
- # Print riverMap
- mst.mapPrint.buildRiverMap( True, "normalizeAddExtras()" )
- # Print mod and map statistics
- mst.mapStats.mapStatistics()
- 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, 0, 0, 0, 0]
- # Try to read map options from the cfgFile.
- mst.mapOptionsStorage.initialize(lMapOptions, 'Erebus')
- lMapOptions = mst.mapOptionsStorage.readConfig()
- optionMountains = [ "TXT_KEY_MAP_EREBUS_MOUNTAINS_NO_SOFTENING",
- "TXT_KEY_MAP_EREBUS_MOUNTAINS_10_PEAKS", "TXT_KEY_MAP_EREBUS_MOUNTAINS_20_PEAKS", "TXT_KEY_MAP_EREBUS_MOUNTAINS_30_PEAKS",
- "TXT_KEY_MAP_EREBUS_MOUNTAINS_40_PEAKS", "TXT_KEY_MAP_EREBUS_MOUNTAINS_50_PEAKS", "TXT_KEY_MAP_EREBUS_MOUNTAINS_60_PEAKS",
- "TXT_KEY_MAP_EREBUS_MOUNTAINS_70_PEAKS", "TXT_KEY_MAP_EREBUS_MOUNTAINS_80_PEAKS", "TXT_KEY_MAP_EREBUS_MOUNTAINS_90_PEAKS",
- "TXT_KEY_MAP_EREBUS_MOUNTAINS_NO_PEAKS" ]
- op = {
- 0: ["TXT_KEY_MAP_SCRIPT_WORLD_WRAP", ["TXT_KEY_MAP_SCRIPT_WORLD_WRAP_FLAT", "TXT_KEY_MAP_SCRIPT_WORLD_WRAP_CYLINDRICAL", "TXT_KEY_MAP_SCRIPT_WORLD_WRAP_TUBULAR", "TXT_KEY_MAP_SCRIPT_WORLD_WRAP_TOROIDAL"], lMapOptions[0], True],
- 1: ["TXT_KEY_MAP_RESOURCES", ["TXT_KEY_MAP_RESOURCES_STANDARD", "TXT_KEY_MAP_RESOURCES_BALANCED"], lMapOptions[1], True],
- 2: ["TXT_KEY_MAP_EREBUS_MOUNTAINS", optionMountains, lMapOptions[2], True],
- 3: ["TXT_KEY_MAP_EREBUS_STARTING_POSITIONS", ["TXT_KEY_MAP_EREBUS_STARTING_POSITIONS_EREBUS", "TXT_KEY_MAP_EREBUS_STARTING_POSITIONS_ORIGINAL"], lMapOptions[3], False],
- 4: ["TXT_KEY_MAP_COASTS", ["TXT_KEY_MAP_COASTS_STANDARD", "TXT_KEY_MAP_COASTS_EXPANDED"], lMapOptions[4], True],
- "Hidden": 4
- }
- if mst.bPfall:
- op[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]
- elif mst.bMars:
- op[5] = ["TXT_KEY_MAP_MARS_THEME", ["TXT_KEY_MAP_MARS_THEME_SANDS_OF_MARS", "TXT_KEY_MAP_MARS_THEME_TERRAFORMED_MARS"], lMapOptions[5], False]
- else:
- op[5] = ["TXT_KEY_MAP_TEAM_START", ["TXT_KEY_MAP_TEAM_START_NEIGHBORS", "TXT_KEY_MAP_TEAM_START_SEPARATED", "TXT_KEY_MAP_TEAM_START_RANDOM"], lMapOptions[5], False]
- if not mst.bFFH:
- op[3] = ["TXT_KEY_MAP_EREBUS_STARTING_POSITIONS", ["TXT_KEY_MAP_EREBUS_STARTING_POSITIONS_ORIGINAL"], lMapOptions[3], False]
- mst.printDict(op,"Erebus 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():
- """ Uses the Climate options """
- return True
- def isSeaLevelMap():
- """ Uses the Sea Level options """
- return True
- def getTopLatitude():
- """ Default is 90. 75 is past the Arctic Circle """
- return 90
- def getBottomLatitude():
- """ Default is -90. -75 is past the Antartic Circle """
- return -90
- def getWrapX():
- return mc.WrapX
- def getWrapY():
- return mc.WrapY
- def isBonusIgnoreLatitude():
- return True
- ##########
- def getGridSize(argsList):
- """ Adjust grid sizes for optimum results """
- if argsList[0] == -1: return [] # (-1,) is passed to function on loads
- # FF: Changed by Jean Elcard 11/22/2008 (moved to beforeInit())
- '''
- mc.initialize()
- '''
- # FF: End Change
- seaLevel = CyMap().getSeaLevel()
- scaler = 1.0
- if seaLevel == GetInfoType("SEALEVEL_LOW"):
- scaler = math.sqrt((mc.RegionsPerPlot - mc.WaterRegionsPerPlot)/(mc.RegionsPerPlot - mc.WaterRegionsPerPlot * 0.5))
- mc.WaterRegionsPerPlot = mc.WaterRegionsPerPlot * 0.5
- print "Sea level is low, map dimension scaler = %f" % scaler
- elif seaLevel == GetInfoType("SEALEVEL_HIGH"):
- scaler = math.sqrt((mc.RegionsPerPlot - mc.WaterRegionsPerPlot)/(mc.RegionsPerPlot - mc.WaterRegionsPerPlot * 3.0))
- mc.WaterRegionsPerPlot = mc.WaterRegionsPerPlot * 2.0
- print "Sea level is high, map dimension scaler = %f" % scaler
- # MST changed: The map size is now proportional to the actual world sizes defined by the mod.
- # Duel and tiny maps are slightly smaller than before, while huge maps are slightly larger.
- [eWorldSize] = argsList
- iMapSize = int(scaler * CyGlobalContext().getWorldInfo(eWorldSize).getGridHeight())
- return iMapSize, iMapSize
- ##########
- class MapConstants :
- def __init__(self):
- return
- def initialize(self):
- ##############################################################################
- # Tunable variables
- ##############################################################################
- #Decides whether to use the Python random generator or the one that is
- #intended for use with civ maps. The Python random has much higher precision
- #than the civ one. 53 bits for Python result versus 16 for getMapRand. The
- #rand they use is actually 32 bits, but they shorten the result to 16 bits.
- #However, the problem with using the Python random is that it may create
- #syncing issues for multi-player now or in the future, therefore it must
- #be optional.
- self.UsePythonRandom = True
- #This variable turns on things that only make sense with Fall from Heaven 2
- self.FFHSpecific = mst.bFFH # was True
- #This variable will make a percentage of peaks into hills in order to break
- #up the worlds valleys. I set this to zero because I feel it diminishes the
- #illusion of differing climates between valleys and looks bad.
- self.SoftenPeakPercent = 0.0
- #This variable decides how many tiles of drainage is needed to create a
- #river.
- self.RiverThreshold = 5.0
- #The amount of rainfall in the dryest desert. Must be between 1.0 and 0.0
- self.MinRainfall = .25
- #This number is multiplied by the RiverThreshold to determine when a river
- #is large enough to have a 100% chance to flatten nearby hills and peaks.
- self.RiverFactorFlattensAll = 10.0
- self.RiverAddsMoistureRange = .20
- self.RiverAddsMoistureMax = 10.0
- #These variables control the frequency of hills and peaks at the lowest
- #and highest altitudes
- self.HillChanceAtZero = .15
- self.HillChanceAtOne = .90
- self.PeakChanceAtZero = .0
- self.PeakChanceAtOne = .20
- #These valiables control the moisture thresholds for desert and plains
- self.JungleThreshold = .90
- self.PlainsThreshold = .50
- self.DesertThreshold = .30
- #Chance for jungle to have marsh, and chance for marsh to replace jungle
- self.ChanceForMarsh = 0.30
- self.ChanceForOnlyMarsh = 0.33
- #These variables control the altitude of tundra and ice. Also, in Civ,
- #deserts are supposed to be hot, so we'll limit the altitude for deserts
- self.TundraThreshold = .74
- self.IceThreshold = .84
- self.MaxDesertAltitude = .65
- #The type of trees are controlled by altitude. Snowy trees use TundraThreshold.
- #Lower than leafy is Jungle.
- self.LeafyAltitude = .30
- self.EvergreenAltitude = .60
- #Chance for an oasis to appear in desert
- self.OasisChance = .08
- #Map constants - I'm making a point on this map to hardcode nothing, so some
- #of these may seem a bit obscure.
- #-------------------------------------------------------------------
- self.RegionsPerPlot = 0.009 #Map regions(valleys, seas) per map plot
- self.WaterRegionsPerPlot = 0.002 #Water regions per map plot
- self.MinSeedRange = 5 #Closest that a region seed can be placed to another
- self.MinEdgeRange = 5 #Closest that a region seed can be to map edge
- self.ChanceToGrow = 0.25 #Base chance for each tile in region to grow
- self.EdgeLimit = 2 #Region stops growing this far from edge
- self.RiverAltitudeSubtraction = 2.0 #Amount subtracted from a plots altitude depending on river size
- self.RiverAltRangeFactor = 2.0 #Amount of RiverThreshold to use for altitude calc
- self.MinRegionSizeStart = 40 #Minimum region size for a starting plot
- self.MinRegionSizeTower = 30 #Minimum region size for a tower placement
- self.ChokePointAreaSize = 10 #chokepoint needs this size area on both sides
- self.ChokePointWalkAroundDistance = 12 #chokepoint must cause this much extra walking to be considered a choke
- self.WrapX = False # Dont touch these, this map has no wrap # Huh?
- self.WrapY = False
- return
- mc = MapConstants()
- def GetCivPreferences():
- ## Civs without preferences will use default values.
- ##
- ## Civ Name from XML
- ## pref = CivPreference(GetInfoType("CIVILIZATION_MALAKIM"))
- ##
- ## Self explanatory.
- ## pref.idealMoisture = 0.1
- ## pref.idealAltitude = 0.25
- ##
- ## These weights influence the effect of each preference. moistureWeight
- ## is hard coded as 1.0 for civ placement
- ## pref.altitudeWeight = 0.25
- ## pref.distanceWeight = 0.25 #how hard to try to start away from other civs
- ## pref.needCoastalStart = False
- civPreferenceList = list()
- pref = CivPreference(GetInfoType("CIVILIZATION_MALAKIM"))
- pref.idealMoisture = 0.1
- pref.idealAltitude = 0.25
- pref.altitudeWeight = 0.25
- pref.distanceWeight = 0.25
- pref.needCoastalStart = False
- pref.allowForestStart = False
- civPreferenceList.append(pref)
- pref = CivPreference(GetInfoType("CIVILIZATION_DOVIELLO"))
- pref.idealMoisture = 0.8
- pref.idealAltitude = 0.95
- pref.altitudeWeight = 2.0
- pref.distanceWeight = 0.75
- pref.needCoastalStart = False
- pref.allowForestStart = False
- civPreferenceList.append(pref)
- pref = CivPreference(GetInfoType("CIVILIZATION_ILLIANS"))
- pref.idealMoisture = 0.5
- pref.idealAltitude = 0.95
- pref.altitudeWeight = 2.0
- pref.distanceWeight = 0.75
- pref.needCoastalStart = False
- pref.allowForestStart = False
- civPreferenceList.append(pref)
- pref = CivPreference(GetInfoType("CIVILIZATION_KHAZAD"))
- pref.idealMoisture = 0.35
- pref.idealAltitude = 0.75
- pref.altitudeWeight = 2.0
- pref.distanceWeight = 0.75
- pref.needCoastalStart = False
- pref.allowForestStart = False
- civPreferenceList.append(pref)
- pref = CivPreference(GetInfoType("CIVILIZATION_LUCHUIRP"))
- pref.idealMoisture = 0.35
- pref.idealAltitude = 0.75
- pref.altitudeWeight = 2.0
- pref.distanceWeight = 0.75
- pref.needCoastalStart = False
- pref.allowForestStart = False
- civPreferenceList.append(pref)
- pref = CivPreference(GetInfoType("CIVILIZATION_LJOSALFAR"))
- pref.idealMoisture = 0.75
- pref.idealAltitude = 0.23
- pref.altitudeWeight = 2.0
- pref.distanceWeight = 0.25
- pref.needCoastalStart = False
- pref.allowForestStart = True
- civPreferenceList.append(pref)
- pref = CivPreference(GetInfoType("CIVILIZATION_LANUN"))
- pref.idealMoisture = 0.5
- pref.idealAltitude = 0.0
- pref.altitudeWeight = 2.0
- pref.distanceWeight = 0.25
- pref.needCoastalStart = True
- pref.allowForestStart = False
- civPreferenceList.append(pref)
- pref = CivPreference(GetInfoType("CIVILIZATION_HIPPUS"))
- pref.idealMoisture = 0.4
- pref.idealAltitude = 0.1
- pref.altitudeWeight = 0.5
- pref.distanceWeight = 0.25
- pref.needCoastalStart = False
- pref.allowForestStart = False
- civPreferenceList.append(pref)
- pref = CivPreference(GetInfoType("CIVILIZATION_SVARTALFAR"))
- pref.idealMoisture = 0.7
- pref.idealAltitude = 0.35
- pref.altitudeWeight = 1.0
- pref.distanceWeight = 2.0
- pref.needCoastalStart = False
- pref.allowForestStart = True
- civPreferenceList.append(pref)
- return civPreferenceList
- def GetImprovementPreferences():
- #These values are similar to the way civs work except distanceWeight is
- #hardcoded as 1.0
- impPreferenceList = list()
- pref = ImprovementPreference(GetInfoType("IMPROVEMENT_GUARDIAN"))
- pref.idealMoisture = .6
- pref.idealAltitude = .8
- pref.moistureWeight = .5
- pref.altitudeWeight = 1.0
- pref.needCoast = False
- pref.needWater = False
- pref.needHill = False
- pref.needFlat = False
- pref.needChoke = True #Only for guardian at this time
- impPreferenceList.append(pref)
- ## Removed to prevent 2 brigits from appearing upon moving improvement
- ## pref = ImprovementPreference(GetInfoType("IMPROVEMENT_RING_OF_CARCER"))
- ## pref.idealMoisture = .6
- ## pref.idealAltitude = 1.0
- ## pref.moistureWeight = .25
- ## pref.altitudeWeight = 3.0
- ## pref.needCoast = False
- ## pref.needWater = False
- ## pref.needHill = True
- ## pref.needFlat = False
- ## pref.favoredTerrain = mst.etSnow
- ## impPreferenceList.append(pref)
- pref = ImprovementPreference(GetInfoType("IMPROVEMENT_SEVEN_PINES"))
- pref.idealMoisture = .60
- pref.idealAltitude = .6
- pref.moistureWeight = 1.0
- pref.altitudeWeight = .5
- pref.needCoast = False
- pref.needWater = False
- pref.needHill = False
- pref.needFlat = False
- pref.favoredTerrain = mst.etGrass
- impPreferenceList.append(pref)
- pref = ImprovementPreference(GetInfoType("IMPROVEMENT_STANDING_STONES"))
- pref.idealMoisture = .75
- pref.idealAltitude = .5
- pref.moistureWeight = 1.0
- pref.altitudeWeight = .5
- pref.needCoast = False
- pref.needWater = False
- pref.needHill = False
- pref.needFlat = True
- pref.favoredTerrain = mst.etGrass
- impPreferenceList.append(pref)
- pref = ImprovementPreference(GetInfoType("IMPROVEMENT_BROKEN_SEPULCHER"))
- pref.idealMoisture = .6
- pref.idealAltitude = .5
- pref.moistureWeight = .5
- pref.altitudeWeight = .5
- pref.needCoast = False
- pref.needWater = False
- pref.needHill = False
- pref.needFlat = True
- impPreferenceList.append(pref)
- pref = ImprovementPreference(GetInfoType("IMPROVEMENT_MIRROR_OF_HEAVEN"))
- pref.idealMoisture = .0
- pref.idealAltitude = .0
- pref.moistureWeight = 2.0
- pref.altitudeWeight = .25
- pref.needCoast = False
- pref.needWater = False
- pref.needHill = False
- pref.needFlat = False
- pref.favoredTerrain = mst.etDesert
- impPreferenceList.append(pref)
- pref = ImprovementPreference(GetInfoType("IMPROVEMENT_DRAGON_BONES"))
- pref.idealMoisture = .35
- pref.idealAltitude = .35
- pref.moistureWeight = 1.0
- pref.altitudeWeight = 1.0
- pref.needCoast = False
- pref.needWater = False
- pref.needHill = False
- pref.needFlat = True
- impPreferenceList.append(pref)
- pref = ImprovementPreference(GetInfoType("IMPROVEMENT_LETUM_FRIGUS"))
- pref.idealMoisture = .7
- pref.idealAltitude = 1.0
- pref.moistureWeight = .5
- pref.altitudeWeight = 2.0
- pref.needCoast = False
- pref.needWater = False
- pref.needHill = False
- pref.needFlat = True
- pref.favoredTerrain = mst.etSnow
- impPreferenceList.append(pref)
- pref = ImprovementPreference(GetInfoType("IMPROVEMENT_ODIOS_PRISON"))
- pref.idealMoisture = .35
- pref.idealAltitude = .75
- pref.moistureWeight = 1.0
- pref.altitudeWeight = 2.0
- pref.needCoast = False
- pref.needWater = False
- pref.needHill = False
- pref.needFlat = True
- impPreferenceList.append(pref)
- pref = ImprovementPreference(GetInfoType("IMPROVEMENT_POOL_OF_TEARS"))
- pref.idealMoisture = .5
- pref.idealAltitude = .5
- pref.moistureWeight = 1.0
- pref.altitudeWeight = 1.0
- pref.needCoast = False
- pref.needWater = False
- pref.needHill = False
- pref.needFlat = True
- impPreferenceList.append(pref)
- pref = ImprovementPreference(GetInfoType("IMPROVEMENT_PYRE_OF_THE_SERAPHIC"))
- pref.idealMoisture = 1.0
- pref.idealAltitude = 0.0
- pref.moistureWeight = 2.0
- pref.altitudeWeight = .5
- pref.needCoast = False
- pref.needWater = False
- pref.needHill = False
- pref.needFlat = True
- impPreferenceList.append(pref)
- pref = ImprovementPreference(GetInfoType("IMPROVEMENT_REMNANTS_OF_PATRIA"))
- pref.idealMoisture = .6
- pref.idealAltitude = .5
- pref.moistureWeight = .5
- pref.altitudeWeight = .5
- pref.needCoast = False
- pref.needWater = False
- pref.needHill = False
- pref.needFlat = True #Forest hill gives 9 hammers which is OP imo.
- impPreferenceList.append(pref)
- pref = ImprovementPreference(GetInfoType("IMPROVEMENT_TOMB_OF_SUCELLUS"))
- pref.idealMoisture = .6
- pref.idealAltitude = .5
- pref.moistureWeight = 1.0
- pref.altitudeWeight = .5
- pref.needCoast = False
- pref.needWater = False
- pref.needHill = False
- pref.needFlat = True
- impPreferenceList.append(pref)
- pref = ImprovementPreference(GetInfoType("IMPROVEMENT_YGGDRASIL"))
- pref.idealMoisture = .75
- pref.idealAltitude = .25
- pref.moistureWeight = 2.0
- pref.altitudeWeight = 1.0
- pref.needCoast = False
- pref.needWater = False
- pref.needHill = False
- pref.needFlat = False
- pref.favoredTerrain = mst.etGrass
- impPreferenceList.append(pref)
- return impPreferenceList
- class ImprovementPreference :
- def __init__(self,improvement):
- self.improvement = improvement
- self.idealAltitude = .5
- self.idealMoisture = .6
- self.altitudeWeight = 1.0
- self.moistureWeight = 1.0
- self.needCoast = False
- self.needWater = False
- self.needHill = False
- self.needFlat = False
- self.needChoke = False
- self.favoredTerrain = TerrainTypes.NO_TERRAIN
- class CivPreference :
- def __init__(self,civ):
- self.civ = civ
- self.idealAltitude = 0.35
- self.idealMoisture = 0.7
- self.needCoastalStart = False
- self.allowForestStart = False
- self.altitudeWeight = 1.0
- self.distanceWeight = 2.0 #distance is most important for generic civs
- return
- class PythonRandom :
- def __init__(self):
- return
- def seed(self):
- #Python randoms are not usable in network games.
- if mc.UsePythonRandom:
- self.usePR = True
- else:
- self.usePR = False
- if self.usePR and CyGame().isNetworkMultiPlayer():
- print "Detecting network game. Setting UsePythonRandom to False."
- self.usePR = False
- if self.usePR:
- # Python 'long' has unlimited precision, while the random generator
- # has 53 bits of precision, so I'm using a 53 bit integer to seed the map!
- seed() #Start with system time
- seedValue = randint(0,9007199254740991)
- seed(seedValue)
- print "Random seed (Using Python rands) for this map is %(s)20d" % {"s":seedValue}
- ## seedValue = 5018808826709881
- ## seed(seedValue)
- ## print "Pre-set seed (Using Pyhon rands) for this map is %(s)20d" % {"s":seedValue}
- else:
- gc = CyGlobalContext()
- self.mapRand = gc.getGame().getMapRand()
- seedValue = self.mapRand.get(65535,"Seeding mapRand - PerfectWorld.py")
- self.mapRand.init(seedValue)
- print "Random seed (Using getMapRand) for this map is %(s)20d" % {"s":seedValue}
- ## seedValue = 56870
- ## self.mapRand.init(seedValue)
- ## print "Pre-set seed (Using getMapRand) for this map is %(s)20d" % {"s":seedValue}
- return
- def random(self):
- if self.usePR:
- return random()
- else:
- #This formula is identical to the getFloat function in CvRandom. It
- #is not exposed to Python so I have to recreate it.
- fResult = float(self.mapRand.get(65535,"Getting float -PerfectWorld.py"))/float(65535)
- # print fResult
- return fResult
- def randint(self,rMin,rMax):
- #if rMin and rMax are the same, then return the only option
- if rMin == rMax:
- return rMin
- #returns a number between rMin and rMax inclusive
- if self.usePR:
- return randint(rMin,rMax)
- else:
- #mapRand.get() is not inclusive, so we must make it so
- return rMin + self.mapRand.get(rMax + 1 - rMin,"Getting a randint - PerfectWorld.py")
- #Set up random number system for global access
- PRand = PythonRandom()
- #This function converts x and y to an index. Useful in case of future wrapping.
- def GetIndex(x,y):
- #Check X for wrap
- if mc.WrapX == True:
- xx = x % mapSize.MapWidth
- elif x < 0 or x >= mapSize.MapWidth:
- return -1
- else:
- xx = x
- #Check y for wrap
- if mc.WrapY == True:
- yy = y % mapSize.MapHeight
- elif y < 0 or y >= mapSize.MapHeight:
- return -1
- else:
- yy = y
- i = yy * mapSize.MapWidth + xx
- return i
- #This function converts x and y to an index on river crossing maps.
- def GetRxIndex(x,y):
- #Check X for wrap
- if mc.WrapX == True:
- xx = x % (mapSize.MapWidth + 1)
- elif x < 0 or x >= (mapSize.MapWidth + 1):
- return -1
- else:
- xx = x
- #Check y for wrap
- if mc.WrapY == True:
- yy = y % (mapSize.MapHeight + 1)
- elif y < 0 or y >= (mapSize.MapHeight + 1):
- return -1
- else:
- yy = y
- i = yy * (mapSize.MapWidth + 1) + xx
- return i
- class MapSize :
- def __init__(self):
- self.MapWidth = 0
- self.MapHeight = 0
- mapSize = MapSize()
- class RegionMap :
- def __init__(self):
- return
- def createRegions(self):
- #Growing the regions directly according to the map size created
- #unsolvable problems for the river system. Instead, I am growing
- #on a map (regionRxMap) that corresponds to rivers rather than
- #map tiles. This ensures rivers have a path from region to
- #region.
- self.L = 0
- self.N = 1
- self.S = 2
- self.E = 3
- self.W = 4
- self.NE = 5
- self.NW = 6
- self.SE = 7
- self.SW = 8
- self.highestRegionAltitude = 0
- numTiles = mapSize.MapWidth*mapSize.MapHeight
- numRx = (mapSize.MapWidth + 1)*(mapSize.MapHeight + 1)
- print "MapWidth = %(mw)d,MapHeight = %(mh)d" % {"mw":mapSize.MapWidth,"mh":mapSize.MapHeight}
- self.regionMap = array('i')
- self.regionRxMap = array('i')
- self.regionList = list()
- self.regionPlotList = list()
- #initialize map
- #The value for unplayable areas will remain -1. playable regions
- #will stop growing when they touch a map edge.
- for i in range(numTiles):
- self.regionMap.append(-1)
- for i in range(numRx):
- self.regionRxMap.append(-1)
- numRegions = int(float(numTiles) * mc.RegionsPerPlot)
- print "numTiles = %(n)d, numRegions = %(w)d" % {"n":numTiles,"w":numRegions}
- for i in range(numRegions):
- #first find a random seed point that is not blocked by
- #previous points
- iterations = 0
- while(True):
- iterations += 1
- if iterations > 10000:
- raise ValueError, "endless loop in region seed placement"
- seedX = PRand.randint(0,mapSize.MapWidth + 1)
- seedY = PRand.randint(0,mapSize.MapHeight + 1)
- if self.isSeedBlocked(seedX,seedY) == False:
- region = Region(i,seedX,seedY)
- self.regionList.append(region)
- n = GetRxIndex(seedX,seedY)
- self.regionRxMap[n] = i
- plot = RegionPlot(i,seedX,seedY)
- self.regionPlotList.append(plot)
- #Now fill a 3x3 area to insure a minimum region size
- for direction in range(1,9,1):
- xx,yy = self.getXYFromDirection(seedX,seedY,direction)
- nn = GetRxIndex(xx,yy)
- self.regionRxMap[nn] = i
- plot = RegionPlot(i,xx,yy)
- self.regionPlotList.append(plot)
- break
- ## self.PrintRegionRxMap(False)
- #Now cause the seeds to grow into regions
- iterations = 0
- while(len(self.regionPlotList) > 0):
- iterations += 1
- if iterations > 200000:
- self.PrintRegionRxMap(False)
- raise ValueError, "endless loop in region growth"
- plot = self.regionPlotList[0]
- region = self.getRegionByID(plot.regionID)
- if region.isGrowing == False:
- del self.regionPlotList[0]
- continue
- roomLeft = False
- for direction in range(1,5,1):
- xx,yy = self.getXYFromDirection(plot.x,plot.y,direction)
- i = GetRxIndex(xx,yy)
- if i == -1 or self.rxTouchesMapEdge(xx,yy):
- if self.canRegionGrowHere(xx,yy,plot.regionID):
- self.regionRxMap[i] = plot.regionID
- newPlot = RegionPlot(plot.regionID,xx,yy)
- self.regionPlotList.append(newPlot)
- if region.isTouchingNeighbor:
- region.isGrowing = False
- continue
- if self.canRegionGrowHere(xx,yy,plot.regionID):
- roomLeft = True
- if PRand.random() < mc.ChanceToGrow:
- self.regionRxMap[i] = plot.regionID
- newPlot = RegionPlot(plot.regionID,xx,yy)
- self.regionPlotList.append(newPlot)
- #move plot to the end of the list if room left, otherwise
- #delete it if no room left
- if roomLeft:
- self.regionPlotList.append(plot)
- del self.regionPlotList[0]
- ## self.PrintRegionRxMap(False)
- #Now convert regionRxMap to regionMap
- for y in range(mapSize.MapHeight + 1):
- for x in range(mapSize.MapWidth + 1):
- i = GetRxIndex(x,y)
- regionID = self.regionRxMap[i]
- if regionID != -1:
- region = self.getRegionByID(regionID)
- for direction in range(5,9,1):
- xx,yy = self.plotFromRx(x,y,direction)
- if xx == 71 and yy == 71:
- print "x=%d,y=%d,xx=%d,yy=%d" % (x,y,xx,yy)
- ii = GetIndex(xx,yy)
- if ii != -1:
- self.regionMap[ii] = regionID
- newPlot = RegionPlot(regionID,xx,yy)
- region.plotList.append(newPlot)
- #Mark border tiles and neighbor regions
- for region in self.regionList:
- for plot in region.plotList:
- i = GetIndex(plot.x,plot.y)
- for direction in range(1,5,1):
- if direction == 1:#N
- xx = plot.x
- yy = plot.y + 1
- elif direction == 2:#S
- xx = plot.x
- yy = plot.y - 1
- elif direction == 3:#E
- xx = plot.x + 1
- yy = plot.y
- else:#W
- xx = plot.x - 1
- yy = plot.y
- ii = GetIndex(xx,yy)
- if ii != -1 and self.regionMap[ii] != -1 and \
- self.regionMap[ii] != region.ID:
- plot.bBorder = True
- plot.bEdge = True
- AppendUnique(region.neighborList,self.regionMap[ii])
- elif self.regionMap[ii] == -1:
- plot.bEdge = True
- ## self.PrintRegionMap(False)
- #Now choose areas to be water
- numWaterRegions = int(float(numTiles) * mc.WaterRegionsPerPlot)
- print "numTiles = %(n)d, numWaterRegions = %(w)d" % {"n":numTiles,"w":numWaterRegions}
- self.regionList = ShuffleList(self.regionList)
- #Try to start with the region in the middle (there is a low chance that there isn't one)
- i = GetIndex(mapSize.MapWidth/2, mapSize.MapHeight/2)
- regionID = self.regionMap[i]
- if regionID == -1:
- self.regionList[0].isWater = True
- else:
- region = self.getRegionByID(regionID)
- region.isWater = True
- for i in range(numWaterRegions):
- self.regionList = ShuffleList(self.regionList)
- for nRegion in self.regionList:
- nRegion.waterNeighborCount = nRegion.getWaterNeighborCount()
- self.regionList.sort(lambda x,y:cmp(x.waterNeighborCount,y.waterNeighborCount))
- for nRegion in self.regionList:
- if nRegion.waterNeighborCount > 0 and nRegion.isWater == False:
- nRegion.isWater = True
- break
- ## self.PrintRegionMap(False)
- #Now fill any non-areas adjacent to water with the water area
- for region in self.regionList:
- if region.isWater == False:
- continue
- regionExpanding = True
- while(regionExpanding):
- regionExpanding = region.expandWaterRegion()
- ## self.PrintRegionMap(False)
- return
- def canRegionGrowHere(self,x,y,regionID):
- i = GetRxIndex(x,y)
- if i == -1:
- return False
- if self.regionRxMap[i] != -1:
- return False
- region = self.getRegionByID(regionID)
- if not region.isGrowing:
- return False
- assume = True
- for direction in range(1,9,1):
- xx,yy = self.getXYFromDirection(x,y,direction)
- ii = GetRxIndex(xx,yy)
- if ii == -1 or self.regionRxMap[ii] == regionID:
- continue
- elif self.regionRxMap[ii] == -1:
- continue
- else:#region is touching a neighbor
- region.isTouchingNeighbor = True
- assume = False
- return assume
- def rxTouchesMapEdge(self,x,y):
- if x >= (mapSize.MapWidth + 1) - mc.EdgeLimit or x < mc.EdgeLimit:
- return True
- if y >= (mapSize.MapHeight + 1) - mc.EdgeLimit or y < mc.EdgeLimit:
- return True
- return False
- def plotFromRx(self,rxX,rxY,direction):
- if direction == self.NE:
- x = rxX
- y = rxY
- elif direction == self.NW:
- x = rxX - 1
- y = rxY
- elif direction == self.SE:
- x = rxX
- y = rxY - 1
- else:#SW
- x = rxX - 1
- y = rxY - 1
- #check for validity
- if x < 0 or x >= mapSize.MapWidth:
- return -1,-1
- if y < 0 or y >= mapSize.MapHeight:
- return -1,-1
- return x,y
- def getXYFromDirection(self,x,y,direction):
- xx = x
- yy = y
- if direction == self.N:
- yy += 1
- elif direction == self.S:
- yy -= 1
- elif direction == self.E:
- xx += 1
- elif direction == self.W:
- xx -= 1
- elif direction == self.NW:
- yy += 1
- xx -= 1
- elif direction == self.NE:
- yy += 1
- xx += 1
- elif direction == self.SW:
- yy -= 1
- xx -= 1
- elif direction == self.SE:
- yy -= 1
- xx += 1
- return xx,yy
- def isSeedBlocked(self,seedX,seedY):
- for region in self.regionList:
- if seedX > region.seedX - mc.MinSeedRange and seedX < region.seedX + mc.MinSeedRange:
- if seedY > region.seedY - mc.MinSeedRange and seedY < region.seedY + mc.MinSeedRange:
- return True
- #Check for edge
- if seedX < mc.MinEdgeRange or seedX >= (mapSize.MapWidth + 1) - mc.MinEdgeRange:
- return True
- if seedY < mc.MinEdgeRange or seedY >= (mapSize.MapHeight + 1) - mc.MinEdgeRange:
- return True
- return False
- def getRegionByID(self,ID):
- for region in self.regionList:
- if region.ID == ID:
- return region
- return None
- def PrintRegionMap(self,bShowWater):
- print "Region Map"
- for y in range(mapSize.MapHeight - 1,-1,-1):
- lineString = ""
- for x in range(mapSize.MapWidth):
- mapLoc = self.regionMap[GetIndex(x,y)]
- region = self.getRegionByID(mapLoc)
- if mapLoc == -1:
- lineString += "X"
- elif bShowWater and region.isWater == True:
- lineString += " "
- else:
- lineString += chr(mapLoc + 33)
- print lineString
- lineString = " "
- print lineString
- def PrintRegionRxMap(self,bShowWater):
- print "Region Map"
- for y in range(mapSize.MapHeight,-1,-1):
- lineString = ""
- for x in range(mapSize.MapWidth + 1):
- mapLoc = self.regionRxMap[GetRxIndex(x,y)]
- region = self.getRegionByID(mapLoc)
- if mapLoc == -1:
- lineString += "X"
- elif bShowWater and region.isWater == True:
- lineString += " "
- else:
- lineString += chr(mapLoc + 33)
- print lineString
- lineString = " "
- print lineString
- def PrintRegionList(self):
- print "Number of regions = %(n)d" % {"n":len(self.regionList)}
- for region in self.regionList:
- print str(region)
- return
- regMap = RegionMap()
- class RegionPlot :
- def __init__(self,ID,x,y):
- self.regionID = ID
- self.x = x
- self.y = y
- self.gateRx = -1
- self.bBorder = False
- self.bEdge = False
- class Region :
- def __init__(self,ID,seedX,seedY):
- self.ID = ID
- self.seedX = seedX
- self.seedY = seedY
- self.isGrowing = True
- self.neighborList = list()
- self.gateRegion = -1
- self.gatePlot = None
- self.plotList = list()
- self.isWater = False
- self.isTouchingNeighbor = False
- self.altitude = 0.0
- self.moisture = 1.0
- def __str__(self):
- string = "ID=%(id)d(%(c)s), size=%(s)d, altitude=%(a)d \n" % {"id":self.ID,"c":chr(self.ID + 33),"s":len(self.plotList),"a":self.altitude}
- string += "gateRegion=%(id)d(%(c)s) \n" % {"id":self.gateRegion,"c":chr(self.gateRegion + 33)}
- string += " " + self.NeighborListString() + "\n"
- return string
- def NeighborListString(self):
- string = "["
- for ID in self.neighborList:
- string += chr(ID + 33) + ","
- string += "]"
- return string
- def getWaterNeighborCount(self):
- count = 0
- for regionID in self.neighborList:
- region = regMap.getRegionByID(regionID)
- if region.isWater == True:
- count += 1
- return count
- def getBorderPlotList(self,neighborID):
- borderPlotList = list()
- borderPlotCount = 0
- for plot in self.plotList:
- if plot.bBorder == True:
- borderPlotCount += 1
- for direction in range(1,5,1):
- if direction == 1:#N
- xx = plot.x
- yy = plot.y + 1
- elif direction == 2:#S
- xx = plot.x
- yy = plot.y - 1
- elif direction == 3:#E
- xx = plot.x + 1
- yy = plot.y
- else:#W
- xx = plot.x - 1
- yy = plot.y
- ii = GetIndex(xx,yy)
- if ii != -1 and regMap.regionMap[ii] == neighborID:
- borderPlotList.append(plot)
- break
- print "borderPlotCount=%(bc)d" % {"bc":borderPlotCount}
- return borderPlotList
- def getGateListToNeighbor(self,neighborID):
- gateListToNeighbor = list()
- for rPlot in self.gateList:
- if riverMap.isRxTouchingRegion(rPlot.x,rPlot.y,neighborID):
- gateListToNeighbor.append(rPlot)
- ## print "%(ng)d gates from %(s)d to %(n)d" % \
- ## {"ng":len(gateListToNeighbor),"s":self.ID,"n":neighborID}
- return gateListToNeighbor
- def defineValidGateList(self):
- #This function is called in createFlowMap so the riverMap functions
- #can be called from here. We now complile a list of all possible river
- #gates
- self.gateList = list()
- for rxY in range(mapSize.MapHeight + 1):
- for rxX in range(mapSize.MapWidth + 1):
- if riverMap.isRxTouchingRegion(rxX,rxY,self.ID):
- if riverMap.isValidFullGate(self.ID,rxX,rxY):
- rPlot = RiverPlot(rxX,rxY,-1,self.ID)
- self.gateList.append(rPlot)
- return
- def expandWaterRegion(self):
- expanded = False
- for plot in self.plotList:
- for direction in range(1,5,1):
- if direction == 1:#N
- xx = plot.x
- yy = plot.y + 1
- elif direction == 2:#S
- xx = plot.x
- yy = plot.y - 1
- elif direction == 3:#E
- xx = plot.x + 1
- yy = plot.y
- else:#W
- xx = plot.x - 1
- yy = plot.y
- ii = GetIndex(xx,yy)
- if ii != -1 and regMap.regionMap[ii] == -1:
- naPlot = RegionPlot(self.ID,xx,yy)
- regMap.regionMap[ii] = self.ID
- self.plotList.append(naPlot)
- expanded = True
- break
- return expanded
- def getGatedNeighborList(self):
- gatedList = list()
- for regionID in self.neighborList:
- region = regMap.getRegionByID(regionID)
- if region.isWater or region.gateRegion != -1:
- validGateList = self.getGateListToNeighbor(regionID)
- if len(validGateList) > 0:
- gatedList.append(region.ID)
- return gatedList
- def getDistanceToClosestBorderPlot(self,plot):
- minDistance = 100.0
- for bPlot in self.plotList:
- if bPlot.bEdge == False:
- continue
- distance = GetDistance(plot.x,plot.y,bPlot.x,bPlot.y)
- if distance < minDistance:
- minDistance = distance
- return minDistance
- #In this case the center is the plot farthest from any border
- def getCenter(self):
- maxDistance = 0.0
- center = None
- for plot in self.plotList:
- distance = self.getDistanceToClosestBorderPlot(plot)
- if maxDistance < distance:
- maxDistance = distance
- ## print "maxDistance= %(m)f, plot.x= %(x)d, plot.y=%(y)d" % \
- ## {"m":maxDistance,"x":plot.x,"y":plot.y}
- center = plot
- return center
- class RiverMap :
- def __init__(self):
- return
- def createRiverMap(self):
- self.createFlowMap()
- self.calculateWetAndDry()
- self.riverMap = array('f')
- for i in range((mapSize.MapHeight + 1) * (mapSize.MapWidth + 1)):
- self.riverMap.append(0)
- for y in range(mapSize.MapHeight + 1):
- for x in range(mapSize.MapWidth + 1):
- i = self.getRiverIndex(x,y)
- direction = self.flowMap[i]
- regionID = self.getRegion(x,y)
- region = regMap.getRegionByID(regionID)
- xx = x
- yy = y
- while direction != -1 and direction != self.L:
- xx,yy = self.getXYFromDirection(xx,yy,direction)
- ii = self.getRiverIndex(xx,yy)
- self.riverMap[ii] += mc.MinRainfall + (1.0 - mc.MinRainfall) * region.moisture
- direction = self.flowMap[ii]
- return
- def createFlowMap(self):
- #Start with an outflow from the region, then randomly decide which neighbors
- #will flow into this square by how many choices that neighbor has. If the
- #neighbor has only one choice, then the chance is 100 percent. At least
- #one neighbor must be chosen unless it is not possible, otherwise the
- #process might end before each tile is set. Then put each chosen neighbor
- #on the stack to be processed the same way.
- self.L = 0
- self.N = 1
- self.S = 2
- self.E = 3
- self.W = 4
- self.NE = 5
- self.NW = 6
- self.SE = 7
- self.SW = 8
- self.heightMap = array('d')
- self.flowMap = array('i')
- for i in range((mapSize.MapHeight + 1) * (mapSize.MapWidth + 1)):
- self.flowMap.append(-1)
- self.heightMap.append(-1.0)
- self.defineGates()
- print "Gates Defined !!!!!!!!!!!!!!!!!!!!!!!!"
- for region in regMap.regionList:
- if region.isWater == True:
- continue
- #randomly choose an outflow gate
- ## print "region.gateRegion = %(gr)d" % {"gr":region.gateRegion}
- validGateList = region.getGateListToNeighbor(region.gateRegion)
- if len(validGateList) == 0:
- print "validGateList == 0!!!!!!!!!!!!!!!!!!!!"
- print "region = %(r)s" % {"r":str(region)}
- gRegion = regMap.getRegionByID(region.gateRegion)
- print "gateRegion = %(g)s" % {"g":str(gRegion)}
- raise ValueError, "region has neighbor but no valid gates. see debug file"
- region.gatePlot = validGateList[PRand.randint(0,len(validGateList)-1)]
- rxX = region.gatePlot.x
- rxY = region.gatePlot.y
- rxI = self.getRiverIndex(rxX,rxY)
- #set flow so that it is pointing out of region
- iterations = 0
- while(True):
- iterations += 1
- if iterations > 100:
- raise ValueError, "endless loop in gate setter"
- gateRegion = regMap.getRegionByID(region.gateRegion)
- if gateRegion.isWater:
- self.flowMap[rxI] = self.L
- self.heightMap[rxI] = 0.01
- break
- #pick random cardinal direction
- direction = PRand.randint(1,4)
- ## print direction
- xx,yy = self.getXYFromDirection(rxX,rxY,direction)
- if self.isRxInRegion(xx,yy,region.gateRegion):
- self.flowMap[rxI] = direction
- self.heightMap[rxI] = 0.01
- break
- #Now create heightmap. Start from each gate and increase altitude of
- #neighbors by a random percentage, and then place each neighbor on a
- #queue for similar processing. Randomize the queue order for each pass.
- #This method should avoid lakes.
- #Place all gates on queue.
- plotList = list()
- regMap.PrintRegionList()
- for region in regMap.regionList:
- if region.gatePlot == None:
- continue
- rxX = region.gatePlot.x
- rxY = region.gatePlot.y
- ## print "rxX=%(x)d, rxY=%(y)d" % {"x":rxX,"y":rxY}
- riverPlot = RiverPlot(rxX,rxY,0,region.ID)
- plotList.append(riverPlot)
- ## print "hi"
- while(len(plotList) > 0):
- ## print "len plotList = v"
- ## print len(plotList)
- count = len(plotList)
- plotList = ShuffleList(plotList)
- for n in range(count):
- thisPlot = plotList.pop(0)#queue method, not stack
- ## print "popping"
- rxI = self.getRiverIndex(thisPlot.x,thisPlot.y)
- altitude = self.heightMap[rxI]
- for direction in range(1,5,1):
- x,y = self.getXYFromDirection(thisPlot.x,thisPlot.y,direction)
- rxII = self.getRiverIndex(x,y)
- ## print "rxII=%(i)d, x=%(x)d, y=%(y)d, heightMap=%(h)f, isRxInRegion=%(ir)d" % \
- ## {"i":rxII,"x":x,"y":y,"h":self.heightMap[rxII],"ir":self.isRxInRegion(x,y,thisPlot.regionID)}
- if rxII != -1 and self.heightMap[rxII] == -1.0 and \
- self.isRxInRegion(x,y,thisPlot.regionID):
- randomScaler = 1.0 + float(PRand.randint(1,20))/100.0
- self.heightMap[rxII] = altitude * randomScaler
- newPlot = RiverPlot(x,y,0,thisPlot.regionID)
- plotList.append(newPlot)
- ## print "newPlot appended"
- #Create flow map
- for y in range(mapSize.MapHeight + 1):
- for x in range(mapSize.MapWidth + 1):
- paths = self.getPossiblePaths(x,y)
- if len(paths) > 0:
- i = self.getRiverIndex(x,y)
- pathIndex = PRand.randint(0,len(paths)-1)
- self.flowMap[i] = paths[pathIndex]
- return
- #Dryness should be calculated by getting the highest altitude
- #region and making it's base the wettest region. Then eliminate
- #those regions from the list. Then get the highest of the remaining
- #regions and make it's base the dryest region.
- def calculateWetAndDry(self):
- regionList = list()
- for region in regMap.regionList:
- regionList.append(region)
- regionList.sort(lambda x,y:cmp(x.altitude,y.altitude))
- regionList.reverse()
- region = regionList[0]
- while(region.altitude > 0):
- region = regMap.getRegionByID(region.gateRegion)
- if region.altitude == 1:
- self.wetSpot = riverMap.plotFromRx(region.gatePlot.x,region.gatePlot.y,riverMap.SW)
- #Now calculate moisture for each region
- minMoisture = 1.0
- for region in regMap.regionList:
- gate = region.gatePlot
- if gate == None:
- continue
- wetSpotX,wetSpotY = self.wetSpot
- distance = GetDistance(gate.x,gate.y,wetSpotX,wetSpotY)
- region.moisture = 1.0 - distance/float(mapSize.MapWidth)
- minMoisture = min(region.moisture,minMoisture)
- scaler = 1.0/(1.0 - minMoisture)
- for region in regMap.regionList:
- region.moisture = (region.moisture - minMoisture) * scaler
- return
- def defineGates(self):
- #Now each region picks one gate that is not in the current gate line
- #to avoid recursive loops
- numRegions = len(regMap.regionList)
- numGatesPlaced = 0
- iterations = 0
- #water is considered gated for this purpose
- for region in regMap.regionList:
- region.defineValidGateList()
- #regions should always have gates
- if len(region.gateList) == 0:
- print str(region)
- print "has no gates!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
- regMap.PrintRegionMap(False)
- raise ValueError, "region has no gates"
- while numGatesPlaced < numRegions:
- if iterations > 500:
- raise ValueError, "Endless loop occured in gate placement"
- break
- else:
- iterations += 1
- regMap.regionList = ShuffleList(regMap.regionList)
- for region in regMap.regionList:
- if region.gateRegion == -1:
- gatedNeighborList = region.getGatedNeighborList()
- if len(gatedNeighborList) > 0:
- gatedNeighborList = ShuffleList(gatedNeighborList)
- region.gateRegion = gatedNeighborList[0]
- if region.isWater:
- region.altitude = 0
- else:
- gateRegion = regMap.getRegionByID(region.gateRegion)
- region.altitude = gateRegion.altitude + 1
- ## print "region %(r)d gateRegion is %(g)d" % \
- ## {"r":region.ID,"g":region.gateRegion}
- numGatesPlaced += 1
- def isValidHalfGate(self,regionID,rxX,rxY):
- #A valid half gate is a rx that is not in a region, touches
- #only 2 regions and is 4-connected to an rx that is in the region
- regionList = list()
- for direction in range(5,9,1):
- px,py = self.plotFromRx(rxX,rxY,direction)
- i = GetIndex(px,py)
- pRegID = regMap.regionMap[i]
- if pRegID == -1:
- return False
- AppendUnique(regionList,pRegID)
- if len(regionList) != 2:
- return False
- if self.isRxInRegion(rxX,rxY,regionID):
- return False
- for direction in range(1,5,1):
- xx,yy = self.getXYFromDirection(rxX,rxY,direction)
- if self.isRxInRegion(xx,yy,regionID):
- return True
- return False
- def isValidFullGate(self,regionID,rxX,rxY):
- if not self.isValidHalfGate(regionID,rxX,rxY):
- return False
- region = regMap.getRegionByID(regionID)
- for nRegionID in region.neighborList:
- if self.isValidHalfGate(nRegionID,rxX,rxY):
- return True
- for direction in range(1,5,1):
- xx,yy = self.getXYFromDirection(rxX,rxY,direction)
- if self.isValidHalfGate(nRegionID,rxX,rxY):
- return True
- return False
- def getPossiblePaths(self,rxX,rxY):
- possiblePaths = list()
- regionID = self.getRegion(rxX,rxY)
- if regionID == -1:
- return possiblePaths
- region = regMap.getRegionByID(regionID)
- if region.isWater == True:
- return possiblePaths
- rxI = self.getRiverIndex(rxX,rxY)
- altitude = self.heightMap[rxI]
- rejectedDirection = self.L
- for direction in range(1,5,1):
- x,y = self.getXYFromDirection(rxX,rxY,direction)
- i = self.getRiverIndex(x,y)
- if self.isRxInRegion(x,y,regionID):
- if self.heightMap[i] > altitude:
- if rejectedDirection == self.L:
- rejectedDirection = self.getOppositeDirection(direction)
- else:
- rejectedDirection = self.L
- for direction in range(1,5,1):
- x,y = self.getXYFromDirection(rxX,rxY,direction)
- if self.isRxInRegion(x,y,regionID) or \
- (x == region.gatePlot.x and y == region.gatePlot.y) :
- i = self.getRiverIndex(x,y)
- if i != -1 and self.heightMap[i] < altitude:
- possiblePaths.append(direction)
- if len(possiblePaths) > 1:
- for n in range(len(possiblePaths)):
- if rejectedDirection == possiblePaths[n]:
- del possiblePaths[n]
- break
- return possiblePaths
- def fillInLake(self,rxX,rxY):
- rxI = self.getRiverIndex(rxX,rxY)
- altitude = self.heightMap[rxI]
- regionID = self.getRegion(rxX,rxY)
- lowestNeighbor = 1.0
- for direction in range(1,5,1):
- x,y = self.getXYFromDirection(rxX,rxY,direction)
- i = self.getRiverIndex(x,y)
- if self.isRxInRegion(x,y,regionID) == True:
- if self.heightMap[i] < lowestNeighbor:
- lowestNeighbor = self.heightMap[i]
- if altitude < lowestNeighbor:
- self.heightMap[rxI] = altitude + ((lowestNeighbor - altitude)/2.0)
- else:
- self.heightMap[rxI] = altitude * 1.05
- def isLake(self,rxX,rxY):
- rxI = self.getRiverIndex(rxX,rxY)
- altitude = self.heightMap[rxI]
- regionID = self.getRegion(rxX,rxY)
- lowestNeighbor = 1.0
- for direction in range(1,5,1):
- x,y = self.getXYFromDirection(rxX,rxY,direction)
- i = self.getRiverIndex(x,y)
- if self.isRxInRegion(x,y,regionID) == True:
- if self.heightMap[i] < lowestNeighbor:
- lowestNeighbor = self.heightMap[i]
- if lowestNeighbor >= altitude:
- return True
- return False
- def isOutFlowGate(self,rxX,rxY):
- for region in regMap.regionList:
- if region.isWater == False:
- gateRxX,gateRxY = self.rxFromPlot(region.gatePlot.x,region.gatePlot.y,self.SW)
- if gateRxX == rxX and gateRxY == rxY:
- return True
- return False
- def getOppositeDirection(self,direction):
- opposite = self.L
- if direction == self.N:
- opposite = self.S
- elif direction == self.S:
- opposite = self.N
- elif direction == self.E:
- opposite = self.W
- elif direction == self.W:
- opposite = self.E
- return opposite
- def getXYFromDirection(self,x,y,direction):
- xx = x
- yy = y
- if direction == self.N:
- yy += 1
- elif direction == self.S:
- yy -= 1
- elif direction == self.E:
- xx += 1
- elif direction == self.W:
- xx -= 1
- return xx,yy
- def getRiverIndex(self,x,y):
- if x < 0 or x >= mapSize.MapWidth + 1:
- return -1
- else:
- xx = x
- if y < 0 or y >= mapSize.MapHeight + 1:
- return -1
- else:
- yy = y
- i = yy * (mapSize.MapWidth + 1) + xx
- return i
- def isRxInRegion(self,x,y,regionID):
- #Rxs on the border are not in region. All plots touching rx must
- #be in region
- for direction in range(5,9,1):
- xx,yy = self.plotFromRx(x,y,direction)
- i = GetIndex(xx,yy)
- if i == -1 or regMap.regionMap[i] != regionID:
- return False
- return True
- def getRegion(self,x,y):
- #Rxs on the border are not in region. All plots touching rx must
- #be in region, unless this is the gate for that region
- xx,yy = self.plotFromRx(x,y,self.SW)
- i = GetIndex(xx,yy)
- regionID = regMap.regionMap[i]
- invalidRegion = False
- for direction in range(5,9,1):
- xx,yy = self.plotFromRx(x,y,direction)
- i = GetIndex(xx,yy)
- nRegionID = regMap.regionMap[i]
- if nRegionID == -1:
- continue
- #test if this main plot is gate for this region
- nRegion = regMap.getRegionByID(nRegionID)
- if nRegion.gatePlot != None and \
- x == nRegion.gatePlot.x and y == nRegion.gatePlot.y:
- return nRegionID
- if nRegionID != regionID:
- invalidRegion = True
- if invalidRegion:
- return -1
- return regionID
- def isRxTouchingRegion(self,x,y,regionID):
- #Check all four plots
- plotX,plotY = self.plotFromRx(x,y,self.NW)
- i = GetIndex(plotX,plotY)
- if i != -1 and regMap.regionMap[i] == regionID:
- return True
- plotX,plotY = self.plotFromRx(x,y,self.NE)
- i = GetIndex(plotX,plotY)
- if i != -1 and regMap.regionMap[i] == regionID:
- return True
- plotX,plotY = self.plotFromRx(x,y,self.SW)
- i = GetIndex(plotX,plotY)
- if i != -1 and regMap.regionMap[i] == regionID:
- return True
- plotX,plotY = self.plotFromRx(x,y,self.SE)
- i = GetIndex(plotX,plotY)
- if i != -1 and regMap.regionMap[i] == regionID:
- return True
- return False
- def rxFromPlot(self,plotX,plotY,direction):
- if direction == self.SW:
- x = plotX
- y = plotY
- elif direction == self.SE:
- x = plotX + 1
- y = plotY
- elif direction == self.NW:
- x = plotX
- y = plotY + 1
- else:#NE
- x = plotX + 1
- y = plotY + 1
- #check for validity
- if x < 0 or x >= mapSize.MapWidth + 1:
- return -1,-1
- if y < 0 or y >= mapSize.MapHeight + 1:
- return -1,-1
- return x,y
- def plotFromRx(self,rxX,rxY,direction):
- if direction == self.NE:
- x = rxX
- y = rxY
- elif direction == self.NW:
- x = rxX - 1
- y = rxY
- elif direction == self.SE:
- x = rxX
- y = rxY - 1
- else:#SW
- x = rxX - 1
- y = rxY - 1
- #check for validity
- if x < 0 or x >= mapSize.MapWidth:
- return -1,-1
- if y < 0 or y >= mapSize.MapHeight:
- return -1,-1
- return x,y
- def PrintFlowMap(self):
- print "Flow Map"
- for y in range(mapSize.MapHeight,-1,-1):
- lineString = ""
- for x in range(mapSize.MapWidth + 1):
- mapLoc = self.flowMap[self.getRiverIndex(x,y)]
- if mapLoc == -1:
- lineString += "X"
- elif mapLoc == self.N:
- lineString += "N"
- elif mapLoc == self.S:
- lineString += "S"
- elif mapLoc == self.E:
- lineString += "E"
- elif mapLoc == self.W:
- lineString += "W"
- else:
- lineString += "X"
- print lineString
- lineString = " "
- print lineString
- riverMap = RiverMap()
- class RiverPlot :
- def __init__(self,x,y,direction,regionID):
- self.x = x
- self.y = y
- self.direction = direction
- self.regionID = regionID
- return
- class PlotMap :
- def __init__(self):
- return
- def createPlotMap(self):
- self.OCEAN = 0
- self.LAND = 1
- self.HILLS = 2
- self.PEAK = 3
- self.L = 0
- self.N = 1
- self.S = 2
- self.E = 3
- self.W = 4
- self.NE = 5
- self.NW = 6
- self.SE = 7
- self.SW = 8
- self.plotMap = array('i')
- scrambledPlotList = list()
- regMap.regionList.sort(lambda n,m: cmp(n.altitude,m.altitude))
- regMap.regionList.reverse()
- regMap.highestRegionAltitude = regMap.regionList[0].altitude
- for y in range(mapSize.MapHeight):
- for x in range(mapSize.MapWidth):
- self.plotMap.append(self.OCEAN)
- scrambledPlotList.append((x,y))
- scrambledPlotList = ShuffleList(scrambledPlotList)
- for n in range(len(scrambledPlotList)):
- x,y = scrambledPlotList[n]
- i = GetIndex(x,y)
- if self.shouldPlacePeak(x,y):
- if self.plotMap[i] != self.HILLS:
- self.plotMap[i] = self.PEAK
- else:
- regionID = regMap.regionMap[i]
- region = regMap.getRegionByID(regionID)
- if not region.isWater:
- self.plotMap[i] = self.LAND
- self.placeLandInWater(x,y)
- for n in range(len(scrambledPlotList)):
- x,y = scrambledPlotList[n]
- i = GetIndex(x,y)
- regionID = regMap.regionMap[i]
- if regionID == -1:
- continue
- region = regMap.getRegionByID(regionID)
- if region.isWater and plotMap.plotMap[i] != plotMap.OCEAN:
- for direction in range(1,5,1):
- xx,yy = self.getXYFromDirection(x,y,direction)
- ii = GetIndex(xx,yy)
- nRegionID = regMap.regionMap[ii]
- if nRegionID == -1:
- continue
- nRegion = regMap.getRegionByID(nRegionID)
- if not nRegion.isWater:
- regMap.regionMap[i] = nRegionID
- break
- for n in range(len(scrambledPlotList)):
- x,y = scrambledPlotList[n]
- i = GetIndex(x,y)
- #Decide if hill or peak should be here
- if self.plotMap[i] == self.LAND:
- altitude = GetPlotAltitude(x,y)
- hillChanceRange = mc.HillChanceAtOne - mc.HillChanceAtZero
- hillChance = mc.HillChanceAtZero + (altitude * hillChanceRange)
- if PRand.random() < hillChance:
- self.plotMap[i] = self.HILLS
- peakChanceRange = mc.PeakChanceAtOne - mc.PeakChanceAtZero
- peakChance = mc.PeakChanceAtZero + (altitude * peakChanceRange)
- if PRand.random() < peakChance:
- self.plotMap[i] = self.PEAK
- #now there's a chance to flatten it again!
- if self.plotMap[i] != self.LAND:
- riverSize = GetRiverSize(x,y)
- maxRiverSize = float(mc.RiverThreshold) * mc.RiverFactorFlattensAll
- riverSize = min(maxRiverSize,riverSize)
- flattenChance = riverSize/maxRiverSize
- ## print flattenChance
- if PRand.random() < flattenChance:
- self.plotMap[i] = self.LAND
- #now make sure that rivers are not flowing between peaks
- if self.plotMap[i] == self.PEAK:
- if self.shouldFlattenRiverPeak(x,y):
- riverSize = GetRiverSize(x,y)
- maxRiverSize = float(mc.RiverThreshold) * mc.RiverFactorFlattensAll
- if riverSize > maxRiverSize:
- self.plotMap[i] = self.LAND
- else:
- self.plotMap[i] = self.HILLS
- #Now for SoftenPeakPercent of peaks, make them hills
- for y in range(1,mapSize.MapHeight - 1):
- for x in range(1,mapSize.MapWidth - 1):
- i = GetIndex(x,y)
- if self.plotMap[i] == self.PEAK:
- if mc.SoftenPeakPercent >= PRand.random():
- self.plotMap[i] = self.HILLS
- #Now make sure there are no passable areas that are blocked in
- ## self.PrintPlotMap()
- areaMap = Areamap(mapSize.MapWidth,mapSize.MapHeight)
- areaMap.findImpassableAreas()
- ## areaMap.PrintAreaMap()
- for i in range(mapSize.MapWidth*mapSize.MapHeight):
- if areaMap.areaMap[i] == 0:
- if self.plotMap[i] != self.PEAK:
- self.plotMap[i] = self.PEAK
- else:
- areaMap.areaMap[i] = 1
- ## areaMap.PrintAreaMap()
- def shouldFlattenRiverPeak(self,x,y):
- direction = riverMap.NW
- rxX,rxY = riverMap.rxFromPlot(x,y,direction)
- rxI = riverMap.getRiverIndex(rxX,rxY)
- if riverMap.riverMap[rxI] > mc.RiverThreshold:
- pDir = direction
- xx,yy = self.getXYFromDirection(x,y,pDir)
- ii = GetIndex(xx,yy)
- if self.plotMap[ii] == self.PEAK:
- return True
- if riverMap.flowMap[rxI] == riverMap.E:
- pDir = self.N
- xx,yy = self.getXYFromDirection(x,y,pDir)
- ii = GetIndex(xx,yy)
- if self.plotMap[ii] == self.PEAK:
- return True
- if riverMap.flowMap[rxI] == riverMap.S:
- pDir = self.W
- xx,yy = self.getXYFromDirection(x,y,pDir)
- ii = GetIndex(xx,yy)
- if self.plotMap[ii] == self.PEAK:
- return True
- direction = riverMap.NE
- rxX,rxY = riverMap.rxFromPlot(x,y,direction)
- rxI = riverMap.getRiverIndex(rxX,rxY)
- if riverMap.riverMap[rxI] > mc.RiverThreshold:
- pDir = direction
- xx,yy = self.getXYFromDirection(x,y,pDir)
- ii = GetIndex(xx,yy)
- if self.plotMap[ii] == self.PEAK:
- return True
- if riverMap.flowMap[rxI] == riverMap.W:
- pDir = self.N
- xx,yy = self.getXYFromDirection(x,y,pDir)
- ii = GetIndex(xx,yy)
- if self.plotMap[ii] == self.PEAK:
- return True
- if riverMap.flowMap[rxI] == riverMap.S:
- pDir = self.E
- xx,yy = self.getXYFromDirection(x,y,pDir)
- ii = GetIndex(xx,yy)
- if self.plotMap[ii] == self.PEAK:
- return True
- direction = riverMap.SE
- rxX,rxY = riverMap.rxFromPlot(x,y,direction)
- rxI = riverMap.getRiverIndex(rxX,rxY)
- if riverMap.riverMap[rxI] > mc.RiverThreshold:
- pDir = direction
- xx,yy = self.getXYFromDirection(x,y,pDir)
- ii = GetIndex(xx,yy)
- if self.plotMap[ii] == self.PEAK:
- return True
- if riverMap.flowMap[rxI] == riverMap.W:
- pDir = self.S
- xx,yy = self.getXYFromDirection(x,y,pDir)
- ii = GetIndex(xx,yy)
- if self.plotMap[ii] == self.PEAK:
- return True
- if riverMap.flowMap[rxI] == riverMap.N:
- pDir = self.E
- xx,yy = self.getXYFromDirection(x,y,pDir)
- ii = GetIndex(xx,yy)
- if self.plotMap[ii] == self.PEAK:
- return True
- direction = riverMap.SW
- rxX,rxY = riverMap.rxFromPlot(x,y,direction)
- rxI = riverMap.getRiverIndex(rxX,rxY)
- if riverMap.riverMap[rxI] > mc.RiverThreshold:
- pDir = direction
- xx,yy = self.getXYFromDirection(x,y,pDir)
- ii = GetIndex(xx,yy)
- if self.plotMap[ii] == self.PEAK:
- return True
- if riverMap.flowMap[rxI] == riverMap.E:
- pDir = self.S
- xx,yy = self.getXYFromDirection(x,y,pDir)
- ii = GetIndex(xx,yy)
- if self.plotMap[ii] == self.PEAK:
- return True
- if riverMap.flowMap[rxI] == riverMap.N:
- pDir = self.W
- xx,yy = self.getXYFromDirection(x,y,pDir)
- ii = GetIndex(xx,yy)
- if self.plotMap[ii] == self.PEAK:
- return True
- return False
- def placeLandInWater(self,x,y):
- i = GetIndex(x,y)
- regionID = regMap.regionMap[i]
- if regionID == -1:
- return False
- region = regMap.getRegionByID(regionID)
- borderPlotIsLand = False
- for direction in range(1,5,1):
- xx,yy = self.getXYFromDirection(x,y,direction)
- ii = GetIndex(xx,yy)
- if ii == -1:
- continue
- if self.plotMap[ii] != self.OCEAN and \
- regMap.regionMap[ii] != regionID:
- if IsPlotTouchingRiver(x,y):
- oceanNeighborTouchingRiver = False
- for dir2 in range(1,5,1):
- xxx,yyy = self.getXYFromDirection(x,y,dir2)
- iii = GetIndex(xxx,yyy)
- if self.plotMap[iii] == self.OCEAN and \
- IsPlotTouchingRiver(xxx,yyy):
- oceanNeighborTouchingRiver = True
- if oceanNeighborTouchingRiver == False:
- continue
- oppDirection = self.getOppositeDirection(direction)
- xxx,yyy = self.getXYFromDirection(x,y,oppDirection)
- if not IsPlotSurroundedByOcean(xxx,yyy):
- continue
- if PRand.randint(0,1) == 0:
- nRegion = regMap.getRegionByID(regMap.regionMap[ii])
- if nRegion != None:
- print "placing land in water"
- if nRegion.altitude < 2:
- self.plotMap[i] = self.LAND
- elif nRegion.altitude < 3 and regMap.highestRegionAltitude >= 3:
- self.plotMap[i] = self.HILLS
- else:
- self.plotMap[i] = self.PEAK
- return False
- def getOppositeDirection(self,direction):
- opposite = self.L
- if direction == self.N:
- opposite = self.S
- elif direction == self.S:
- opposite = self.N
- elif direction == self.E:
- opposite = self.W
- elif direction == self.W:
- opposite = self.E
- elif direction == self.NW:
- opposite = self.SE
- elif direction == self.SE:
- opposite = self.NW
- elif direction == self.SW:
- opposite = self.NE
- elif direction == self.NE:
- opposite = self.SW
- return opposite
- def shouldPlacePeak(self,x,y):
- i = GetIndex(x,y)
- regionID = regMap.regionMap[i]
- if regionID == -1:
- return True #Plots without a region are always peaks
- region = regMap.getRegionByID(regionID)
- if region.isWater:
- return False #Water regions have no peaks
- #if neighbor in different region not peak, then return True
- for direction in range(1,9,1):
- xx,yy = self.getXYFromDirection(x,y,direction)
- ii = GetIndex(xx,yy)
- if ii == -1:
- return True #Land plots on map edge are peaks, water handled above
- if self.plotMap[ii] != self.PEAK:
- nRegionID = regMap.regionMap[ii]
- if nRegionID == -1:
- continue
- ## if nRegionID == region.gateRegion:
- nRegion = regMap.getRegionByID(nRegionID)
- if nRegion.isWater and region.altitude < 2:
- return False
- elif nRegion.isWater and region.altitude < 3 and \
- regMap.highestRegionAltitude >= 3:
- self.plotMap[i] = self.HILLS #Cheating sorta
- return True
- if nRegionID != regionID:
- return True
- return False
- def getXYFromDirection(self,x,y,direction):
- xx = x
- yy = y
- if direction == self.N:
- yy += 1
- elif direction == self.S:
- yy -= 1
- elif direction == self.E:
- xx += 1
- elif direction == self.W:
- xx -= 1
- elif direction == self.NW:
- yy += 1
- xx -= 1
- elif direction == self.NE:
- yy += 1
- xx += 1
- elif direction == self.SW:
- yy -= 1
- xx -= 1
- elif direction == self.SE:
- yy -= 1
- xx += 1
- return xx,yy
- def PrintPlotMap(self):
- print "Plot Map"
- for y in range(mapSize.MapHeight - 1,-1,-1):
- lineString = ""
- for x in range(mapSize.MapWidth):
- mapLoc = self.plotMap[GetIndex(x,y)]
- if mapLoc == self.OCEAN:
- lineString += "O"
- elif mapLoc == self.PEAK:
- lineString += "P"
- elif mapLoc == self.HILLS:
- lineString += "H"
- elif mapLoc == self.LAND:
- lineString += "L"
- print lineString
- lineString = " "
- print lineString
- plotMap = PlotMap()
- class TerrainMap :
- def __init__(self):
- return
- def createTerrainMap(self):
- self.L = 0
- self.N = 1
- self.S = 2
- self.E = 3
- self.W = 4
- self.NE = 5
- self.NW = 6
- self.SE = 7
- self.SW = 8
- self.DESERT = 0
- self.PLAINS = 1
- self.ICE = 2
- self.TUNDRA = 3
- self.GRASS = 4
- self.HILL = 5
- self.COAST = 6
- self.OCEAN = 7
- self.PEAK = 8
- self.MARSH = 9
- self.terrainMap = array('i')
- #initialize terrainMap with OCEAN
- for i in range(0,mapSize.MapHeight*mapSize.MapWidth):
- self.terrainMap.append(self.OCEAN)
- for y in range(mapSize.MapHeight):
- for x in range(mapSize.MapWidth):
- i = GetIndex(x,y)
- if plotMap.plotMap[i] != plotMap.OCEAN:
- self.terrainMap[i] = self.GRASS
- else:
- for direction in range(1,9,1):
- xx,yy = self.getXYFromDirection(x,y,direction)
- ii = GetIndex(xx,yy)
- if ii != -1 and plotMap.plotMap[ii] != plotMap.OCEAN:
- self.terrainMap[i] = self.COAST
- for y in range(mapSize.MapHeight):
- for x in range(mapSize.MapWidth):
- i = GetIndex(x,y)
- if plotMap.plotMap[i] != plotMap.OCEAN:
- rainFall = GetRainfall(x,y)
- if rainFall < mc.DesertThreshold:
- if rainFall < ((PRand.random()*mc.DesertThreshold)/2.0) + (mc.DesertThreshold/2.0):
- self.terrainMap[i] = self.DESERT
- else:
- self.terrainMap[i] = self.PLAINS
- elif rainFall < mc.PlainsThreshold:
- if rainFall < ((PRand.random() * (mc.PlainsThreshold - mc.DesertThreshold))/2.0) + mc.DesertThreshold + ((mc.PlainsThreshold - mc.DesertThreshold)/2.0):
- self.terrainMap[i] = self.PLAINS
- else:
- self.terrainMap[i] = self.GRASS
- else:
- self.terrainMap[i] = self.GRASS
- altitude = GetPlotAltitude(x,y)
- if altitude > mc.IceThreshold:
- self.terrainMap[i] = self.ICE
- elif altitude > mc.TundraThreshold:
- self.terrainMap[i] = self.TUNDRA
- elif altitude > mc.MaxDesertAltitude and self.terrainMap[i] == self.DESERT:
- self.terrainMap[i] = self.PLAINS
- def getXYFromDirection(self,x,y,direction):
- xx = x
- yy = y
- if direction == self.N:
- yy += 1
- elif direction == self.S:
- yy -= 1
- elif direction == self.E:
- xx += 1
- elif direction == self.W:
- xx -= 1
- elif direction == self.NW:
- yy += 1
- xx -= 1
- elif direction == self.NE:
- yy += 1
- xx += 1
- elif direction == self.SW:
- yy -= 1
- xx -= 1
- elif direction == self.SE:
- yy -= 1
- xx += 1
- return xx,yy
- terrainMap = TerrainMap()
- ##############################################################################
- ## Seed filler class
- ##############################################################################
- class Areamap :
- def __init__(self,width,height):
- self.mapWidth = width
- self.mapHeight = height
- self.areaMap = array('i')
- #initialize map with zeros
- for i in range(0,self.mapHeight*self.mapWidth):
- self.areaMap.append(0)
- return
- def findImpassableAreas(self):
- # self.areaSizes = array('i')
- ## starttime = time.clock()
- #make sure map is erased in case it is used multiple times
- for i in range(0,self.mapHeight*self.mapWidth):
- self.areaMap[i] = 0
- # for i in range(0,1):
- for i in range(0,self.mapHeight*self.mapWidth):
- if plotMap.plotMap[i] == plotMap.OCEAN: #not assigned to an area yet
- areaSize = self.fillArea(i,1)
- ## endtime = time.clock()
- ## elapsed = endtime - starttime
- ## print "defineAreas time ="
- ## print elapsed
- ## print
- return
- def findChokePointAreas(self):
- gc = CyGlobalContext()
- gameMap = CyMap()
- #fill water and peaks with non-zero value
- for i in range(0,self.mapHeight*self.mapWidth):
- gamePlot = gameMap.plotByIndex(i)
- if gamePlot.isWater():
- self.areaMap[i] = -1
- elif gamePlot.isImpassable():
- self.areaMap[i] = -3
- self.areaList = list()
- self.areaList.append(-1)#placeholder to avoid using a zero index
- areaID = 0
- for i in range(0,self.mapHeight*self.mapWidth):
- if self.areaMap[i] == 0:
- areaID += 1
- areaSize = self.fillArea(i,areaID)
- # print "areaID = %(id)d, size = %(s)d" % {"id":areaID,"s":areaSize}
- self.areaList.append(areaSize)
- def fillArea(self,index,areaID):
- #first divide index into x and y
- y = index/self.mapWidth
- x = index%self.mapWidth
- #We check 8 neigbors for land,but 4 for water. This is because
- #the game connects land squares diagonally across water, but
- #water squares are not passable diagonally across land
- self.segStack = list()
- self.size = 0
- #place seed on stack for both directions
- seg = LineSegment(y,x,x,1)
- self.segStack.append(seg)
- seg = LineSegment(y+1,x,x,-1)
- self.segStack.append(seg)
- while(len(self.segStack) > 0):
- seg = self.segStack.pop()
- self.scanAndFillLine(seg,areaID)
- return self.size
- def scanAndFillLine(self,seg,areaID):
- #check for y + dy being off map
- i = GetIndex(seg.xLeft,seg.y + seg.dy)
- if i < 0:
- ## print "scanLine off map ignoring",str(seg)
- return
- debugReport = False
- ## if (seg.y < 8 and seg.y > 4) or (seg.y < 70 and seg.y > 64):
- ## if (areaID == 4):
- ## debugReport = True
- #landOffset = 1 for 8 connected neighbors, 0 for 4 connected neighbors
- landOffset = 1
- lineFound = False
- #first scan and fill any left overhang
- if debugReport:
- print ""
- print str(seg)
- print "Going left"
- for xLeftExtreme in range(seg.xLeft - landOffset,-1 ,-1):
- i = GetIndex(xLeftExtreme,seg.y + seg.dy)
- if debugReport:
- print "xLeftExtreme = %(xl)4d" % {'xl':xLeftExtreme}
- if self.areaMap[i] == 0 and plotMap.plotMap[i] != plotMap.PEAK:
- self.areaMap[i] = areaID
- self.size += 1
- lineFound = True
- else:
- #if no line was found, then xLeftExtreme is fine, but if
- #a line was found going left, then we need to increment
- #xLeftExtreme to represent the inclusive end of the line
- if lineFound:
- xLeftExtreme += 1
- break
- if debugReport:
- print "xLeftExtreme finally = %(xl)4d" % {'xl':xLeftExtreme}
- print "Going Right"
- #now scan right to find extreme right, place each found segment on stack
- # xRightExtreme = seg.xLeft - landOffset #needed sometimes? one time it was not initialized before use.
- xRightExtreme = seg.xLeft #needed sometimes? one time it was not initialized before use.
- for xRightExtreme in range(seg.xLeft,self.mapWidth,1):
- if debugReport:
- print "xRightExtreme = %(xr)4d" % {'xr':xRightExtreme}
- i = GetIndex(xRightExtreme,seg.y + seg.dy)
- if self.areaMap[i] == 0 and plotMap.plotMap[i] != plotMap.PEAK:
- self.areaMap[i] = areaID
- self.size += 1
- if lineFound == False:
- lineFound = True
- xLeftExtreme = xRightExtreme #starting new line
- if debugReport:
- print "starting new line at xLeftExtreme= %(xl)4d" % {'xl':xLeftExtreme}
- elif lineFound == True: #found the right end of a line segment!
- lineFound = False
- #put same direction on stack
- newSeg = LineSegment(seg.y + seg.dy,xLeftExtreme,xRightExtreme - 1,seg.dy)
- self.segStack.append(newSeg)
- if debugReport:
- print "same direction to stack",str(newSeg)
- #determine if we must put reverse direction on stack
- if xLeftExtreme < seg.xLeft or xRightExtreme >= seg.xRight:
- #out of shadow so put reverse direction on stack also
- newSeg = LineSegment(seg.y + seg.dy,xLeftExtreme,xRightExtreme - 1,-seg.dy)
- self.segStack.append(newSeg)
- if debugReport:
- print "opposite direction to stack",str(newSeg)
- if xRightExtreme >= seg.xRight + landOffset:
- if debugReport:
- print "finished with line"
- break; #past the end of the parent line and this line ends
- elif lineFound == False and xRightExtreme >= seg.xRight + landOffset:
- if debugReport:
- print "no additional lines found"
- break; #past the end of the parent line and no line found
- else:
- continue #keep looking for more line segments
- if lineFound == True: #still a line needing to be put on stack
- if debugReport:
- print "still needing to stack some segs"
- lineFound = False
- #put same direction on stack
- newSeg = LineSegment(seg.y + seg.dy,xLeftExtreme,xRightExtreme - 1,seg.dy)
- self.segStack.append(newSeg)
- if debugReport:
- print str(newSeg)
- #determine if we must put reverse direction on stack
- if xLeftExtreme < seg.xLeft or xRightExtreme - 1 > seg.xRight:
- #out of shadow so put reverse direction on stack also
- newSeg = LineSegment(seg.y + seg.dy,xLeftExtreme,xRightExtreme - 1,-seg.dy)
- self.segStack.append(newSeg)
- if debugReport:
- print str(newSeg)
- return
- #for debugging
- def PrintAreaMap(self):
- print "Area Map"
- for y in range(self.mapHeight - 1,-1,-1):
- lineString = ""
- for x in range(self.mapWidth):
- mapLoc = self.areaMap[GetIndex(x,y)]
- if mapLoc > 0:
- if mapLoc + 34 > 127:
- mapLoc = 127 - 34
- lineString += chr(mapLoc + 34)
- ## if self.areaList[mapLoc] > ChokePointAreaSize:
- ## lineString += "*"
- ## else:
- ## lineString += "+"
- elif mapLoc == 0:
- lineString += "!"
- elif mapLoc == -1:
- lineString += "."
- elif mapLoc == -2:
- lineString += "X"
- elif mapLoc == -3:
- lineString += "^"
- lineString += "-" + str(y)
- print lineString
- lineString = " "
- print lineString
- return
- class LineSegment :
- def __init__(self,y,xLeft,xRight,dy):
- self.y = y
- self.xLeft = xLeft
- self.xRight = xRight
- self.dy = dy
- def __str__ (self):
- string = "y = %(y)3d, xLeft = %(xl)3d, xRight = %(xr)3d, dy = %(dy)2d" % \
- {'y':self.y,'xl':self.xLeft,'xr':self.xRight,'dy':self.dy}
- return string
- class StartRegion :
- def __init__(self,region):
- self.region = region
- self.differenceFromIdeal = -1.0
- class StartingPlotFinder :
- def __init__(self):
- return
- def initialize(self):
- self.availableRegionList = list()
- self.occupiedRegionList = list()
- def assignStartingPlots(self):
- gc = CyGlobalContext()
- gameMap = CyMap()
- #Shuffle players so the same player doesn't always get the first pick.
- playerList = list()
- for plrCheckLoop in range(gc.getMAX_CIV_PLAYERS()):
- if CyGlobalContext().getPlayer(plrCheckLoop).isEverAlive():
- playerList.append(plrCheckLoop)
- playerList = ShuffleList(playerList)
- for region in regMap.regionList:
- if not region.isWater:
- startRegion = StartRegion(region)
- self.availableRegionList.append(startRegion)
- civPreferenceList = GetCivPreferences()
- for playerIndex in playerList:
- player = gc.getPlayer(playerIndex)
- player.AI_updateFoundValues(True)
- civType = player.getCivilizationType()
- civInfo = gc.getCivilizationInfo(civType)
- print "Civ = %(c)s" % {"c":civInfo.getType()}
- civPref = self.getCivPreference(civPreferenceList,civType)
- bestRegion = self.getBestStartRegion(self.availableRegionList,self.occupiedRegionList,civPref)
- startPlot = self.getStartPlotInRegion(bestRegion.region,player,civPref)
- DeleteFromList(self.availableRegionList,bestRegion)
- self.occupiedRegionList.append(bestRegion)
- player.setStartingPlot(startPlot,True)
- return
- def getStartPlotInRegion(self,region,player,civPref):
- gc = CyGlobalContext()
- gameMap = CyMap()
- bestValue = 0
- bestPlot = None
- for plot in region.plotList:
- startPlot = gameMap.plot(plot.x,plot.y)
- if civPref.needCoastalStart and not isCoast(startPlot):
- continue
- if startPlot.isPeak() == True:
- continue
- value = startPlot.getFoundValue(player.getID())
- if value > bestValue:
- bestValue = value
- bestPlot = startPlot
- if bestPlot == None:
- raise ValueError, "best plot in region is null"
- return bestPlot
- def getBestStartRegion(self,availableRegionList,occupiedRegionList,civPref):
- bestRegionList = list()
- for startRegion in availableRegionList:
- #first make sure region has a water gateRegion if coastal start
- #is desired
- if civPref.needCoastalStart:
- gateRegion = regMap.getRegionByID(startRegion.region.gateRegion)
- if not gateRegion.isWater:
- continue
- if len(startRegion.region.plotList) < mc.MinRegionSizeStart:
- continue
- bestRegionList.append(startRegion)
- for startRegion in bestRegionList:
- normalizedAlt = startRegion.region.altitude/regMap.highestRegionAltitude
- altitudeDiff = abs(normalizedAlt - civPref.idealAltitude)
- moistureDiff = abs(startRegion.region.moisture - civPref.idealMoisture)
- maxDistance = GetDistance(0,0,mapSize.MapWidth - 1,mapSize.MapHeight - 1)
- distanceToNearest = self.getDistToNearestOccRegion(occupiedRegionList,startRegion)
- distanceFactor = 1.0 - (distanceToNearest/maxDistance)
- weightedAverageDiff = ((civPref.altitudeWeight * altitudeDiff) + (distanceFactor * civPref.distanceWeight) + moistureDiff)/(civPref.altitudeWeight + civPref.distanceWeight + 1)
- ## print "regionID = %(r)d, altitudeDiff= %(ad)f, moistureDiff= %(md)f, altitudeWeight= %(aw)f, weightedAverageDiff= %(wd)f" % \
- ## {"r":startRegion.region.ID,"ad":altitudeDiff,"md":moistureDiff,"aw":civPref.altitudeWeight,"wd":weightedAverageDiff}
- startRegion.differenceFromIdeal = weightedAverageDiff
- bestRegionList.sort(lambda x,y:cmp(x.differenceFromIdeal,y.differenceFromIdeal))
- startRegion = bestRegionList[0]
- print "chosen regionID = %(r)d" % {"r":startRegion.region.ID}
- return startRegion
- def getDistToNearestOccRegion(self,occupiedRegionList,startRegion):
- minDistance = GetDistance(0,0,mapSize.MapWidth - 1,mapSize.MapHeight - 1)
- for occRegion in occupiedRegionList:
- startGatePlot = startRegion.region.gatePlot
- if startGatePlot == None:
- continue
- occGatePlot = occRegion.region.gatePlot
- distance = GetDistance(startGatePlot.x,startGatePlot.y,occGatePlot.x,occGatePlot.y)
- minDistance = min(distance,minDistance)
- return minDistance
- def getCivPreference(self,civPreferenceList,civType):
- for civPref in civPreferenceList:
- if civPref.civ == civType:
- return civPref
- #None defined so let's make a generic one
- civPref = CivPreference(civType)
- return civPref
- def replaceUniqueImprovements(self):
- gc = CyGlobalContext()
- gameMap = CyMap()
- impPrefList = GetImprovementPreferences()
- availableRegionList = list()
- occupiedRegionList = list()
- for region in regMap.regionList:
- startRegion = StartRegion(region)
- availableRegionList.append(startRegion)
- for y in range(mapSize.MapHeight):
- for x in range(mapSize.MapWidth):
- plot = gameMap.plot(x,y)
- impType = plot.getImprovementType()
- impInfo = gc.getImprovementInfo(impType)
- if impInfo == None:
- continue
- print "Found %(i)s" % {"i":impInfo.getType()}
- impPref = None
- #Find impType in preference list
- for foundImpPref in impPrefList:
- if foundImpPref.improvement == impType:
- impPref = foundImpPref
- break
- if impPref == None:
- continue
- impInfo = gc.getImprovementInfo(impType)
- print "Removing %(i)s at %(x)d, %(y)d" % {"i":impInfo.getType(),"x":x,"y":y}
- plot.setImprovementType(ImprovementTypes.NO_IMPROVEMENT)
- ## numUnits = plot.getNumUnits()
- ## unitList = list()
- ## for n in range(numUnits):
- ## unit = plot.getUnit(n)
- ## unitList.append(unit)
- plot.setBonusType(BonusTypes.NO_BONUS)
- # FF: Changed by Jean Elcard 11/20/2008
- '''
- bestRegion = self.getBestImprovementRegion(availableRegionList,occupiedRegionList,impPref)
- DeleteFromList(availableRegionList,bestRegion)
- occupiedRegionList.append(bestRegion)
- bestPlot = self.getBestImpPlotInRegion(bestRegion.region,impPref)
- DeleteFromList(impPrefList,impPref)
- print "Adding %(i)s at %(x)d, %(y)d" % {"i":impInfo.getType(),"x":bestPlot.getX(),"y":bestPlot.getY()}
- bestPlot.setImprovementType(impType)
- '''
- if len(availableRegionList) > 0:
- bestRegion = self.getBestImprovementRegion(availableRegionList,occupiedRegionList,impPref)
- if bestRegion:
- # if not CyGame().isOption(GameOptionTypes.GAMEOPTION_ALL_UNIQUE_FEATURES):
- DeleteFromList(availableRegionList,bestRegion)
- occupiedRegionList.append(bestRegion)
- bestPlot = self.getBestImpPlotInRegion(bestRegion.region,impPref)
- DeleteFromList(impPrefList,impPref)
- print "Adding %(i)s at %(x)d, %(y)d" % {"i":impInfo.getType(),"x":bestPlot.getX(),"y":bestPlot.getY()}
- bestPlot.setImprovementType(impType)
- else: print "FF: No suitable region found for %(i)s." % {"i":impInfo.getType()}
- else: print "FF: Not enough regions to add %(i)s." % {"i":impInfo.getType()}
- # FF: End Change
- ## for n in range(numUnits):
- ## unit = unitList[n]
- ## unit.setXY(bestPlot.getX(),bestPlot.getY(),False,True,False)
- def getBestImprovementRegion(self,availableRegionList,occupiedRegionList,impPref):
- bestRegionList = list()
- for startRegion in availableRegionList:
- #first make sure region has a water gateRegion if coastal plot
- #is desired
- if impPref.needCoast:
- gateRegion = regMap.getRegionByID(startRegion.region.gateRegion)
- if not gateRegion.isWater:
- continue
- if impPref.needWater:
- if not startRegion.region.isWater:
- continue
- if startRegion.region.isWater:
- continue #water regions not supported right now
- if len(startRegion.region.plotList) < mc.MinRegionSizeTower:
- continue
- if impPref.needChoke:
- if self.findChokePoint(startRegion.region) == None:
- continue
- bestRegionList.append(startRegion)
- # FF: Added by Jean Elcard 11/20/2008
- if len(bestRegionList) == 0:
- return None
- # FF: End Add
- for startRegion in bestRegionList:
- normalizedAlt = startRegion.region.altitude/regMap.highestRegionAltitude
- altitudeDiff = abs(normalizedAlt - impPref.idealAltitude)
- moistureDiff = abs(startRegion.region.moisture - impPref.idealMoisture)
- maxDistance = GetDistance(0,0,mapSize.MapWidth - 1,mapSize.MapHeight - 1)
- distanceToNearest = self.getDistToNearestOccRegion(occupiedRegionList,startRegion)
- distanceFactor = 1.0 - (distanceToNearest/maxDistance)
- weightedAverageDiff = ((impPref.altitudeWeight * altitudeDiff) + distanceFactor + (moistureDiff * impPref.moistureWeight))/(impPref.altitudeWeight + impPref.moistureWeight + 1)
- print "regionID = %(r)d, altitudeDiff= %(ad)f, moistureDiff= %(md)f, altitudeWeight= %(aw)f, weightedAverageDiff= %(wd)f" % \
- {"r":startRegion.region.ID,"ad":altitudeDiff,"md":moistureDiff,"aw":impPref.altitudeWeight,"wd":weightedAverageDiff}
- startRegion.differenceFromIdeal = weightedAverageDiff
- bestRegionList.sort(lambda x,y:cmp(x.differenceFromIdeal,y.differenceFromIdeal))
- startRegion = bestRegionList[0]
- print "chosen regionID = %(r)d" % {"r":startRegion.region.ID}
- return startRegion
- def getBestImpPlotInRegion(self,region,impPref):
- gc = CyGlobalContext()
- gameMap = CyMap()
- midPoint = region.getCenter()
- ## print "midPoint.x= %(mx)d, midPoint.y= %(my)d" % {"mx":midPoint.x,"my":midPoint.y}
- minDistance = 100.0
- bestPlot = gameMap.plot(midPoint.x,midPoint.y)
- region.plotList = ShuffleList(region.plotList)
- for plot in region.plotList:
- i = GetIndex(plot.x,plot.y)
- gamePlot = gameMap.plot(plot.x,plot.y)
- print "gamePlot = %(x)d,%(y)d" % {"x":plot.x,"y":plot.y}
- if gamePlot.getBonusType(TeamTypes.NO_TEAM) != BonusTypes.NO_BONUS:
- continue
- # FF: Added by Jean Elcard 11/20/2008
- if gamePlot.getImprovementType() != ImprovementTypes.NO_IMPROVEMENT:
- continue
- # FF: End Add
- if gamePlot.isPeak() == True and impPref.needChoke == False:
- print "rejected for peak"
- continue
- if impPref.needHill and plotMap.plotMap[i] != plotMap.HILLS:
- print "rejected for not hill"
- continue
- if impPref.needFlat and plotMap.plotMap[i] != plotMap.LAND:
- print "rejected for not flat"
- continue
- if impPref.needCoast and not isCoast(gamePlot):
- continue
- if impPref.favoredTerrain != TerrainTypes.NO_TERRAIN \
- and gamePlot.getTerrainType() != impPref.favoredTerrain:
- print "rejected for not favored terrain"
- continue
- if impPref.needChoke:
- chokePlot = self.findChokePoint(region)
- if (plot.x >= chokePlot.getX() - 1 and plot.x <= chokePlot.getX() + 1 \
- and plot.y >= chokePlot.getY() - 1 and plot.y <= chokePlot.getY() + 1 \
- and gamePlot.isPeak()):
- print "Found choke"
- #place bait
- reagents = GetInfoType("BONUS_REAGENTS")
- if reagents != -1:
- for direction in range(1,9,1):
- xx,yy = plotMap.getXYFromDirection(plot.x,plot.y,direction)
- baitPlot = gameMap.plot(xx,yy)
- forest = mst.efForest
- if forest != -1 and baitPlot.getFeatureType() == forest:
- baitPlot.setFeatureType(FeatureTypes.NO_FEATURE,0)
- if baitPlot.canHaveBonus(reagents,True):
- baitPlot.setBonusType(reagents)
- break
- else:
- print "rejected not next to choke=%(x)d,%(y)d or not peak" % {"x":chokePlot.getX(),"y":chokePlot.getY()}
- continue
- bestPlot = gameMap.plot(plot.x,plot.y)
- break
- return bestPlot
- def collectAllWatchtowers(self):
- gc = CyGlobalContext()
- gameMap = CyMap()
- count = 0
- for y in range(mapSize.MapHeight):
- for x in range(mapSize.MapWidth):
- plot = gameMap.plot(x,y)
- impType = plot.getImprovementType()
- if impType == GetInfoType("IMPROVEMENT_TOWER"):
- count += 1
- plot.setImprovementType(ImprovementTypes.NO_IMPROVEMENT)
- print "razed %(t)d watchtowers" % {"t":count}
- return count
- def replaceWatchtowers(self,count):
- ## regMap.PrintRegionMap(False)
- gc = CyGlobalContext()
- gameMap = CyMap()
- towersPlacedAtChoke = 0
- towersPlacedInMiddle = 0
- self.createChokePointList()
- for region in regMap.regionList:
- if region.isWater:
- continue
- if len(region.plotList) < mc.MinRegionSizeTower:
- continue
- if PRand.randint(0,3) == 0:
- continue #not all regions should have a tower
- ## print "placing towers in region %(r)d" % {"r":region.ID}
- if PRand.randint(0,1) == 0:
- chokePoint = self.findChokePoint(region)
- badNeighbor = False
- if chokePoint != None:
- for direction in range(1,9,1):
- x,y = plotMap.getXYFromDirection(chokePoint.getX(),chokePoint.getY(),direction)
- nPlot = gameMap.plot(x,y)
- if nPlot.getImprovementType() != ImprovementTypes.NO_IMPROVEMENT:
- badNeighbor = True
- if chokePoint != None and not badNeighbor:
- chokePoint.setImprovementType(GetInfoType("IMPROVEMENT_TOWER"))
- towersPlacedAtChoke += 1
- continue #regions should not have a choke tower and mid tower or else they might appear together
- #If a chokepoint is not found or if mid tower is randomly selected,
- #place tower in the middle of a region
- midPoint = region.getCenter()
- ## print "midPoint.x= %(mx)d, midPoint.y= %(my)d" % {"mx":midPoint.x,"my":midPoint.y}
- minDistance = 100.0
- bestPlot = None
- for plot in region.plotList:
- i = GetIndex(plot.x,plot.y)
- gamePlot = gameMap.plot(plot.x,plot.y)
- if gamePlot.getBonusType(TeamTypes.NO_TEAM) != BonusTypes.NO_BONUS:
- continue
- if plotMap.plotMap[i] == plotMap.HILLS:
- distance = GetDistance(plot.x,plot.y,midPoint.x,midPoint.y)
- if minDistance > distance:
- bestPlot = plot
- minDistance = distance
- if bestPlot != None:
- midHill = gameMap.plot(bestPlot.x,bestPlot.y)
- midHill.setImprovementType(GetInfoType("IMPROVEMENT_TOWER"))
- towersPlacedInMiddle += 1
- print "towersPlacedAtChoke= %(c)d, towersPlacedInMiddle= %(m)d, total= %(t)d" % \
- {"c":towersPlacedAtChoke,"m":towersPlacedInMiddle,"t":towersPlacedAtChoke + towersPlacedInMiddle}
- def createChokePointList(self):
- gc = CyGlobalContext()
- gameMap = CyMap()
- areaMap = Areamap(mapSize.MapWidth,mapSize.MapHeight)
- possibleChokeList = list()
- likelyChokeList = list()
- self.chokePointList = list()
- chokeAreaList = list()
- #First compile a list of local chokepoints
- for y in range(mapSize.MapHeight):
- for x in range(mapSize.MapWidth):
- i = GetIndex(x,y)
- if self.isPossibleChokePoint(x,y):
- areaMap.areaMap[i] = -2
- possibleChokeList.append(ChokePoint(x,y))
- #Then eliminate chokes that don't connect significant areas
- areaMap.findChokePointAreas()
- for i in range(len(areaMap.areaList)):
- chokeAreaList.append(ChokeArea(i,areaMap.areaList[i]))
- for possibleChoke in possibleChokeList:
- self.findChokeNeighbors(possibleChoke,areaMap,chokeAreaList,possibleChokeList)
- for possibleChoke in possibleChokeList:
- for area in possibleChoke.neighborAreaList:
- if area.size > mc.ChokePointAreaSize:
- chokesCheckedList = list()
- ## print "Starting area search through %(p)s ----------------------------------------------------------" % \
- ## {"p":str(possibleChoke)}
- if self.canFindAdditionalAreaThroughChokes(possibleChoke,area,chokesCheckedList,True):
- likelyChokeList.append(possibleChoke)#upgrade!
- ## print "choke %(x)d,%(y)d is valid \n------------------------------------------------------\n" \
- ## % {"x":possibleChoke.x,"y":possibleChoke.y}
- ## else:
- ## print "choke %(x)d,%(y)d is NOT valid \n------------------------------------------------------\n" \
- ## % {"x":possibleChoke.x,"y":possibleChoke.y}
- break
- ## areaMap.PrintAreaMap()
- ## for chokePoint in likelyChokeList:
- ## print "Likely chokepoint at %(x)d, %(y)d" % {"x":chokePoint.x,"y":chokePoint.y}
- #Now you have a list of good chokepoints, but some areas may have so many
- #choke points that none of them are useful. Now we block the choke points
- #and test the walk-around distance to see if this choke point is useful
- for chokePoint in likelyChokeList:
- if self.isConfirmedChokePoint(chokePoint):
- print "Confirmed chokepoint at %(c)s" % {"c":str(chokePoint)}
- self.chokePointList.append(chokePoint)
- else:
- print "Rejected chokepoint at %(x)d, %(y)d" % {"x":chokePoint.x,"y":chokePoint.y}
- return
- def isConfirmedChokePoint(self,choke):
- gc = CyGlobalContext()
- gameMap = CyMap()
- gamePlot = gameMap.plot(choke.x,choke.y)
- #remember old plot type so we can replace
- oldPlotType = gamePlot.getPlotType()
- #change plot type to peak to block path
- gamePlot.setPlotType(PlotTypes.PLOT_PEAK,True,True)
- for inX,inY in choke.gateList:
- for outX,outY in choke.gateList:
- if outX == inX and outY == inY:
- continue
- gameMap.resetPathDistance()
- inPlot = gameMap.plot(inX,inY)
- outPlot = gameMap.plot(outX,outY)
- distance = gameMap.calculatePathDistance(inPlot,outPlot)
- ## print "distance from %(ix)d,%(iy)d to %(ox)d,%(oy)d = %(d)d" % \
- ## {"ix":inX,"iy":inY,"ox":outX,"oy":outY,"d":distance}
- if distance >= mc.ChokePointWalkAroundDistance or distance == -1:
- gamePlot.setPlotType(oldPlotType,True,True)
- return True
- gamePlot.setPlotType(oldPlotType,True,True)
- return False
- def canFindAdditionalAreaThroughChokes(self,possibleChoke,origionalArea,chokesCheckedList,bTopLayer):
- #First try to find a large area that is not the origional area
- twoAreasFound = False
- returnValue = False
- for area in possibleChoke.neighborAreaList:
- if bTopLayer == False and area == origionalArea:
- ## print "This secondary choke touches origional area and must be declared a dead end."
- return False
- elif area != origionalArea and area.size > mc.ChokePointAreaSize:
- twoAreasFound = True
- if twoAreasFound:
- ## print "Chokepoint %(c)s leads to second large area" % {"c":str(possibleChoke)}
- returnValue = True
- #These coordinates are checked and can not be checked again or else endless loop possible
- chokesCheckedList.append(possibleChoke)
- largeAreaFound = False
- #Now loop through neighbor choke points and recurse this function if they aren't
- #in checked list
- for neighborChoke in possibleChoke.neighborChokeList:
- alreadyChecked = False
- for checkedChoke in chokesCheckedList:
- if checkedChoke == neighborChoke:
- alreadyChecked = True
- if not alreadyChecked:
- ## print "possibleChoke(%(x)d,%(y)d) searching through %(n)s" % \
- ## {"x":possibleChoke.x,"y":possibleChoke.y,"n":str(neighborChoke)}
- largeAreaFound = self.canFindAdditionalAreaThroughChokes(neighborChoke,origionalArea,chokesCheckedList,False)
- if largeAreaFound == True:
- ## print "Found second area through neighbor chokepoint"
- if bTopLayer:
- possibleChoke.gateList.append((neighborChoke.x,neighborChoke.y))#for final path check
- returnValue = True
- #Now loop through small areas neighbor choke points
- for neighborArea in possibleChoke.neighborAreaList:
- if area != origionalArea:
- ## print "possibleChoke(%(x)d,%(y)d) searching through %(n)s" % \
- ## {"x":possibleChoke.x,"y":possibleChoke.y,"n":str(area)}
- for neighborChoke in neighborArea.neighborChokeList:
- alreadyChecked = False
- for checkedChoke in chokesCheckedList:
- if checkedChoke == neighborChoke:
- alreadyChecked = True
- if not alreadyChecked:
- ## print "possibleChoke(%(x)d,%(y)d) searching through %(n)s which is through area=%(a)d,%(c)s" % \
- ## {"x":possibleChoke.x,"y":possibleChoke.y,"n":str(neighborChoke),"a":area.ID,"c":chr(area.ID + 34)}
- largeAreaFound = self.canFindAdditionalAreaThroughChokes(neighborChoke,origionalArea,chokesCheckedList,False)
- if largeAreaFound == True:
- ## print "Found second area through neighbor area and chokepoint"
- if bTopLayer:
- possibleChoke.gateList.append((neighborChoke.x,neighborChoke.y))#for final path check
- returnValue = True
- ## if returnValue == False:
- ## print "no second area found through possibleChoke(%(x)d,%(y)d)" % \
- ## {"x":possibleChoke.x,"y":possibleChoke.y}
- return returnValue
- def findChokeNeighbors(self,possibleChoke,areaMap,chokeAreaList,possibleChokeList):
- for direction in range(1,9,1):
- xx,yy = plotMap.getXYFromDirection(possibleChoke.x,possibleChoke.y,direction)
- i = GetIndex(xx,yy)
- if i == -1:
- continue
- if areaMap.areaMap[i] == -2:
- for neighborChoke in possibleChokeList:
- if neighborChoke.x == xx and neighborChoke.y == yy:
- possibleChoke.neighborChokeList.append(neighborChoke)
- elif areaMap.areaMap[i] > 0:
- #make sure it's not in list already before adding it
- alreadyInList = False
- for area in possibleChoke.neighborAreaList:
- if area.ID == areaMap.areaMap[i]:
- alreadyInList = True
- if alreadyInList == False:
- #add area to neighbor list and also add this choke to areas neighbor list
- for area in chokeAreaList:
- if area.ID == areaMap.areaMap[i]:
- possibleChoke.neighborAreaList.append(area)
- area.neighborChokeList.append(possibleChoke)
- if area.size > mc.ChokePointAreaSize:
- possibleChoke.gateList.append((xx,yy))#gateList is for final path check
- return
- def isPossibleChokePoint(self,x,y):
- gc = CyGlobalContext()
- gameMap = CyMap()
- gamePlot = gameMap.plot(x,y)
- i = GetIndex(x,y)
- if gamePlot.isWater() or gamePlot.isImpassable():
- return False
- if gamePlot.getBonusType(TeamTypes.NO_TEAM) != BonusTypes.NO_BONUS:
- return False
- #First check cardinal directions
- direction = plotMap.W
- xx,yy = plotMap.getXYFromDirection(x,y,direction)
- passable = self.isPassableLand(xx,yy)
- oppDir = plotMap.getOppositeDirection(direction)
- xxx,yyy = plotMap.getXYFromDirection(x,y,oppDir)
- if passable == self.isPassableLand(xxx,yyy):
- direction = plotMap.N
- xx,yy = plotMap.getXYFromDirection(x,y,direction)
- oppDir = plotMap.getOppositeDirection(direction)
- xxx,yyy = plotMap.getXYFromDirection(x,y,oppDir)
- if passable != self.isPassableLand(xx,yy) and passable != self.isPassableLand(xxx,yyy):
- # print "choke at %(x)d,%(y)d is opposites" % {"x":x,"y":y}
- return True #Definately a possible choke
- #No choke yet, try diagonal chokes
- direction = plotMap.NW
- xx,yy = plotMap.getXYFromDirection(x,y,direction)
- if self.isPassableLand(xx,yy):
- direction = plotMap.N
- xx,yy = plotMap.getXYFromDirection(x,y,direction)
- direction = plotMap.W
- xxx,yyy = plotMap.getXYFromDirection(x,y,direction)
- if self.isPassableLand(xx,yy) == False and self.isPassableLand(xxx,yyy) == False:
- # print "choke at %(x)d,%(y)d is NW diagonal" % {"x":x,"y":y}
- return True #choke
- direction = plotMap.NE
- xx,yy = plotMap.getXYFromDirection(x,y,direction)
- if self.isPassableLand(xx,yy):
- direction = plotMap.N
- xx,yy = plotMap.getXYFromDirection(x,y,direction)
- direction = plotMap.E
- xxx,yyy = plotMap.getXYFromDirection(x,y,direction)
- if self.isPassableLand(xx,yy) == False and self.isPassableLand(xxx,yyy) == False:
- # print "choke at %(x)d,%(y)d is NE diagonal" % {"x":x,"y":y}
- return True #choke
- direction = plotMap.SW
- xx,yy = plotMap.getXYFromDirection(x,y,direction)
- if self.isPassableLand(xx,yy):
- direction = plotMap.S
- xx,yy = plotMap.getXYFromDirection(x,y,direction)
- direction = plotMap.W
- xxx,yyy = plotMap.getXYFromDirection(x,y,direction)
- if self.isPassableLand(xx,yy) == False and self.isPassableLand(xxx,yyy) == False:
- # print "choke at %(x)d,%(y)d is SW diagonal" % {"x":x,"y":y}
- return True #choke
- direction = plotMap.SE
- xx,yy = plotMap.getXYFromDirection(x,y,direction)
- if self.isPassableLand(xx,yy):
- direction = plotMap.S
- xx,yy = plotMap.getXYFromDirection(x,y,direction)
- direction = plotMap.E
- xxx,yyy = plotMap.getXYFromDirection(x,y,direction)
- if self.isPassableLand(xx,yy) == False and self.isPassableLand(xxx,yyy) == False:
- # print "choke at %(x)d,%(y)d is SE diagonal" % {"x":x,"y":y}
- return True #choke
- return False
- def isPassableLand(self,x,y):
- gc = CyGlobalContext()
- gameMap = CyMap()
- gamePlot = gameMap.plot(x,y)
- i = GetIndex(x,y)
- if i == -1:
- return False
- if gamePlot.isWater() or gamePlot.isImpassable():
- return False
- return True
- def findChokePoint(self,region):
- gc = CyGlobalContext()
- gameMap = CyMap()
- for choke in self.chokePointList:
- for plot in region.plotList:
- if plot.x == choke.x and plot.y == choke.y:
- return gameMap.plot(plot.x,plot.y)
- ## for plot in region.plotList:
- ## i = GetIndex(plot.x,plot.y)
- ## if plotMap.plotMap[i] == plotMap.PEAK:
- ## continue
- ## gamePlot = gameMap.plot(plot.x,plot.y)
- ## if gamePlot.getBonusType(TeamTypes.NO_TEAM) != BonusTypes.NO_BONUS:
- ## continue
- ## oppositePeaks = False
- ## for direction in range(1,5,1):
- ## xx,yy = plotMap.getXYFromDirection(plot.x,plot.y,direction)
- ## ii = GetIndex(xx,yy)
- ## if plotMap.plotMap[ii] == plotMap.PEAK:
- ## oppDir = plotMap.getOppositeDirection(direction)
- ## xxx,yyy = plotMap.getXYFromDirection(plot.x,plot.y,oppDir)
- ## iii = GetIndex(xxx,yyy)
- ## if plotMap.plotMap[iii] == plotMap.PEAK:
- ## oppositePeaks = True
- ##
- ## oppositePass = False
- ## for direction in range(1,5,1):
- ## xx,yy = plotMap.getXYFromDirection(plot.x,plot.y,direction)
- ## ii = GetIndex(xx,yy)
- ## if plotMap.plotMap[ii] != plotMap.PEAK:
- ## oppDir = plotMap.getOppositeDirection(direction)
- ## xxx,yyy = plotMap.getXYFromDirection(plot.x,plot.y,oppDir)
- ## iii = GetIndex(xxx,yyy)
- ## if plotMap.plotMap[iii] != plotMap.PEAK:
- ## oppositePass = True
- ## if oppositePeaks and oppositePass:
- ## chokePoint = gameMap.plot(plot.x,plot.y)
- ## if chokePoint.isRiverSide() == True:
- ## return chokePoint
- return None
- class ChokePoint :
- def __init__(self,x,y):
- self.x = x
- self.y = y
- self.neighborChokeList = list()
- self.neighborAreaList = list()
- self.gateList = list()
- return
- def __str__(self):
- rstring = "%(x)d,%(y)d \n" % {"x":self.x,"y":self.y}
- rstring += " neighborChokeList = \n"
- for nChoke in self.neighborChokeList:
- rstring += " %(x)d,%(y)d\n" % {"x":nChoke.x,"y":nChoke.y}
- rstring += " neighborAreaList = \n"
- for nArea in self.neighborAreaList:
- rstring +=" ID=%(id)d, char=%(c)s, size=%(s)d \n" % {"id":nArea.ID,"c":chr(nArea.ID + 34),"s":nArea.size}
- rstring += " gateList = \n"
- for x,y in self.gateList:
- rstring += " %(x)d,%(y)d\n" % {"x":x,"y":y}
- return rstring
- class ChokeArea :
- def __init__(self,ID,size):
- self.ID = ID
- self.size = size
- self.neighborChokeList = list()
- def __str__(self):
- rstring = "ID=%(id)d, char=%(c)s, size=%(s)d \n" % {"id":self.ID,"c":chr(self.ID + 34),"s":self.size}
- rstring += " neighborChokeList = \n"
- for nChoke in self.neighborChokeList:
- rstring += " %(x)d,%(y)d\n" % {"x":nChoke.x,"y":nChoke.y}
- return rstring
- spf = StartingPlotFinder()
- #######################################################################################
- ## Global Functions
- #######################################################################################
- #This function appends an item to a list only if it is not already
- #in the list
- def isCoast(plot):
- WaterArea = plot.waterArea()
- if not WaterArea.isNone():
- if not WaterArea.isLake():
- return True
- return False
- def AppendUnique(theList,newItem):
- if IsInList(theList,newItem) == False:
- theList.append(newItem)
- return
- def IsInList(theList,newItem):
- itemFound = False
- for item in theList:
- if item == newItem:
- itemFound = True
- break
- return itemFound
- def DeleteFromList(theList,oldItem):
- for n in range(len(theList)):
- if theList[n] == oldItem:
- del theList[n]
- break
- return
- def ShuffleList(theList):
- preshuffle = list()
- shuffled = list()
- numElements = len(theList)
- for i in range(numElements):
- preshuffle.append(theList[i])
- for i in range(numElements):
- n = PRand.randint(0,len(preshuffle)-1)
- shuffled.append(preshuffle[n])
- del preshuffle[n]
- return shuffled
- def GetInfoType(string):
- cgc = CyGlobalContext()
- return cgc.getInfoTypeForString(string)
- def GetPlotAltitude(x,y):
- #calculate highest region altitude if necessary and save it for later
- if regMap.highestRegionAltitude == 0:
- regMap.regionList.sort(lambda n,m: cmp(n.altitude,m.altitude))
- regMap.regionList.reverse()
- regMap.highestRegionAltitude = regMap.regionList[0].altitude
- i = GetIndex(x,y)
- regionID = regMap.regionMap[i]
- if regionID == -1:
- return -1.0
- region = regMap.getRegionByID(regionID)
- ## print "GetPlotAltitude"
- regionAlt = float(region.altitude + 1)/float(regMap.highestRegionAltitude + 1)
- ## print "regionAlt = %(ra)f" % {"ra":regionAlt}
- riverAltRange = mc.RiverAltRangeFactor * float(mc.RiverThreshold)
- riverSize = GetRiverSize(x,y)
- if riverSize > riverAltRange:
- riverSize = riverAltRange
- ## print "riverSize = %(r)f" % {"r":riverSize}
- riverSubtract = riverSize * ((mc.RiverAltitudeSubtraction/riverAltRange)/float(regMap.highestRegionAltitude + 1))
- ## print "riverSubtract = %(rs)f" % {"rs":riverSubtract}
- altitude = regionAlt - riverSubtract
- ## print "altitude = %(a)f" % {"a":altitude}
- ## print ""
- return altitude
- def GetRiverSize(x,y):
- riverAverage = 0.0
- for direction in range(5,9,1):
- rxX,rxY = riverMap.rxFromPlot(x,y,direction)
- rxI = riverMap.getRiverIndex(rxX,rxY)
- riverAverage += float(riverMap.riverMap[rxI])
- riverAverage = riverAverage/4.0
- return riverAverage
- def IsPlotTouchingRiver(x,y):
- for direction in range(5,9,1):
- rxX,rxY = riverMap.rxFromPlot(x,y,direction)
- rxI = riverMap.getRiverIndex(rxX,rxY)
- if riverMap.riverMap[rxI] > mc.RiverThreshold:
- return True
- return False
- def IsPlotSurroundedByOcean(x,y):
- for direction in range(1,9,1):
- xx,yy = regMap.getXYFromDirection(x,y,direction)
- i = GetIndex(xx,yy)
- if plotMap.plotMap[i] != plotMap.OCEAN:
- return False
- return True
- def SetClimateOptions():
- climate = CyMap().getClimate()
- if climate == GetInfoType("CLIMATE_ARID"):
- mc.JungleThreshold = .98
- mc.PlainsThreshold = .80
- mc.DesertThreshold = .70
- elif climate == GetInfoType("CLIMATE_TROPICAL"):
- mc.JungleThreshold = .50
- mc.PlainsThreshold = .35
- mc.DesertThreshold = .10
- mc.LeafyAltitude = .40
- elif climate == GetInfoType("CLIMATE_COLD"):
- mc.TundraThreshold = .35
- mc.IceThreshold = .55
- mc.MaxDesertAltitude = .25
- mc.LeafyAltitude = .20
- mc.EvergreenAltitude = .30
- def GetRainfall(x,y):
- rainfall = 0
- i = GetIndex(x,y)
- regionID = regMap.regionMap[i]
- if regionID != -1:
- region = regMap.getRegionByID(regionID)
- rainfall = region.moisture
- riverSize = GetRiverSize(x,y)
- riverSizeMax = float(mc.RiverThreshold) * mc.RiverAddsMoistureMax
- riverSize = min(riverSize,riverSizeMax)
- rainfall += (riverSize/riverSizeMax) * mc.RiverAddsMoistureRange
- return rainfall
- def GetDistance(x,y,dx,dy):
- distance = math.sqrt(abs((float(x - dx) * float(x - dx)) + (float(y - dy) * float(y - dy))))
- return distance
- ###############################################################################
- #functions that civ is looking for
- ###############################################################################
- '''
- # FF: Added by Jean Elcard 11/20/2008
- def getNumCustomMapOptions():
- return 3 + mst.iif( mst.bMars, 0, 1 )
- def getNumHiddenCustomMapOptions():
- """ Default is used for the last n custom-options in 'Play Now' mode. """
- return 2 + mst.iif( mst.bMars, 0, 1 )
- def getCustomMapOptionName(argsList):
- [iOption] = argsList
- option_names = {
- 0: "Shape",
- 1: "Peaks",
- 2: "Starts",
- 3: "Team Start"
- }
- translated_text = unicode(CyTranslator().getText(option_names[iOption], ()))
- return translated_text
- def getNumCustomMapOptionValues(argsList):
- [iOption] = argsList
- option_values = {
- 0: 3,
- 1: 11,
- 2: 2,
- 3: 3
- }
- return option_values[iOption]
- def getCustomMapOptionDescAt(argsList):
- [iOption, iSelection] = argsList
- selection_names = {
- 0: {
- 0: "Flat World (default)",
- 1: "Cylinder World (X Wrap)",
- 2: "Toroidal World (X and Y Wrap)"
- },
- 1: {
- 0: "No Softening (default)",
- 1: "10% less Peaks",
- 2: "20% less Peaks",
- 3: "30% less Peaks",
- 4: "40% less Peaks",
- 5: "50% less Peaks",
- 6: "60% less Peaks",
- 7: "70% less Peaks",
- 8: "80% less Peaks",
- 9: "90% less Peaks",
- 10: "No Peaks"
- },
- 2: {
- 0: "Use Erebus Starting Plot Finder (default)",
- 1: "Use Original Civilization IV Method"
- },
- 3: {
- 0: "Team Neighbors",
- 1: "Team Separated",
- 2: "Randomly Placed"
- }
- }
- translated_text = unicode(CyTranslator().getText(selection_names[iOption][iSelection], ()))
- return translated_text
- def getCustomMapOptionDefault(argsList):
- [iOption] = argsList
- option_defaults = {
- 0: 0,
- 1: 0,
- 2: 0,
- 3: 0
- }
- return option_defaults[iOption]
- def isRandomCustomMapOption(argsList):
- [iOption] = argsList
- option_random = {
- 0: True,
- 1: True,
- 2: False,
- 3: False
- }
- return option_random[iOption]
- # FF: End Add
- '''
- def generatePlotTypes():
- NiTextOut("Generating Plot Types ...")
- print "Adding Terrain"
- gc = CyGlobalContext()
- mmap = gc.getMap()
- mapSize.MapWidth = mmap.getGridWidth()
- mapSize.MapHeight = mmap.getGridHeight()
- PRand.seed()
- SetClimateOptions()
- print "MapWidth = %(mw)d,MapHeight = %(mh)d" % {"mw":mapSize.MapWidth,"mh":mapSize.MapHeight}
- plotTypes = [PlotTypes.PLOT_OCEAN] * (mapSize.MapWidth*mapSize.MapHeight)
- NumberOfPlayers = gc.getGame().countCivPlayersEverAlive()
- regMap.createRegions()
- riverMap.createRiverMap()
- plotMap.createPlotMap()
- for i in range(mapSize.MapWidth*mapSize.MapHeight):
- mapLoc = plotMap.plotMap[i]
- if mapLoc == plotMap.PEAK:
- plotTypes[i] = PlotTypes.PLOT_PEAK
- elif mapLoc == plotMap.HILLS:
- plotTypes[i] = PlotTypes.PLOT_HILLS
- elif mapLoc == plotMap.LAND:
- plotTypes[i] = PlotTypes.PLOT_LAND
- else:
- plotTypes[i] = PlotTypes.PLOT_OCEAN
- print "Finished generating plot types."
- return plotTypes
- def generateTerrainTypes():
- NiTextOut("Generating Terrain ...")
- print "--- generateTerrainTypes()"
- gc = CyGlobalContext()
- map = CyMap()
- terrainMap.createTerrainMap()
- ########## Temudjin START
- # Planetfall: more highlands
- mst.planetFallMap.buildPfallHighlands()
- # Prettify the map - change coastal peaks to hills with 30% chance; default: 66%
- mst.mapPrettifier.hillifyCoast( 30 )
- # Prettify map: Connect small islands
- # mst.mapPrettifier.bulkifyIslands()
- if mst.bPfall:
- # convert terrainMap into Planetfall terrainMap
- print "Latitude Borders: %r" % ( mst.getLatitudeBorders() )
- terrainTypes = [0]*(mapSize.MapWidth*mapSize.MapHeight)
- terrainList = [ 7, 6, 0, 1, 4, 9, 3, 2 ] # Ocean, Coast, Desert, Plains, Grass, Marsh, Tundra, Snow
- for i in range( CyMap().numPlots() ):
- terrainTypes[i] = mst.planetFallMap.mapPfallTerrain( terrainMap.terrainMap[i], terrainList, CyMap().plotByIndex(i) )
- print "Latitude Borders: %r" % ( mst.getLatitudeBorders() )
- elif mst.bMars:
- # There are two possible scenarios for 'Mars Now!':
- # either water is converted to desert or not
- iDesert = mst.iif( mst.bSandsOfMars, 16, 32 )
- terrainGen = mst.MST_TerrainGenerator_Mars( iDesert )
- terrainTypes = terrainGen.generateTerrain()
- else:
- ########## Temudjin END
- terrainTypes = [0]*(mapSize.MapWidth*mapSize.MapHeight)
- for i in range(mapSize.MapWidth*mapSize.MapHeight):
- if terrainMap.terrainMap[i] == terrainMap.OCEAN:
- terrainTypes[i] = mst.etOcean
- elif terrainMap.terrainMap[i] == terrainMap.COAST:
- terrainTypes[i] = mst.etCoast
- elif terrainMap.terrainMap[i] == terrainMap.DESERT:
- terrainTypes[i] = mst.etDesert
- elif terrainMap.terrainMap[i] == terrainMap.PLAINS:
- terrainTypes[i] = mst.etPlains
- elif terrainMap.terrainMap[i] == terrainMap.GRASS:
- terrainTypes[i] = mst.etGrass
- elif terrainMap.terrainMap[i] == terrainMap.TUNDRA:
- terrainTypes[i] = mst.etTundra
- elif terrainMap.terrainMap[i] == terrainMap.ICE:
- terrainTypes[i] = mst.etSnow
- elif terrainMap.terrainMap[i] == terrainMap.MARSH:
- terrainTypes[i] = mst.etMarsh
- print "Finished generating terrain types."
- print str(mst.etOcean)
- print str(mst.etCoast)
- print str(mst.etDesert)
- print str(mst.etPlains)
- print str(mst.etGrass)
- print str(mst.etTundra)
- print str(mst.etSnow)
- print str(mst.etMarsh)
- return terrainTypes
- '''
- def addRivers2():
- NiTextOut("Adding Rivers....")
- print "Adding Rivers"
- gc = CyGlobalContext()
- pmap = gc.getMap()
- for y in range(mapSize.MapHeight):
- for x in range(mapSize.MapWidth):
- placeRiversInPlot(x,y)
- def placeRiversInPlot(x,y):
- gc = CyGlobalContext()
- pmap = gc.getMap()
- plot = pmap.plot(x,y)
- #NE
- xx,yy = riverMap.rxFromPlot(x,y,riverMap.NE)
- ii = riverMap.getRiverIndex(xx,yy)
- if riverMap.riverMap[ii] > mc.RiverThreshold and riverMap.flowMap[ii] == riverMap.S:
- plot.setWOfRiver(True,CardinalDirectionTypes.CARDINALDIRECTION_SOUTH)
- #SW
- xx,yy = riverMap.rxFromPlot(x,y,riverMap.SW)
- ii = riverMap.getRiverIndex(xx,yy)
- if riverMap.riverMap[ii] > mc.RiverThreshold and riverMap.flowMap[ii] == riverMap.E:
- plot.setNOfRiver(True,CardinalDirectionTypes.CARDINALDIRECTION_EAST)
- #SE
- xx,yy = riverMap.rxFromPlot(x,y,riverMap.SE)
- ii = riverMap.getRiverIndex(xx,yy)
- if riverMap.riverMap[ii] > mc.RiverThreshold and riverMap.flowMap[ii] == riverMap.N:
- plot.setWOfRiver(True,CardinalDirectionTypes.CARDINALDIRECTION_NORTH)
- elif riverMap.riverMap[ii] > mc.RiverThreshold and riverMap.flowMap[ii] == riverMap.W:
- plot.setNOfRiver(True,CardinalDirectionTypes.CARDINALDIRECTION_WEST)
- '''
- def addFeatures2():
- NiTextOut("Generating Features ...")
- print "Adding Features"
- gc = CyGlobalContext()
- mmap = gc.getMap()
- FORESTLEAFY = 0
- FORESTEVERGREEN = 1
- FORESTSNOWY = 2
- #Now plant forest or jungle and place floodplains and oasis
- for y in range(mapSize.MapHeight):
- for x in range(mapSize.MapWidth):
- plot = mmap.plot(x,y)
- plotTerrain = plot.getTerrainType()
- #forest and jungle
- if not plot.isWater() and plotTerrain != mst.etDesert and not plot.isPeak():
- #Chance for trees based on rainfall
- rainfall = GetRainfall(x,y)
- if rainfall >= PRand.random():#Trees are present
- altitude = GetPlotAltitude(x,y)
- if plotTerrain == mst.etTundra or plotTerrain == mst.etSnow: #Safeguard for possibly modified tiles
- plot.setFeatureType(mst.efForest, FORESTSNOWY)
- elif altitude < mc.LeafyAltitude:
- if rainfall >= mc.JungleThreshold:
- if plot.isFlatlands() and PRand.random() < mc.ChanceForMarsh:
- plot.setTerrainType(mst.etMarsh,True,True)
- if PRand.random() >= mc.ChanceForOnlyMarsh:
- plot.setFeatureType(mst.efJungle,0)
- else:
- plot.setFeatureType(mst.efJungle,0)
- else:
- if altitude < mc.EvergreenAltitude:
- plot.setFeatureType(mst.efForest, FORESTLEAFY)
- elif altitude < mc.TundraThreshold:
- plot.setFeatureType(mst.efForest, FORESTEVERGREEN)
- else:
- plot.setFeatureType(mst.efForest, FORESTSNOWY)
- elif altitude < mc.EvergreenAltitude:
- plot.setFeatureType(mst.efForest, FORESTLEAFY)
- elif altitude < mc.TundraThreshold:
- plot.setFeatureType(mst.efForest, FORESTEVERGREEN)
- else:
- plot.setFeatureType(mst.efForest, FORESTSNOWY)
- #scrub
- if mst.bScrub and plotTerrain == mst.etDesert and not plot.isPeak() and not plot.isHills():
- rainfall = GetRainfall(x,y)
- randValue = PRand.random()
- if rainfall * 3.0 >= randValue:
- plot.setFeatureType(mst.efScrub, 0)
- ################Sat
- ### added ###23
- ### by Opera ###05
- ################09
- ## Kelp ; chance: 25% of spawning on Coasts
- if mst.bKelp != -1 and plot.isCoastalLand():
- randValue = PRand.randint(1,100)
- if randValue > 75:
- if plot.isWater():
- plot.setFeatureType(mst.efkelp, 0)
- ## Crystal Plains ; Chance function of surrounding tiles
- if mst.bCrystalPlains and plotTerrain == mst.etSnow and not plot.isPeak() and not plot.isHills():
- # Base chance;
- # equal to 25% if iTemp=1
- # equal to 12.5% if iTemp=2
- # equal to 8.33% if iTemp=3
- iChance = 25
- iTemp = 1
- if plot.isRiver() == True:
- iChance += 5 # Rivers increase base chance
- for xx in range(x-1,x+2):
- for yy in range(y-1,y+2): # Checks surrounding plots
- surPlot = mmap.plot(xx,yy)
- if surPlot.getTerrainType() == mst.etSnow or surPlot.getTerrainType() == mst.etTundra:
- if surPlot.isRiver(): # Surrounding plot river also increase chance
- iChance += 2
- if surPlot.getFeatureType() == mst.efCrystalPlains:
- iChance += 3
- else: # If neither Crystal Plains nor river but Snow or Tundra
- iChance += 1
- elif surPlot.getTerrainType() == mst.etDesert:
- # Desert increases iTemp and decreases chance
- iTemp = 3
- iChance -= 4
- elif surPlot.getTerrainType() != mst.etSnow:
- # Terrains that aren't Snow, Tundra or Desert
- iTemp = 2
- iChance -= 2
- # Here iTemp is used to reduce the chance of CP if the temperature is to high
- rand = PRand.randint(1,100) * iTemp
- if rand <= iChance:
- plot.setFeatureType(mst.efCrystalPlains,0)
- ## Haunted Lands ; mostly random (2%) but 33% if city ruins nearby
- if mst.bHauntedLands and not plot.isPeak() and not plot.isWater():
- if plot.getImprovementType() == mst.eiCityRuins:
- for xx in range(x-1,x+2):
- for yy in range(y-1,y+2):
- surPlot = mmap.plot(xx,yy)
- if surPlot.getFeatureType() != mst.efHauntedLands and not surPlot.isPeak() and not surPlot.isWater():
- if PRand.randint(1,100) <= 33:
- surPlot.setFeatureType(mst.efHauntedLands,0)
- plot.setFeatureType(mst.efHauntedLands,0)
- else:
- if PRand.randint(1,100) <= 2:
- plot.setFeatureType(mst.efHauntedLands,0)
- ################
- ### end of ###
- ### addition ###
- ################
- #floodplains and Oasis
- if plotTerrain == mst.etDesert and not plot.isHills() and not plot.isPeak() and not plot.isWater():
- if plot.isRiver() == True:
- plot.setFeatureType(mst.efFloodPlains, 0)
- else:
- #is this square surrounded by desert?
- foundNonDesert = False
- #print "trying to place oasis"
- for yy in range(y - 1,y + 2):
- for xx in range(x - 1,x + 2):
- surPlot = mmap.plot(xx,yy)
- if surPlot.getTerrainType() != mst.etDesert and not surPlot.isPeak():
- #print "non desert neighbor"
- foundNonDesert = True
- elif surPlot == 0:
- #print "neighbor off map"
- foundNonDesert = True
- elif surPlot.isWater() == True:
- #print "water neighbor"
- foundNonDesert = True
- elif surPlot.getFeatureType() == mst.efOasis:
- #print "oasis neighbor"
- foundNonDesert = True
- if foundNonDesert == False:
- if PRand.random() < mc.OasisChance:
- #print "placing oasis"
- plot.setFeatureType(mst.efOasis, 0)
- ########## Temudjin Start
- mst.featurePlacer.placeReefs()
- ########## Temudjin End
- return
- ##mapSize.MapWidth = 68
- ##mapSize.MapHeight = 68
- ##regMap.createRegions()
- ####regMap.PrintRegionMap(False)
- ####regMap.PrintRegionList()
- ####regMap.PrintRegionMap(True)
- ##riverMap.createRiverMap()
- ##riverMap.PrintFlowMap()
- ##plotMap.createPlotMap()
- ##plotMap.PrintPlotMap()
- ##regMap.PrintRegionRxMap(False)
- ##regMap.PrintRegionMap(True)
|