home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2006 January / Gamestar_80_2006-01_dvd.iso / Dema / Civilization4 / data1.cab / Civ4DemoComponent / Assets / Python / CvUtil.py < prev    next >
Encoding:
Python Source  |  2005-11-09  |  14.8 KB  |  405 lines

  1. ## Sid Meier's Civilization 4
  2. ## Copyright Firaxis Games 2005
  3. #
  4. # for error reporting
  5. import traceback
  6.  
  7. # for file ops
  8. import os
  9. import sys
  10.  
  11. # For Civ game code access
  12. from CvPythonExtensions import *
  13.  
  14. # For exception handling
  15. SHOWEXCEPTIONS = 1
  16.  
  17. # for C++ compatibility
  18. false=False
  19. true=True
  20.  
  21. # globals
  22. gc = CyGlobalContext()
  23. FontIconMap = {}
  24. localText = CyTranslator()
  25.  
  26. #
  27. # Popup context enums, values greater than 999 are reserved for events
  28. #
  29.  
  30. # DEBUG TOOLS
  31. PopupTypeEntityEventTest = 4
  32. PopupTypeEffectViewer = 5
  33.  
  34. # HELP SCREENS
  35. PopupTypeMilitaryAdvisor = 103
  36. PopupTypePlayerSelect = 104
  37.  
  38. # WORLD BUILDER
  39. PopupTypeWBContextStart = 200
  40. PopupTypeWBEditCity = PopupTypeWBContextStart 
  41. PopupTypeWBEditUnit = 201
  42. PopupTypeWBContextEnd    = 299
  43.  
  44. # EVENT ID VALUES (also used in popup contexts)
  45. EventEditCityName = 5000
  46. EventEditCity = 5001
  47. EventPlaceObject = 5002
  48. EventAwardTechsAndGold = 5003
  49. EventEditUnitName = 5006
  50. EventCityWarning = 5007
  51. EventWBAllPlotsPopup = 5008
  52. EventWBLandmarkPopup = 5009
  53. EventWBScriptPopup = 5010
  54. EventWBStartYearPopup = 5011
  55.  
  56. EventLButtonDown=1
  57. EventLcButtonDblClick=2
  58. EventRButtonDown=3
  59. EventBack=4
  60. EventForward=5
  61. EventKeyDown=6
  62. EventKeyUp=7
  63.  
  64. # List of unreported Events
  65. SilentEvents = [EventEditCityName, EventEditUnitName]
  66.  
  67. # Popup defines (TODO: Expose these from C++)
  68. FONT_CENTER_JUSTIFY=1<<2
  69. FONT_RIGHT_JUSTIFY=1<<1
  70. FONT_LEFT_JUSTIFY=1<<0
  71.  
  72. def convertToUnicode(s):
  73.     "if the string is non unicode, convert it to unicode by decoding it using 8859-1, latin_1"
  74.     if (isinstance(s, str)):
  75.         return s.decode("latin_1")
  76.     return s
  77.     
  78. def convertToStr(s):
  79.     "if the string is unicode, convert it to str by encoding it using 8859-1, latin_1"
  80.     if (isinstance(s, unicode)):
  81.         return s.encode("latin_1")
  82.     return s
  83.  
  84. class RedirectDebug:
  85.     """Send Debug Messages to Civ Engine"""
  86.     def __init__(self):
  87.         self.m_PythonMgr = CyPythonMgr()
  88.     def write(self, stuff):
  89.         # if str is non unicode and contains encoded unicode data, supply the right encoder to encode it into a unicode object
  90.         if (isinstance(stuff, unicode)):
  91.             self.m_PythonMgr.debugMsgWide(stuff)
  92.         else:
  93.             self.m_PythonMgr.debugMsg(stuff)
  94.         
  95. class RedirectError:
  96.     """Send Error Messages to Civ Engine"""
  97.     def __init__(self):
  98.         self.m_PythonMgr = CyPythonMgr()
  99.     def write(self, stuff):
  100.         # if str is non unicode and contains encoded unicode data, supply the right encoder to encode it into a unicode object
  101.         if (isinstance(stuff, unicode)):
  102.             self.m_PythonMgr.errorMsgWide(stuff)
  103.         else:
  104.             self.m_PythonMgr.errorMsg(stuff)
  105.  
  106. def myExceptHook(type, value, tb):
  107.     lines=traceback.format_exception(type, value, tb)
  108.     #pre= "---------------------Traceback lines-----------------------\n"
  109.     mid="\n".join(lines)
  110.     #post="-----------------------------------------------------------"
  111.     #total = pre+mid+post
  112.     total=mid
  113.     if SHOWEXCEPTIONS:
  114.         sys.stderr.write(total)
  115.     else:
  116.         sys.stdout.write(total)
  117.  
  118. def pyPrint(stuff):
  119.     stuff = 'PY:' + stuff + "\n"
  120.     sys.stdout.write(stuff)
  121.  
  122. def pyAssert(cond, msg):
  123.     if (cond==False):
  124.         sys.stderr.write(msg)
  125.     assert(cond, msg)
  126.     
  127. def getScoreComponent(iRawScore, iInitial, iMax, iFactor, bExponential, bFinal, bVictory):
  128.  
  129.     if gc.getGame().getEstimateEndTurn() == 0:
  130.         return 0
  131.  
  132.     if bFinal and bVictory:
  133.         fTurnRatio = float(gc.getGame().getGameTurn()) / float(gc.getGame().getEstimateEndTurn())
  134.         if bExponential and (iInitial != 0):
  135.             fRatio = iMax / iInitial
  136.             iMax = iInitial * pow(fRatio, fTurnRatio)
  137.         else:
  138.             iMax = iInitial + fTurnRatio * (iMax - iInitial)
  139.  
  140.     iFree = (gc.getDefineINT("SCORE_FREE_PERCENT") * iMax) / 100
  141.     if (iFree + iMax) != 0:
  142.         iScore = (iFactor * (iRawScore + iFree)) / (iFree + iMax)
  143.     else:
  144.         iScore = iFactor
  145.         
  146.     if bVictory:
  147.         iScore = ((100 + gc.getDefineINT("SCORE_VICTORY_PERCENT")) * iScore) / 100
  148.  
  149.     return int(iScore)
  150.     
  151. def getOppositeCardinalDirection(dir):
  152.     return (dir + 2) % CardinalDirectionTypes.NUM_CARDINALDIRECTION_TYPES
  153.  
  154. def shuffle(num, rand):
  155.     "returns a tuple of size num of shuffled numbers"    
  156.     piShuffle = [0]*num
  157.     shuffleList(num, rand, piShuffle)    # implemented in C for speed
  158.     return piShuffle
  159.  
  160. def spawnUnit(iUnit, pPlot, pPlayer):
  161.     pPlayer.initUnit(iUnit, pPlot.getX(), pPlot.getY(), UnitAITypes.NO_UNITAI)
  162.     return 1
  163.  
  164. def findInfoTypeNum(infoGetter, numInfos, typeStr):
  165.     if (typeStr == 'NONE'):
  166.         return -1
  167.     idx = gc.getInfoTypeForString(typeStr)
  168.     pyAssert(idx != -1, "Can't find type enum for type tag %s" %(typeStr,))
  169.     return idx
  170.  
  171. def getInfo(strInfoType, strInfoName):    # returns info for InfoType
  172.     #set Type to lowercase
  173.     strInfoType = strInfoType.lower()
  174.     strInfoName = strInfoName.capitalize()
  175.     
  176.     #get the appropriate dictionary item
  177.     infoDict = GlobalInfosMap.get(strInfoType)
  178.     #get the number of infos
  179.     numInfos = infoDict['NUM']()
  180.     #loop through each info
  181.     for i in range(numInfos):
  182.         loopInfo = infoDict['GET'](i)
  183.         
  184.         if loopInfo.getDescription() == strInfoName:
  185.             #and return the one requested
  186.             return loopInfo
  187.  
  188. def AdjustBuilding(add, all, BuildingIdx, pCity): # adds/removes buildings from a city
  189.     "Function for toggling buildings in cities"
  190.     if (BuildingIdx!= -1):  
  191.         if (all):                #Add/Remove ALL
  192.             for i in range(BuildingIdx):
  193.                 pCity.setHasRealBuildingIdx(i,add)
  194.         else:
  195.             pCity.setHasRealBuildingIdx(BuildingIdx,add)
  196.     return 0
  197.  
  198. def getIcon(iconEntry):                        # returns Font Icons
  199.     global FontIconMap
  200.     
  201.     iconEntry = iconEntry.lower()
  202.     if (FontIconMap.has_key(iconEntry)):
  203.         return     FontIconMap.get(iconEntry)
  204.     else:
  205.         return (u"%c" %(191,))
  206.  
  207. def combatDetailMessageBuilder(cdUnit, ePlayer, iChange):
  208.     if (cdUnit.iExtraCombatPercent != 0):
  209.         msg=localText.getText("TXT_KEY_COMBAT_MESSAGE_EXTRA_COMBAT_PERCENT",(cdUnit.iExtraCombatPercent * iChange,))
  210.         CyInterface().addCombatMessage(ePlayer,msg)
  211.  
  212.     if (cdUnit.iAnimalCombatModifierTA != 0):
  213.         msg=localText.getText("TXT_KEY_COMBAT_MESSAGE_ANIMAL_COMBAT",(cdUnit.iAnimalCombatModifierTA * iChange,))
  214.         CyInterface().addCombatMessage(ePlayer,msg)
  215.  
  216.     if (cdUnit.iAIAnimalCombatModifierTA != 0):
  217.         msg=localText.getText("TXT_KEY_COMBAT_MESSAGE_AI_ANIMAL_COMBAT",(cdUnit.iAIAnimalCombatModifierTA * iChange,))
  218.         CyInterface().addCombatMessage(ePlayer,msg)
  219.  
  220.     if (cdUnit.iAnimalCombatModifierAA != 0):
  221.         msg=localText.getText("TXT_KEY_COMBAT_MESSAGE_ANIMAL_COMBAT",(cdUnit.iAnimalCombatModifierAA * iChange,))
  222.         CyInterface().addCombatMessage(ePlayer,msg)
  223.  
  224.     if (cdUnit.iAIAnimalCombatModifierAA != 0):
  225.         msg=localText.getText("TXT_KEY_COMBAT_MESSAGE_AI_ANIMAL_COMBAT",(cdUnit.iAIAnimalCombatModifierAA * iChange,))
  226.         CyInterface().addCombatMessage(ePlayer,msg)
  227.  
  228.     if (cdUnit.iBarbarianCombatModifierTB != 0):
  229.         msg=localText.getText("TXT_KEY_COMBAT_MESSAGE_BARBARIAN_COMBAT",(cdUnit.iBarbarianCombatModifierTB * iChange,))
  230.         CyInterface().addCombatMessage(ePlayer,msg)
  231.         
  232.     if (cdUnit.iAIBarbarianCombatModifierTB != 0):
  233.         msg=localText.getText("TXT_KEY_COMBAT_MESSAGE_BARBARIAN_AI_COMBAT",(cdUnit.iAIBarbarianCombatModifierTB * iChange,))
  234.         CyInterface().addCombatMessage(ePlayer,msg)
  235.  
  236.     if (cdUnit.iBarbarianCombatModifierAB != 0):
  237.         msg=localText.getText("TXT_KEY_COMBAT_MESSAGE_BARBARIAN_COMBAT",(cdUnit.iBarbarianCombatModifierAB * iChange,))
  238.         CyInterface().addCombatMessage(ePlayer,msg)
  239.         
  240.     if (cdUnit.iAIBarbarianCombatModifierAB != 0):
  241.         msg=localText.getText("TXT_KEY_COMBAT_MESSAGE_BARBARIAN_AI_COMBAT",(cdUnit.iAIBarbarianCombatModifierAB * iChange,))
  242.         CyInterface().addCombatMessage(ePlayer,msg)
  243.  
  244.     if (cdUnit.iPlotDefenseModifier != 0):
  245.         msg=localText.getText("TXT_KEY_COMBAT_MESSAGE_PLOT_DEFENSE",(cdUnit.iPlotDefenseModifier * iChange,))
  246.         CyInterface().addCombatMessage(ePlayer,msg)
  247.  
  248.     if (cdUnit.iFortifyModifier != 0):
  249.         msg=localText.getText("TXT_KEY_COMBAT_MESSAGE_FORTIFY",(cdUnit.iFortifyModifier * iChange,))
  250.         CyInterface().addCombatMessage(ePlayer,msg)
  251.  
  252.     if (cdUnit.iCityDefenseModifier != 0):
  253.         msg=localText.getText("TXT_KEY_COMBAT_MESSAGE_CITY_DEFENSE",(cdUnit.iCityDefenseModifier * iChange,))
  254.         CyInterface().addCombatMessage(ePlayer,msg)
  255.         
  256.     if (cdUnit.iHillsDefenseModifier != 0):
  257.         msg=localText.getText("TXT_KEY_COMBAT_MESSAGE_HILLS",(cdUnit.iHillsDefenseModifier * iChange,))
  258.         CyInterface().addCombatMessage(ePlayer,msg)
  259.         
  260.     if (cdUnit.iFeatureDefenseModifier != 0):
  261.         msg=localText.getText("TXT_KEY_COMBAT_MESSAGE_FEATURE",(cdUnit.iFeatureDefenseModifier * iChange,))
  262.         CyInterface().addCombatMessage(ePlayer,msg)
  263.         
  264.     if (cdUnit.iTerrainDefenseModifier != 0):
  265.         msg=localText.getText("TXT_KEY_COMBAT_MESSAGE_TERRAIN",(cdUnit.iTerrainDefenseModifier * iChange,))
  266.         CyInterface().addCombatMessage(ePlayer,msg)
  267.  
  268.     if (cdUnit.iCityAttackModifier != 0):
  269.         msg=localText.getText("TXT_KEY_COMBAT_MESSAGE_CITY_ATTACK",(cdUnit.iCityAttackModifier * iChange,))
  270.         CyInterface().addCombatMessage(ePlayer,msg)
  271.  
  272.     if (cdUnit.iDomainDefenseModifier != 0):
  273.         msg=localText.getText("TXT_KEY_COMBAT_MESSAGE_CITY_DOMAIN_DEFENSE",(cdUnit.iDomainDefenseModifier * iChange,))
  274.         CyInterface().addCombatMessage(ePlayer,msg)
  275.  
  276.     if (cdUnit.iCityBarbarianDefenseModifier != 0):
  277.         msg=localText.getText("TXT_KEY_COMBAT_MESSAGE_CITY_BARBARIAN_DEFENSE",(cdUnit.iCityBarbarianDefenseModifier * iChange,))
  278.         CyInterface().addCombatMessage(ePlayer,msg)
  279.  
  280.     if (cdUnit.iClassDefenseModifier != 0):
  281.         msg=localText.getText("TXT_KEY_COMBAT_MESSAGE_CLASS_DEFENSE",(cdUnit.iClassDefenseModifier * iChange,))
  282.         CyInterface().addCombatMessage(ePlayer,msg)
  283.  
  284.     if (cdUnit.iClassAttackModifier != 0):
  285.         msg=localText.getText("TXT_KEY_COMBAT_MESSAGE_CLASS_ATTACK",(cdUnit.iClassAttackModifier * iChange,))
  286.         CyInterface().addCombatMessage(ePlayer,msg)
  287.  
  288.     if (cdUnit.iCombatModifierT != 0):
  289.         msg=localText.getText("TXT_KEY_COMBAT_MESSAGE_CLASS_COMBAT",(cdUnit.iCombatModifierT * iChange,))
  290.         CyInterface().addCombatMessage(ePlayer,msg)
  291.  
  292.     if (cdUnit.iCombatModifierA != 0):
  293.         msg=localText.getText("TXT_KEY_COMBAT_MESSAGE_CLASS_COMBAT",(cdUnit.iCombatModifierA * iChange,))
  294.         CyInterface().addCombatMessage(ePlayer,msg)
  295.  
  296.     if (cdUnit.iDomainModifierA != 0):
  297.         msg=localText.getText("TXT_KEY_COMBAT_MESSAGE_CLASS_DOMAIN",(cdUnit.iDomainModifierA * iChange,))
  298.         CyInterface().addCombatMessage(ePlayer,msg)
  299.  
  300.     if (cdUnit.iDomainModifierT != 0):
  301.         msg=localText.getText("TXT_KEY_COMBAT_MESSAGE_CLASS_DOMAIN",(cdUnit.iDomainModifierT * iChange,))
  302.         CyInterface().addCombatMessage(ePlayer,msg)
  303.  
  304.     if (cdUnit.iAnimalCombatModifierA != 0):
  305.         msg=localText.getText("TXT_KEY_COMBAT_MESSAGE_CLASS_ANIMAL_COMBAT",(cdUnit.iAnimalCombatModifierA * iChange,))
  306.         CyInterface().addCombatMessage(ePlayer,msg)
  307.  
  308.     if (cdUnit.iAnimalCombatModifierT != 0):
  309.         msg=localText.getText("TXT_KEY_COMBAT_MESSAGE_CLASS_ANIMAL_COMBAT",(cdUnit.iAnimalCombatModifierT * iChange,))
  310.         CyInterface().addCombatMessage(ePlayer,msg)
  311.  
  312.     if (cdUnit.iRiverAttackModifier != 0):
  313.         msg=localText.getText("TXT_KEY_COMBAT_MESSAGE_CLASS_RIVER_ATTACK",(cdUnit.iRiverAttackModifier * iChange,))
  314.         CyInterface().addCombatMessage(ePlayer,msg)
  315.  
  316.     if (cdUnit.iAmphibAttackModifier != 0):
  317.         msg=localText.getText("TXT_KEY_COMBAT_MESSAGE_CLASS_AMPHIB_ATTACK",(cdUnit.iAmphibAttackModifier * iChange,))
  318.         CyInterface().addCombatMessage(ePlayer,msg)
  319.  
  320. def combatMessageBuilder(cdAttacker, cdDefender):
  321.  
  322.     combatMessage = "%s's %s (%.2f)" %(gc.getPlayer(cdAttacker.eOwner).getName(),cdAttacker.sUnitName,cdAttacker.iCurrCombatStr/100.0,)
  323.     combatMessage += " " + localText.getText("TXT_KEY_COMBAT_MESSAGE_VS", ()) + " "
  324.     combatMessage += "%s's %s (%.2f)" %(gc.getPlayer(cdDefender.eOwner).getName(),cdDefender.sUnitName,cdDefender.iCurrCombatStr/100.0,)
  325.     CyInterface().addCombatMessage(cdAttacker.eOwner,combatMessage)
  326.     CyInterface().addCombatMessage(cdDefender.eOwner,combatMessage)
  327.     combatDetailMessageBuilder(cdAttacker,cdAttacker.eOwner,-1)
  328.     combatDetailMessageBuilder(cdDefender,cdAttacker.eOwner,1)
  329.     combatDetailMessageBuilder(cdAttacker,cdDefender.eOwner,-1)
  330.     combatDetailMessageBuilder(cdDefender,cdDefender.eOwner,1)
  331.     
  332. def initDynamicFontIcons():
  333.     global FontIconMap
  334.     
  335.     info = ""
  336.     desc = ""
  337.     # add Commerce Icons
  338.     for i in range(CommerceTypes.NUM_COMMERCE_TYPES):
  339.         info = gc.getCommerceInfo(i)
  340.         desc = info.getDescription().lower()
  341.         addIconToMap(info.getChar, desc)
  342.     # add Yield Icons
  343.     for i in range(YieldTypes.NUM_YIELD_TYPES):
  344.         info = gc.getYieldInfo(i)
  345.         desc = info.getDescription().lower()
  346.         addIconToMap(info.getChar, desc)
  347.     # add Religion & Holy City Icons
  348.     for i in range(gc.getNumReligionInfos()):
  349.         info = gc.getReligionInfo(i)
  350.         desc = info.getDescription().lower()
  351.         addIconToMap(info.getChar, desc)
  352.         addIconToMap(info.getHolyCityChar, desc)
  353.     for key in OtherFontIcons.keys():
  354.         #print key
  355.         FontIconMap[key] = (u"%c" % CyGame().getSymbolID(OtherFontIcons.get(key)))
  356.     
  357.     #print FontIconMap
  358.     
  359. def addIconToMap(infoChar, desc):
  360.     global FontIconMap
  361.     desc = convertToStr(desc)
  362.     print "%s - %s" %(infoChar(), desc)
  363.     uc = infoChar()
  364.     if (uc>=0):
  365.         FontIconMap[desc] = u"%c" %(uc,)
  366.  
  367. OtherFontIcons = { 'happy' : FontSymbols.HAPPY_CHAR,
  368.                 'unhappy' : FontSymbols.UNHAPPY_CHAR,
  369.                 'healthy' : FontSymbols.HEALTHY_CHAR,
  370.                 'unhealthy' : FontSymbols.UNHEALTHY_CHAR,
  371.                 'bullet' : FontSymbols.BULLET_CHAR,
  372.                 'strength' : FontSymbols.STRENGTH_CHAR,
  373.                 'moves' : FontSymbols.MOVES_CHAR,
  374.                 'religion' : FontSymbols.RELIGION_CHAR,
  375.                 'star' : FontSymbols.STAR_CHAR,
  376.                 'silver star' : FontSymbols.SILVER_STAR_CHAR,
  377.                 'trade' : FontSymbols.TRADE_CHAR,
  378.                 'defense' : FontSymbols.DEFENSE_CHAR,
  379.                 'greatpeople' : FontSymbols.GREAT_PEOPLE_CHAR,
  380.                 'badgold' : FontSymbols.BAD_GOLD_CHAR,
  381.                 'badfood' : FontSymbols.BAD_FOOD_CHAR,
  382.                 'eatenfood' : FontSymbols.EATEN_FOOD_CHAR,
  383.                 'goldenage' : FontSymbols.GOLDEN_AGE_CHAR,
  384.                 'angrypop' : FontSymbols.ANGRY_POP_CHAR,
  385.                 'openBorders' : FontSymbols.OPEN_BORDERS_CHAR,
  386.                 'defensivePact' : FontSymbols.DEFENSIVE_PACT_CHAR,
  387.                 'map' : FontSymbols.MAP_CHAR,
  388.                 'occupation' : FontSymbols.OCCUPATION_CHAR,
  389.                 'power' : FontSymbols.POWER_CHAR,
  390.                 }
  391.  
  392. GlobalInfosMap = {    'bonus': {'NUM': gc.getNumBonusInfos, 'GET': gc.getBonusInfo},
  393.                     'improvement': {'NUM': gc.getNumImprovementInfos, 'GET': gc.getImprovementInfo},
  394.                     'yield': {'NUM': YieldTypes.NUM_YIELD_TYPES, 'GET': gc.getYieldInfo},
  395.                     'religion': {'NUM': gc.getNumReligionInfos, 'GET': gc.getReligionInfo},
  396.                     'tech': {'NUM': gc.getNumTechInfos, 'GET': gc.getTechInfo},
  397.                     'unit': {'NUM': gc.getNumUnitInfos, 'GET': gc.getUnitInfo},
  398.                     'civic': {'NUM': gc.getNumCivicInfos, 'GET': gc.getCivicInfo},
  399.                     'building': {'NUM': gc.getNumBuildingInfos, 'GET': gc.getBuildingInfo},
  400.                     'terrain': {'NUM': gc.getNumTerrainInfos, 'GET': gc.getTerrainInfo},
  401.                     'trait': {'NUM': gc.getNumTraitInfos, 'GET': gc.getTraitInfo},
  402.                     'feature' : {'NUM': gc.getNumFeatureInfos, 'GET': gc.getFeatureInfo},
  403.                     'route': {'NUM': gc.getNumRouteInfos, 'GET': gc.getRouteInfo},
  404.                     'promotion': {'NUM':gc.getNumPromotionInfos, 'GET': gc.getPromotionInfo},
  405.                 }