Advertisement
Guest User

Untitled

a guest
Sep 1st, 2014
204
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 27.73 KB | None | 0 0
  1. ## TradeUtil
  2. ##
  3. ## Utilities for dealing with Trades and TradeData.
  4. ##
  5. ## Trading Partners
  6. ##
  7. ##   canTrade(playerOrID, withPlayerOrID)
  8. ##     Returns True if <player> can open the trade window with <withPlayer>.
  9. ##
  10. ##   getTechTradePartners(playerOrID)
  11. ##     Returns a list of CyPlayers that can trade technologies with <player>.
  12. ##
  13. ##   getBonusTradePartners(playerOrID)
  14. ##     Returns a list of CyPlayers that can trade bonuses with <player>.
  15. ##
  16. ##   getGoldTradePartners(playerOrID)
  17. ##     Returns a list of CyPlayers that can trade gold with <player>.
  18. ##
  19. ##   getMapTradePartners(playerOrID)
  20. ##     Returns a list of CyPlayers that can trade maps with <player>.
  21. ##
  22. ##
  23. ##   getOpenBordersTradePartners(playerOrID)
  24. ##     Returns a list of CyPlayers that can sign an Open Borders agreement with <player>.
  25. ##
  26. ##   getDefensivePactTradePartners(playerOrID)
  27. ##     Returns a list of CyPlayers that can sign a Defensive Pact with <player>.
  28. ##
  29. ##   getPermanentAllianceTradePartners(playerOrID)
  30. ##     Returns a list of CyPlayers that can sign a Permanent Alliance with <player>.
  31. ##
  32. ##
  33. ##   getPeaceTradePartners(playerOrID)
  34. ##     Returns a list of CyPlayers that can sign a peace treaty with <player>.
  35. ##
  36. ##   getVassalTradePartners(playerOrID)
  37. ##     Returns a list of CyPlayers that can become a vassal of <player>.
  38. ##
  39. ##   getCapitulationTradePartners(playerOrID)
  40. ##     Returns a list of CyPlayers that can capitulate to <player>.
  41. ##
  42. ##
  43. ##   tradeParters(playerOrID)
  44. ##     Iterates over all of <player>'s possible trade partners, yielding each CyPlayer in turn.
  45. ##
  46. ##   getTradePartnersByPlayer(playerOrID, testFunction, args...)
  47. ##     Returns a list of CyPlayers that can trade with <player>.
  48. ##
  49. ##   getTradePartnersByTeam(playerOrID, testFunction, args...)
  50. ##     Returns a list of CyPlayers that can trade with <player>.
  51. ##
  52. ## Trade Items
  53. ##
  54. ##   getDesiredBonuses(playerOrID)
  55. ##     Returns a set of bonus IDs that <player> can receive in trade.
  56. ##
  57. ##   getCorporationBonuses(playerOrID)
  58. ##     Returns the set of bonus IDs that <player> can receive due to their corporations.
  59. ##
  60. ##   getSurplusBonuses(playerOrID, minimum=1
  61. ##     Returns a list of bonus IDs of which <player> has at least <minimum>.
  62. ##
  63. ##   getTradeableBonuses(fromPlayerOrID, toPlayerOrID)
  64. ##     Returns two sets of bonus IDs that <fromPlayer> will and won't trade to <toPlayer>.
  65. ##
  66. ## Trade Routes
  67. ##
  68. ##   isFractionalTrade()
  69. ##     Returns True of BULL is active with Fractional Trade Routes.
  70. ##
  71. ##   getTradeProfitFunc()
  72. ##     Returns the CyCity function to use to calculate the trade route profit for a single route.
  73. ##
  74. ##   calculateTradeRouteYield(city, route, yieldType)
  75. ##     Returns the total <yieldType> for the <route>th trade route in <city>.
  76. ##
  77. ##   calculateTotalTradeRouteYield(city, yieldType)
  78. ##     Returns the total <yieldType> for all trade routes in <city>.
  79. ##
  80. ##   calculateTradeRoutes(playerOrID, withPlayerOrID=None)
  81. ##     Returns the domestic and foreign trade route yields and counts for <playerOrID>:
  82. ##     domestic yield, domestic count, foreign yield, and foreign count.
  83. ##     If <withPlayerOrID> is given, only counts trade routes to their cities.
  84. ##
  85. ## TradeData
  86. ##
  87. ##   format(player or ID, TradeData(s))
  88. ##     Returns a plain text description of the given tradeable item(s).
  89. ##
  90. ##   Trade(ePlayer, eOtherPlayer)
  91. ##     Can be used to create new trades.
  92. ##     (not really since implementDeal() not exposed to Python)
  93. ##
  94. ## Notes
  95. ##   - Must be initialized externally by calling init()
  96. ##
  97. ## Copyright (c) 2008 The BUG Mod.
  98. ##
  99. ## Author: EmperorFool
  100.  
  101. from CvPythonExtensions import *
  102. import BugUtil
  103. import DiplomacyUtil
  104. import GameUtil
  105. import PlayerUtil
  106.  
  107. # BUG - Mac Support - start
  108. BugUtil.fixSets(globals())
  109. # BUG - Mac Support - end
  110.  
  111. gc = CyGlobalContext()
  112.  
  113. CORP_BONUSES = {}
  114.  
  115. DOMESTIC_TRADE = 0
  116. DOMESTIC_OVERSEAS_TRADE = 1
  117. FOREIGN_TRADE = 2
  118. FOREIGN_OVERSEAS_TRADE = 3
  119.  
  120. MAX_TRADE_ROUTES = gc.getDefineINT("MAX_TRADE_ROUTES")
  121. FRACTIONAL_TRADE = False
  122. TRADE_PROFIT_FUNC = None
  123.  
  124. TRADE_FORMATS = {}
  125.  
  126.  
  127. ## Trading Partners
  128.  
  129. def canTrade(playerOrID, withPlayerOrID):
  130.     """
  131.     Returns True if <player> can open the trade window with <withPlayer>.
  132.     """
  133.     return DiplomacyUtil.canContact(playerOrID, withPlayerOrID) and DiplomacyUtil.isWillingToTalk(withPlayerOrID, playerOrID)
  134.  
  135. def getTechTradePartners(playerOrID):
  136.     """
  137.     Returns a list of CyPlayers that can trade technologies with <player>.
  138.     """
  139.     if not GameUtil.isTechTrading():
  140.         return ()
  141.     return getTradePartnersByTeam(playerOrID, lambda fromTeam, toTeam: fromTeam.isTechTrading() or toTeam.isTechTrading())
  142.  
  143. def getBonusTradePartners(playerOrID):
  144.     """
  145.     Returns a list of CyPlayers that can trade bonuses with <player>.
  146.     """
  147.     return getTradePartnersByPlayer(playerOrID, lambda fromPlayer, toPlayer: fromPlayer.canTradeNetworkWith(toPlayer.getID()))
  148.  
  149. def getGoldTradePartners(playerOrID):
  150.     """
  151.     Returns a list of CyPlayers that can trade gold with <player>.
  152.     """
  153.     return getTradePartnersByTeam(playerOrID, lambda fromTeam, toTeam: fromTeam.isGoldTrading() or toTeam.isGoldTrading())
  154.  
  155. def getMapTradePartners(playerOrID):
  156.     """
  157.     Returns a list of CyPlayers that can trade maps with <player>.
  158.     """
  159.     return getTradePartnersByTeam(playerOrID, lambda fromTeam, toTeam: fromTeam.isMapTrading() or toTeam.isMapTrading())
  160.  
  161. def getOpenBordersTradePartners(playerOrID):
  162.     """
  163.     Returns a list of CyPlayers that can sign an Open Borders agreement with <player>.
  164.     """
  165.     return getTradePartnersByTeam(playerOrID, canSignOpenBorders)
  166.  
  167. def canSignOpenBorders(fromTeam, toTeam):
  168.     """
  169.     Returns True if the two CyTeams can sign an Open Borders agreement.
  170.     """
  171.     if fromTeam.isOpenBorders(toTeam.getID()) or toTeam.isOpenBorders(fromTeam.getID()):
  172.         return False
  173.     return fromTeam.isOpenBordersTrading() or toTeam.isOpenBordersTrading()
  174. #Afforess Advanced Diplomacy
  175. def getLimitedBordersTradePartners(playerOrID):
  176.     """
  177.     Returns a list of CyPlayers that can sign an Limited Borders agreement with <player>.
  178.     """
  179.     return getTradePartnersByTeam(playerOrID, canSignLimitedBorders)
  180.  
  181. def canSignLimitedBorders(fromTeam, toTeam):
  182.     """
  183.     Returns True if the two CyTeams can sign an Limited Borders agreement.
  184.     Limited Borders are enabled when Open Borders are, so the functions are identical.
  185.     """
  186.     if fromTeam.isOpenBorders(toTeam.getID()) or toTeam.isOpenBorders(fromTeam.getID()):
  187.         return False
  188.     if not (gc.getGame().isOption(GameOptionTypes.GAMEOPTION_ADVANCED_DIPLOMACY)):
  189.         return False
  190.     return fromTeam.isOpenBordersTrading() or toTeam.isOpenBordersTrading()
  191.  
  192. def getEmbassyTradePartners(playerOrID):
  193.     """
  194.     Returns a list of CyPlayers that can sign an Limited Borders agreement with <player>.
  195.     """
  196.     return getTradePartnersByTeam(playerOrID, canTradeEmbassy)
  197.  
  198. def canTradeEmbassy(fromTeam, toTeam):
  199.     """
  200.     Returns True if the two CyTeams can trade for an Embassy.
  201.     Embassies are enabled when Open Borders are, so the functions are identical.
  202.     """
  203.     if fromTeam.isOpenBorders(toTeam.getID()) or toTeam.isOpenBorders(fromTeam.getID()):
  204.         return False
  205.     if not (gc.getGame().isOption(GameOptionTypes.GAMEOPTION_ADVANCED_DIPLOMACY)):
  206.         return False
  207.     return fromTeam.isOpenBordersTrading() or toTeam.isOpenBordersTrading()
  208.  
  209. #Afforess End
  210. def getDefensivePactTradePartners(playerOrID):
  211.     """
  212.     Returns a list of CyPlayers that can sign a Defensive Pact with <player>.
  213.     """
  214.     return getTradePartnersByTeam(playerOrID, canSignDefensivePact)
  215.  
  216. def canSignDefensivePact(fromTeam, toTeam):
  217.     """
  218.     Returns True if the two CyTeams can sign a Defensive Pact.
  219.     """
  220.     if fromTeam.isDefensivePact(toTeam.getID()) or toTeam.isDefensivePact(fromTeam.getID()):
  221.         return False
  222.     return fromTeam.isDefensivePactTrading() or toTeam.isDefensivePactTrading()
  223.  
  224. def getPermanentAllianceTradePartners(playerOrID):
  225.     """
  226.     Returns a list of CyPlayers that can sign a Permanent Alliance with <player>.
  227.     """
  228.     return getTradePartnersByTeam(playerOrID, canSignPermanentAlliance)
  229.  
  230. def canSignPermanentAlliance(fromTeam, toTeam):
  231.     """
  232.     Returns True if the two CyTeams can sign a Permanent Alliance.
  233.     """
  234.     if fromTeam.getID() == toTeam.getID():
  235.         return False
  236.     return fromTeam.isPermanentAllianceTrading() or toTeam.isPermanentAllianceTrading()
  237.  
  238. def getPeaceTradePartners(playerOrID):
  239.     """
  240.     Returns a list of CyPlayers that can sign a peace treaty with <player>.
  241.     """
  242.     return getTradePartnersByTeam(playerOrID, lambda fromTeam, toTeam: toTeam.isAtWar(fromTeam.getID()))
  243.  
  244. def getVassalTradePartners(playerOrID):
  245.     """
  246.     Returns a list of CyPlayers that can become a vassal of <player>.
  247.     """
  248.     return getTradePartnersByTeam(playerOrID, canAcceptVassal, False)
  249.  
  250. def getCapitulationTradePartners(playerOrID):
  251.     """
  252.     Returns a list of CyPlayers that can capitulate to <player>.
  253.     """
  254.     return getTradePartnersByTeam(playerOrID, canAcceptVassal, True)
  255.  
  256. def canAcceptVassal(masterTeam, vassalTeam, bAtWar):
  257.     """
  258.     Returns True if <vassalTeam> can become a vassal of <masterTeam>.
  259.    
  260.     Pass True for <bAtWar> to test for capitulation and False to test for peaceful vassalage.
  261.     """
  262.     if masterTeam.getID() == vassalTeam.getID():
  263.         return False
  264.     if masterTeam.isAVassal() or vassalTeam.isAVassal():
  265.         return False
  266.     if masterTeam.isAtWar(vassalTeam.getID()) != bAtWar:
  267.         return False
  268.     # master must possess tech
  269.     return masterTeam.isVassalStateTrading()
  270.    
  271. #RevolutionDCM start - extra civlerts
  272. def getWarTraders(playerOrID):
  273.     """
  274.     Returns a list of CyPlayers that can trade for war <player>.
  275.     """
  276.     return getTradePartnersByTeam(playerOrID, canWarTrade)
  277.  
  278. def canWarTrade(fromTeam, toTeam):
  279.     """
  280.     Returns True if the two CyTeams can trade for war
  281.     """
  282.     if fromTeam.getID() == toTeam.getID():
  283.         return False
  284.     if fromTeam.isAVassal() or toTeam.isAVassal():
  285.         return False
  286.     if fromTeam.isAtWar(toTeam.getID()): # being at war means NO_DENIAL warTrade
  287.         return False
  288.     return True
  289. #RevolutionDCM end 
  290.  
  291. def tradeParters(playerOrID):
  292.     """
  293.     Iterates over all of <player>'s possible trade partners, yielding each CyPlayer in turn.
  294.     """
  295.     player = PlayerUtil.getPlayer(playerOrID)
  296.     for partner in PlayerUtil.players(alive=True, barbarian=False, minor=False):
  297.         if canTrade(player, partner):
  298.             yield partner
  299.  
  300. def getTradePartnersByPlayer(playerOrID, testFunction, *args):
  301.     """
  302.     Returns a list of CyPlayers that can trade with <player>.
  303.    
  304.     <testFunction> is passed two CyPlayers plus <args> for each viable pairing and should return a boolean value.
  305.     """
  306.     player = PlayerUtil.getPlayer(playerOrID)
  307.     partners = []
  308.     for partner in tradeParters(player):
  309.         if testFunction(player, partner, *args):
  310.             partners.append(partner)
  311.     return partners
  312.  
  313. def getTradePartnersByTeam(playerOrID, testFunction, *args):
  314.     """
  315.     Returns a list of CyPlayers that can trade with <player>.
  316.    
  317.     <testFunction> is passed two CyTeams plus <args> for each viable pairing and should return a boolean value.
  318.     """
  319.     player = PlayerUtil.getPlayer(playerOrID)
  320.     team = PlayerUtil.getTeam(player.getTeam())
  321.     partners = []
  322.     for partner in tradeParters(player):
  323.         if testFunction(team, PlayerUtil.getTeam(partner.getTeam()), *args):
  324.             partners.append(partner)
  325.     return partners
  326.  
  327.  
  328. ## Trade Items
  329.  
  330. def getDesiredBonuses(playerOrID):
  331.     """
  332.     Returns a set of bonus IDs that <player> can receive in trade.
  333.     """
  334.     player, team = PlayerUtil.getPlayerAndTeam(playerOrID)
  335.     bonuses = set()
  336.     for eBonus in range(gc.getNumBonusInfos()):
  337.         if player.getNumAvailableBonuses(eBonus) == 0:
  338.             eObsoleteTech = gc.getBonusInfo(eBonus).getTechObsolete()
  339.             if eObsoleteTech == -1 or not team.isHasTech(eObsoleteTech):
  340.                 bonuses.add(eBonus)
  341.     return bonuses | getCorporationBonuses(player)
  342.  
  343. def getCorporationBonuses(playerOrID):
  344.     """
  345.     Returns the set of bonus IDs that <player> can receive due to their corporations.
  346.    
  347.     Takes into account anything (e.g. civics) that alters <player>'s ability to run corporations.
  348.     """
  349.     player = PlayerUtil.getPlayer(playerOrID)
  350.     bonuses = set()
  351.     for eCorp, inputs in CORP_BONUSES.iteritems():
  352.         if player.getHasCorporationCount(eCorp) > 0:
  353.             bonuses |= inputs
  354.     return bonuses
  355.  
  356. def initCorporationBonuses():
  357.     """
  358.     Initializes the CORP_BONUSES dictionary that maps each corporation ID to the set of bonus IDs it uses.
  359.     """
  360.     for eCorp in range(gc.getNumCorporationInfos()):
  361.         corp = gc.getCorporationInfo(eCorp)
  362.         bonuses = set()
  363.         for i in range(gc.getNUM_CORPORATION_PREREQ_BONUSES()):
  364.             eBonus = corp.getPrereqBonus(i)
  365.             if eBonus != -1:
  366.                 bonuses.add(eBonus)
  367.         CORP_BONUSES[eCorp] = bonuses
  368.  
  369. def getSurplusBonuses(playerOrID, minimum=1):
  370.     """
  371.     Returns a list of bonus IDs of which <player> has at least <minimum> available to export.
  372.     """
  373.     player = PlayerUtil.getPlayer(playerOrID)
  374.     available = []
  375.     for eBonus in range(gc.getNumBonusInfos()):
  376.         if player.getNumTradeableBonuses(eBonus) >= minimum:
  377.             available.append(eBonus)
  378.     return available
  379.  
  380. def getTradeableBonuses(fromPlayerOrID, toPlayerOrID):
  381.     """
  382.     Returns two sets of bonus IDs that <fromPlayer> will and won't trade to <toPlayer>.
  383.    
  384.     Assumes that the two players can trade bonuses.
  385.     """
  386.     fromPlayer = PlayerUtil.getPlayer(fromPlayerOrID)
  387.     eToPlayer = PlayerUtil.getPlayerID(toPlayerOrID)
  388.     fromPlayerIsHuman = fromPlayer.isHuman()
  389.     will = set()
  390.     wont = set()
  391.     tradeData = TradeData()
  392.     tradeData.ItemType = TradeableItems.TRADE_RESOURCES
  393.     for eBonus in range(gc.getNumBonusInfos()):
  394.         tradeData.iData = eBonus
  395.         if fromPlayer.canTradeItem(eToPlayer, tradeData, False):
  396.             if fromPlayerIsHuman or fromPlayer.canTradeItem(eToPlayer, tradeData, True):
  397.                 will.add(eBonus)
  398.             else:
  399.                 wont.add(eBonus)
  400.     return will, wont
  401.  
  402.  
  403. ## Trade Routes
  404.  
  405. def isFractionalTrade():
  406.     """
  407.     Returns True of BULL is active with Fractional Trade Routes.
  408.     """
  409.     return FRACTIONAL_TRADE
  410.  
  411. def getTradeProfitFunc():
  412.     """
  413.     Returns the CyCity function to use to calculate the trade route profit for a single route.
  414.     """
  415.     return TRADE_PROFIT_FUNC
  416.  
  417. def calculateTradeRouteYield(city, route, yieldType):
  418.     """
  419.     Returns the total <yieldType> for the <route>th trade route in <city>.
  420.    
  421.     If Fractional Trade Routes is active, the value returned is fractional (times 100).
  422.     """
  423.     return city.calculateTradeYield(yieldType, TRADE_PROFIT_FUNC(city, city.getTradeCity(route)))
  424.  
  425. def calculateTotalTradeRouteYield(city, yieldType):
  426.     """
  427.     Returns the total <yieldType> for all trade routes in <city>.
  428.    
  429.     If Fractional Trade Routes is active, the total is rounded down and returned as a regular number.
  430.     """
  431.     trade = 0
  432.     for route in range(city.getTradeRoutes()):
  433.         trade += calculateTradeRouteYield(city, route, yieldType)
  434.     if isFractionalTrade():
  435.         trade /= 100
  436.     return trade
  437.        
  438.     return city.calculateTradeYield(yieldType, TRADE_PROFIT_FUNC(city, city.getTradeCity(route)))
  439.  
  440. def calculateTradeRoutes(playerOrID, withPlayerOrID=None):
  441.     """
  442.     Returns the domestic and foreign trade route yields and counts for <playerOrID>:
  443.     domestic yield, domestic count, foreign yield, and foreign count.
  444.    
  445.     If <withPlayerOrID> is given, only counts trade routes to their cities.
  446.     If Fractional Trade Routes is active, the value returned is fractional (times 100).
  447.     """
  448.     domesticTrade = domesticCount = foreignTrade = foreignCount = 0
  449.     eTeam = PlayerUtil.getPlayerTeam(playerOrID)
  450.     eWithPlayer = PlayerUtil.getPlayerID(withPlayerOrID)
  451.     for city in PlayerUtil.playerCities(playerOrID):
  452.         for i in range(city.getTradeRoutes()):
  453.             tradeCity = city.getTradeCity(i)
  454.             if tradeCity and tradeCity.getOwner() >= 0 and (eWithPlayer == -1 or eWithPlayer == tradeCity.getOwner()):
  455.                 trade = city.calculateTradeYield(YieldTypes.YIELD_COMMERCE, TRADE_PROFIT_FUNC(city, tradeCity))
  456.                 if tradeCity.getTeam() == eTeam:
  457.                     domesticTrade += trade
  458.                     domesticCount += 1
  459.                 else:
  460.                     foreignTrade += trade
  461.                     foreignCount += 1
  462.     return domesticTrade, domesticCount, foreignTrade, foreignCount
  463.  
  464. def initFractionalTrade():
  465.     """
  466.     Sets the global fractional trade constants by testing for the function it adds.
  467.    
  468.     Fractional Trade is an optional compile-time feature of BULL.
  469.     """
  470.     global FRACTIONAL_TRADE, TRADE_PROFIT_FUNC
  471.     try:
  472.         TRADE_PROFIT_FUNC = CyCity.calculateTradeProfitTimes100
  473.         FRACTIONAL_TRADE = True
  474.         BugUtil.debug("TradeUtil - Fractional Trade Routes is active")
  475.     except:
  476.         TRADE_PROFIT_FUNC = CyCity.calculateTradeProfit
  477.         FRACTIONAL_TRADE = False
  478.  
  479.  
  480. ## Trade Class
  481.  
  482. class Trade(object):
  483.     """
  484.     Encapsulates the player IDs and TradeData for a new or proposed trade.
  485.    
  486.     Implements the same interface as the DealUtil.Deal class.
  487.     """
  488.     def __init__(self, ePlayer, eOtherPlayer):
  489.         self.ePlayer = ePlayer
  490.         self.eOtherPlayer = eOtherPlayer
  491.         self.tradeList = []
  492.         self.otherTradeList = []
  493.    
  494.     def isReversed(self):
  495.         return False
  496.     def getPlayer(self):
  497.         return self.ePlayer
  498.     def getOtherPlayer(self):
  499.         return self.eOtherPlayer
  500.    
  501.     def getCount(self):
  502.         return len(self.tradeList)
  503.     def getOtherCount(self):
  504.         return len(self.otherTradeList)
  505.     def getTrade(self, index):
  506.         return self.tradeList[index]
  507.     def getOtherTrade(self, index):
  508.         return self.otherTradeList[index]
  509.     def trades(self):
  510.         return self.tradeList
  511.     def otherTrades(self):
  512.         return self.otherTradeList
  513.    
  514.     def addTrade(self, trade):
  515.         self.tradeList.append(trade)
  516.     def addOtherTrade(self, trade):
  517.         self.otherTradeList.append(trade)
  518.    
  519.     def hasType(self, type):
  520.         return self.hasAnyType((type,))
  521.     def hasAnyType(self, types):
  522.         for trade in self.trades():
  523.             if trade.ItemType in types:
  524.                 return True
  525.         for trade in self.otherTrades():
  526.             if trade.ItemType in types:
  527.                 return True
  528.         return False
  529.     def findType(self, type):
  530.         return self.findTypes((type,))
  531.     def findTypes(self, types):
  532.         found = []
  533.         for trade in self.trades():
  534.             for type in types:
  535.                 if type == trade.ItemType:
  536.                     found.append(trade)
  537.         for trade in self.otherTrades():
  538.             for type in types:
  539.                 if type == trade.ItemType:
  540.                     found.append(trade)
  541.         return found
  542.    
  543.     def __repr__(self):
  544.         return ("<trade %d [%s] for %d [%s]>" %
  545.                 (self.getPlayer(),
  546.                 format(self.getPlayer(), self.trades()),
  547.                 self.getOtherPlayer(),
  548.                 format(self.getOtherPlayer(), self.otherTrades())))
  549.  
  550.  
  551. ## TradeData Formatting
  552.  
  553. def format(player, trade):
  554.     """Returns a single string containing all of the trade items separated by commas.
  555.    
  556.     player can be either an ID or CyPlayer and is needed when a city is being traded.
  557.     """
  558.     if isinstance(trade, list) or isinstance(trade, tuple) or isinstance(trade, set):
  559.         return ", ".join([format(player, t) for t in trade])
  560.     elif trade.ItemType in TRADE_FORMATS:
  561.         return TRADE_FORMATS[trade.ItemType].format(player, trade)
  562.     else:
  563.         BugUtil.warn("TradeUtil - unknown item type %d", trade.ItemType)
  564.         return ""
  565.  
  566. def initTradeableItems():
  567.     addSimpleTrade("gold", TradeableItems.TRADE_GOLD, "TXT_KEY_TRADE_GOLD_NUM")
  568.     addSimpleTrade("gold per turn", TradeableItems.TRADE_GOLD_PER_TURN, "TXT_KEY_TRADE_GOLD_PER_TURN_NUM")
  569.     addPlainTrade("map", TradeableItems.TRADE_MAPS, "TXT_KEY_TRADE_WORLD_MAP_STRING")
  570.     addPlainTrade("vassal", TradeableItems.TRADE_VASSAL, "TXT_KEY_TRADE_VASSAL_TREATY_STRING")
  571.     addPlainTrade("capitulation", TradeableItems.TRADE_SURRENDER, "TXT_KEY_TRADE_CAPITULATE_STRING")
  572.     addPlainTrade("open borders", TradeableItems.TRADE_OPEN_BORDERS, "TXT_KEY_TRADE_OPEN_BORDERS_STRING")
  573.     addPlainTrade("defensive pact", TradeableItems.TRADE_DEFENSIVE_PACT, "TXT_KEY_TRADE_DEFENSIVE_PACT_STRING")
  574.     addPlainTrade("alliance", TradeableItems.TRADE_PERMANENT_ALLIANCE, "TXT_KEY_TRADE_PERMANENT_ALLIANCE_STRING")
  575.     addComplexTrade("peace treaty", TradeableItems.TRADE_PEACE_TREATY, getTradePeaceDeal)
  576.     addComplexTrade("technology", TradeableItems.TRADE_TECHNOLOGIES, getTradeTech)
  577.     addComplexTrade("resource", TradeableItems.TRADE_RESOURCES, getTradeBonus)
  578.     addComplexTrade("city", TradeableItems.TRADE_CITIES, getTradeCity)
  579.     addAppendingTrade("peace", TradeableItems.TRADE_PEACE, "TXT_KEY_TRADE_PEACE_WITH", getTradePlayer)
  580.     addAppendingTrade("war", TradeableItems.TRADE_WAR, "TXT_KEY_TRADE_WAR_WITH", getTradePlayer)
  581.     addAppendingTrade("trade embargo", TradeableItems.TRADE_EMBARGO, "TXT_KEY_TRADE_STOP_TRADING_WITH", getTradePlayer, " %s")
  582.     addAppendingTrade("civic", TradeableItems.TRADE_CIVIC, "TXT_KEY_TRADE_ADOPT", getTradeCivic)
  583.     addAppendingTrade("religion", TradeableItems.TRADE_RELIGION, "TXT_KEY_TRADE_CONVERT", getTradeReligion)
  584.     #Afforess
  585.     addPlainTrade("limited borders", TradeableItems.TRADE_RIGHT_OF_PASSAGE, "TXT_KEY_TRADE_LIMITED_BORDERS_STRING")
  586.     addPlainTrade("embassy", TradeableItems.TRADE_EMBASSY, "TXT_KEY_TRADE_EMBASSY_STRING")
  587.     addComplexTrade("units", TradeableItems.TRADE_MILITARY_UNIT, getTradeUnits)
  588.     #Afforess End
  589.    
  590. def addPlainTrade(name, type, key):
  591.     """Creates a trade using an unparameterized XML <text> tag."""
  592.     return addTrade(type, PlainTradeFormat(name, type, key))
  593.  
  594. def addSimpleTrade(name, type, key):
  595.     """Creates a trade using an XML <text> tag with a int placeholder for iData."""
  596.     return addTrade(type, SimpleTradeFormat(name, type, key))
  597.  
  598. def addAppendingTrade(name, type, key, argsFunction, text="%s"):
  599.     """Creates a trade using an XML <text> tag with a single appended string placeholder."""
  600.     format = addTrade(type, AppendingTradeFormat(name, type, key, text))
  601.     if argsFunction is not None:
  602.         format.getParameters = lambda player, trade: argsFunction(player, trade)
  603.     return format
  604.  
  605. def addComplexTrade(name, type, argsFunction, textFunction=None):
  606.     """Creates a trade using an XML <text> tag with any number of placeholders."""
  607.     format = addTrade(type, ComplexTradeFormat(name, type))
  608.     if argsFunction is not None:
  609.         format.getParameters = lambda player, trade: argsFunction(player, trade)
  610.     if textFunction is not None:
  611.         format.getText = lambda player, trade: textFunction(player, trade)
  612.     return format
  613.  
  614. def addTrade(type, format):
  615.     TRADE_FORMATS[type] = format
  616.     return format
  617.  
  618.  
  619. ## Functions for use as argsFunction: converting TradeData.iData into
  620. ## whatever you want to display in the formatted string.
  621.  
  622. def getTradeTech(player, trade):
  623.     return gc.getTechInfo(trade.iData).getDescription()
  624.  
  625. def getTradeBonus(player, trade):
  626.     return gc.getBonusInfo(trade.iData).getDescription()
  627.  
  628. def getTradeCity(player, trade):
  629.     return PlayerUtil.getPlayer(player).getCity(trade.iData).getName()
  630.  
  631. def getTradeCivic(player, trade):
  632.     return gc.getCivicInfo(trade.iData).getDescription()
  633.  
  634. def getTradeReligion(player, trade):
  635.     return gc.getReligionInfo(trade.iData).getDescription()
  636.  
  637. def getTradePlayer(player, trade):
  638.     return PlayerUtil.getPlayer(trade.iData).getName()
  639.  
  640. def getTradePeaceDeal(player, trade):
  641.     BugUtil.debug("TradeUtil - peace treaty has iData %d", trade.iData)
  642.     return BugUtil.getText("TXT_KEY_TRADE_PEACE_TREATY_STRING", (gc.getDefineINT("PEACE_TREATY_LENGTH"),))
  643.  
  644. #Afforess
  645. def getTradeUnits(player, trade):
  646.     return PlayerUtil.getPlayer(player).getUnit(trade.iData).getName()
  647. #Afforess End
  648. ## Classes for Formatting TradeData
  649.  
  650. class BaseTradeFormat(object):
  651.     def __init__(self, name, type):
  652.         self.name = name
  653.         self.type = type
  654.     def format(self, player, trade):
  655.         pass
  656.  
  657. class PlainTradeFormat(BaseTradeFormat):
  658.     def __init__(self, name, type, key):
  659.         super(PlainTradeFormat, self).__init__(name, type)
  660.         self.key = key
  661.     def format(self, player, trade):
  662.         return BugUtil.getPlainText(self.key)
  663.  
  664. class SimpleTradeFormat(BaseTradeFormat):
  665.     def __init__(self, name, type, key):
  666.         super(SimpleTradeFormat, self).__init__(name, type)
  667.         self.key = key
  668.     def format(self, player, trade):
  669.         return BugUtil.getText(self.key, (self.getParameters(player, trade),))
  670.     def getParameters(self, player, trade):
  671.         return trade.iData
  672.  
  673. class AppendingTradeFormat(BaseTradeFormat):
  674.     def __init__(self, name, type, key, text="%s"):
  675.         super(AppendingTradeFormat, self).__init__(name, type)
  676.         self.key = key
  677.         self.text = text
  678.     def format(self, player, trade):
  679.         return self.getText(player, trade) % (self.getParameters(player, trade),)
  680.     def getText(self, player, trade):
  681.         return BugUtil.getPlainText(self.key) + self.text
  682.     def getParameters(self, player, trade):
  683.         return trade.iData
  684.  
  685. class ComplexTradeFormat(BaseTradeFormat):
  686.     def __init__(self, name, type):
  687.         super(ComplexTradeFormat, self).__init__(name, type)
  688.     def format(self, player, trade):
  689.         return self.getText(player, trade) % (self.getParameters(player, trade),)
  690.     def getText(self, player, trade):
  691.         return "%s"
  692.     def getParameters(self, player, trade):
  693.         return trade.iData
  694.  
  695.  
  696. ## Initialization
  697.  
  698. def init():
  699.     """
  700.     Performs one-time initialization after the game starts up.
  701.     """
  702.     initCorporationBonuses()
  703.     initFractionalTrade()
  704.     initTradeableItems()
  705.  
  706.  
  707. ## Testing
  708.  
  709. def makeTrade(type, value=-1):
  710.     trade = TradeData()
  711.     trade.ItemType = TradeableItems(type)
  712.     if value != -1:
  713.         trade.iData = value
  714.     return trade
  715.  
  716. def test(player, type, value):
  717.     print format(player, makeTrade(type, value))
  718.  
  719. def testAll():
  720.     for i in TRADE_FORMATS.keys():
  721.         test(2, i, 1)
  722.  
  723. def testList():
  724.     print format(2, [
  725.         makeTrade(TradeableItems.TRADE_GOLD, 53),
  726.         makeTrade(TradeableItems.TRADE_MAPS),
  727.         makeTrade(TradeableItems.TRADE_PEACE, 1),
  728.         makeTrade(TradeableItems.TRADE_CITY, 1),
  729.         makeTrade(TradeableItems.TRADE_GOLD_PER_TURN, 6),
  730.     ])
  731.  
  732. STATUS_TRADE_ITEMS = (
  733.     (TradeableItems.TRADE_MAPS, "Map"),
  734.     (TradeableItems.TRADE_VASSAL, "Vassal"),
  735.     (TradeableItems.TRADE_SURRENDER, "Surrender"),
  736.     (TradeableItems.TRADE_OPEN_BORDERS, "Borders"),
  737.     (TradeableItems.TRADE_DEFENSIVE_PACT, "Pact"),
  738.     (TradeableItems.TRADE_PERMANENT_ALLIANCE, "Alliance"),
  739.     (TradeableItems.TRADE_PEACE_TREATY, "Peace"),
  740. #RevolutionDCM start - extra civlerts
  741.     (TradeableItems.TRADE_WAR, "War"),
  742. #RevolutionDCM end
  743.    
  744. )
  745. DENIALS = {
  746.     DenialTypes.NO_DENIAL : "None",
  747.     DenialTypes.DENIAL_UNKNOWN : "Unknown",
  748.     DenialTypes.DENIAL_NEVER : "Never",
  749.     DenialTypes.DENIAL_TOO_MUCH : "Too Much",
  750.     DenialTypes.DENIAL_MYSTERY : "Mystery",
  751.     DenialTypes.DENIAL_JOKING : "Joking",
  752.     DenialTypes.DENIAL_ANGER_CIVIC : "Anger Civic",
  753.     DenialTypes.DENIAL_FAVORITE_CIVIC : "Favorite Civic",
  754.     DenialTypes.DENIAL_MINORITY_RELIGION : "Minority Religion",
  755.     DenialTypes.DENIAL_CONTACT_THEM : "Contact Them",
  756.     DenialTypes.DENIAL_VICTORY : "Victory",
  757.     DenialTypes.DENIAL_ATTITUDE : "Attitude",
  758.     DenialTypes.DENIAL_ATTITUDE_THEM : "Attitude Them",
  759.     DenialTypes.DENIAL_TECH_WHORE : "Tech Whore",
  760.     DenialTypes.DENIAL_TECH_MONOPOLY : "Tech Monopoly",
  761.     DenialTypes.DENIAL_POWER_US : "Power Us",
  762.     DenialTypes.DENIAL_POWER_YOU : "Power You",
  763.     DenialTypes.DENIAL_POWER_THEM : "Power Them",
  764.     DenialTypes.DENIAL_TOO_MANY_WARS : "WHEOOH",
  765.     DenialTypes.DENIAL_NO_GAIN : "No Gain",
  766.     DenialTypes.DENIAL_NOT_ALLIED : "Not Allied",
  767.     DenialTypes.DENIAL_RECENT_CANCEL : "Recent Cancel",
  768.     DenialTypes.DENIAL_WORST_ENEMY : "Worst Enemy",
  769.     DenialTypes.DENIAL_POWER_YOUR_ENEMIES : "Power Your Enemies",
  770.     DenialTypes.DENIAL_TOO_FAR : "Too Far",
  771.     # these aren't available during startup (dunno about later)
  772.     #DenialTypes.DENIAL_VASSAL : "Vassal",
  773.     #DenialTypes.DENIAL_WAR_NOT_POSSIBLE_US : "War Not Possible Us",
  774.     #DenialTypes.DENIAL_WAR_NOT_POSSIBLE_THEM : "War Not Possible Them",
  775.     #DenialTypes.DENIAL_PEACE_NOT_POSSIBLE_US : "Peace Not Possible Us",
  776.     #DenialTypes.DENIAL_PEACE_NOT_POSSIBLE_THEM : "Peace Not Possible Them",
  777. }
  778.  
  779. def printStatus(ePlayer, eAskingPlayer=None):
  780.     player = PlayerUtil.getPlayer(ePlayer)
  781.     if eAskingPlayer is None:
  782.         eAskingPlayer = PlayerUtil.getActivePlayerID()
  783.     print "Trade Status -- %s" % player.getName()
  784.     for eItem, name in STATUS_TRADE_ITEMS:
  785.         tradeData = TradeData()
  786.         tradeData.ItemType = eItem
  787.         can = player.canTradeItem(eAskingPlayer, tradeData, False)
  788.         denial = player.getTradeDenial(eAskingPlayer, tradeData)
  789.         will = denial == DenialTypes.NO_DENIAL
  790.         if denial in DENIALS:
  791.             denial = DENIALS[denial]
  792.         else:
  793.             denial = str(denial)
  794.         if not can:
  795.             if will:
  796.                 print "%s: can't but will" % (name)
  797.             else:
  798.                 print "%s: can't and won't because %s" % (name, denial)
  799.         else:
  800.             if will:
  801.                 print "%s: will" % (name)
  802.             else:
  803.                 print "%s: won't because %s" % (name, denial)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement