def initAppFolder(): """ Locates the directory that contains the BTS application. """ global _appFolderInitDone if _appFolderInitDone: return BugUtil.debug("BugPath - initializing application folder") global _appDir, _appFolder # Determine the app directory that holds the executable and Mods # as well as the folder name inside MY_GAMES_FOLDER that holds CustomAssets and Mods. if isMac(): _appDir = os.getcwd() else: if isfile(sys.executable): # BugUtil.debug("BugPath - exe is '%s'", sys.executable) _appDir = dirname(sys.executable) if _appDir: _appFolder = basename(_appDir) safeInfoPath("BugPath - app dir is '%s'", _appDir) safeDebugPath("BugPath - app folder is '%s'", _appFolder) else: BugUtil.warn("BugPath - no executable found") _appFolderInitDone = True
def dispatchEvent(eComment, eFromPlayer, eToPlayer, args): event = g_eventsByCommentType.get(eComment, None) if event: event.dispatch(eFromPlayer, eToPlayer, args) else: key = gc.getDiplomacyInfo(eComment).getType() BugUtil.debug("DiplomacyUtil - ignoring %s from %d to %d with %r", key, eFromPlayer, eToPlayer, args)
def _getPendingAlertMessageIcon(self, city, passes): if (passes): BugUtil.warn("%s passed pending occupation test, ignoring", city.getName()) return (None, None) else: return (localText.getText("TXT_KEY_CIV4LERTS_ON_CITY_PENDING_PACIFIED", (city.getName(), )), HAPPY_ICON)
def configure(logging=None, noLogEvents=None): """Sets the global event manager's logging options.""" if g_eventManager: g_eventManager.setLogging(logging) g_eventManager.setNoLogEvents(noLogEvents) else: BugUtil.error("BugEventManager - BugEventManager not setup before configure()")
def _setValue(self, value, *args): """Sets the actual value in the INI file.""" BugUtil.debug("BugOptions - setting %s to %r", self.getID(), value) if args: return TYPE_SETTER_MAP[self.type](self.file, self.section, self.key % args, value) else: return TYPE_SETTER_MAP[self.type](self.file, self.section, self.key, value)
def __init__ (self, iThisPlayer, iTargetPlayer): pActiveTeam = gc.getTeam(gc.getActivePlayer().getTeam()) iThisTeam = gc.getPlayer(iThisPlayer).getTeam() pThisTeam = gc.getTeam(iThisTeam) iTargetTeam = gc.getPlayer(iTargetPlayer).getTeam() self.iThisPlayer = iThisPlayer self.iTargetPlayer = iTargetPlayer self.iAttitudeSum = 0 self.iAttitudeModifiers = {} self.bHasActiveMetBoth = CyGame().isDebugMode() or (pActiveTeam.isHasMet(iThisTeam) and pActiveTeam.isHasMet(iTargetTeam)) self.eAttitudeType = AttitudeTypes.NO_ATTITUDE # This might be better off being something descriptive such as # "players have not met" or "players are the same" self.sAttitudeString = "" if (iThisPlayer != iTargetPlayer and pThisTeam.isHasMet(iTargetTeam)): self.eAttitudeType = gc.getPlayer(iThisPlayer).AI_getAttitude(iTargetPlayer) self.sAttitudeString = CyGameTextMgr().getAttitudeString(iThisPlayer, iTargetPlayer) for sLine in self.sAttitudeString.split("\n"): #BugUtil.debug(u"LINE: %s" % (sLine)) pMatch = re.match("^.*>([-\+]\d+)\s?:\s+(\".+\")<.*$", sLine, re.UNICODE) if (pMatch): #BugUtil.debug(u"MATCH: (%s) (%s)" %(pMatch.group(1), pMatch.group(2))) iValue = int(pMatch.group(1)) sString = unicode(pMatch.group(2)) if sString in MODIFIER_STRING_TO_KEY: self.iAttitudeModifiers[MODIFIER_STRING_TO_KEY[sString]] = iValue self.iAttitudeSum = self.iAttitudeSum + iValue #BugUtil.debug(u"Attitude::init() - Added to dict: %s" % (sString)) else: BugUtil.debug(u"Attitude::init() - Attitude string contains unknown modifier text: %s" % (sString)) #BugUtil.debug(u"Attitude::init() complete.") BugUtil.debug(u"%s" % (self))
def _handleDefaultEvent(self, eventType, argsList): if self.EventHandlerMap.has_key(eventType): for eventHandler in self.EventHandlerMap[eventType]: try: eventHandler(argsList) except: BugUtil.trace("Error in %s event handler %s", eventType, eventHandler)
def onPlayerRevolution(self, argsList): ePlayer, iAnarchyTurns, leOldCivics, leNewCivics = argsList civics = [] for eOldCivic, eNewCivic in zip(leOldCivics, leNewCivics): if eOldCivic != eNewCivic: civics.append(gc.getCivicInfo(eNewCivic).getDescription()) BugUtil.debug("Revolution for %s, %d turns: %s", gc.getPlayer(ePlayer).getCivilizationShortDescription(0), iAnarchyTurns, ", ".join(civics))
def onEmbargoRejected(argsList): #BugUtil.debug("DiplomacyUtil::onEmbargoRejected %s" %(str(argsList))) eTargetPlayer, eDemandPlayer, eVictim = argsList BugUtil.debug("DiplomacyUtil - %s rejects demand from %s to stop trading with %s", PlayerUtil.getPlayer(eTargetPlayer).getName(), PlayerUtil.getPlayer(eDemandPlayer).getName(), PlayerUtil.getPlayer(eVictim).getName())
def onReligionRejected(argsList): #BugUtil.debug("DiplomacyUtil::onReligionRejected %s" %(str(argsList))) eTargetPlayer, eDemandPlayer, eReligion = argsList BugUtil.debug("DiplomacyUtil - %s rejects demand from %s to convert to %s", PlayerUtil.getPlayer(eTargetPlayer).getName(), PlayerUtil.getPlayer(eDemandPlayer).getName(), gc.getReligionInfo(eReligion).getDescription())
def onWarDemanded(argsList): #BugUtil.debug("DiplomacyUtil::onWarDemanded %s" %(str(argsList))) eDemandPlayer, eTargetPlayer, eVictim = argsList BugUtil.debug("DiplomacyUtil - %s asks %s to declare war on %s", PlayerUtil.getPlayer(eDemandPlayer).getName(), PlayerUtil.getPlayer(eTargetPlayer).getName(), PlayerUtil.getPlayer(eVictim).getName())
def onCivicRejected(argsList): #BugUtil.debug("DiplomacyUtil::onCivicRejected %s" %(str(argsList))) eTargetPlayer, eDemandPlayer, eCivic = argsList BugUtil.debug("DiplomacyUtil - %s rejects demand from %s to switch to %s", PlayerUtil.getPlayer(eTargetPlayer).getName(), PlayerUtil.getPlayer(eDemandPlayer).getName(), gc.getCivicInfo(eCivic).getDescription())
def onHelpOffered(argsList): #BugUtil.debug("DiplomacyUtil::onHelpOffered %s" %(str(argsList))) eOfferPlayer, eTargetPlayer, pTrade = argsList BugUtil.debug("DiplomacyUtil - %s offers help to %s: %r", PlayerUtil.getPlayer(eOfferPlayer).getName(), PlayerUtil.getPlayer(eTargetPlayer).getName(), pTrade)
def onDealRejected(argsList): #BugUtil.debug("DiplomacyUtil::onDealRejected %s" %(str(argsList))) eTargetPlayer, eOfferPlayer, pTrade = argsList BugUtil.debug("DiplomacyUtil - %s accepts trade offered by %s: %r", PlayerUtil.getPlayer(eTargetPlayer).getName(), PlayerUtil.getPlayer(eOfferPlayer).getName(), pTrade)
def __init__(self, eventManager, *args, **kwargs): super(StatusDumpEvent, self).__init__(eventManager, *args, **kwargs) eventManager.addEventHandler("kbdEvent", self.onKbdEvent) self.eventMgr = eventManager BugUtil.debug("StatusDump-Start-0")
def DumpStatus(self): BugUtil.debug("StatusDump") # open the status dump file self.StatusDump_OpenFile() # Year zyear = self._getGameYear() zsTurn = self._getGameTurn() zCurrDateTime = time.strftime("%d-%b-%Y %H:%M:%S") sMsg = BugUtil.getText("TXT_KEY_STATUS_DUMP_TURN", (zsTurn, zyear, zCurrDateTime)) self._writeMsg(sMsg, vColor="Black", vBold=False, vUnderline=True, vOpenSpoiler=sMsg, vCloseSpoiler=False) # basic leader information self.StatusDump_Basic() # tech, culture, espionage, gold per turn info self.StatusDump_Spinners() # loop over each city self.StatusDump_Player_Cities() # loop over each unit self.StatusDump_Player_Units() # tech, culture, espionage, gold per turn info self.StatusDump_AIs() self._writeMsg(" ", vColor="Black", vBold=False, vUnderline=False, vOpenSpoiler="", vCloseSpoiler=True) self.StatusDump_CloseFile()
def StatusDump_Basic(self): BugUtil.debug("StatusDump - basic") # dump basic stuff # - leader name / civ # - current game turn and year # - current tech being researched # - techs available to research # - opponents # - scoreboard # - number of cities # - bank balance # player stuff ePlayer = gc.getGame().getActivePlayer() pPlayer = gc.getPlayer(ePlayer) # human / game name sMsg = BugUtil.getText("TXT_KEY_STATUS_DUMP_PLAYER_NAME", (pPlayer.getCivilizationShortDescription(0))) self._writeMsg(sMsg, vColor="Black", vBold=False, vUnderline=False, vOpenSpoiler="", vCloseSpoiler=False) # leader / civ name sMsg = BugUtil.getText("TXT_KEY_STATUS_DUMP_LEADER_CIV", (gc.getLeaderHeadInfo(pPlayer.getLeaderType()).getDescription(), pPlayer.getCivilizationShortDescription(0))) self._writeMsg(sMsg, vColor="Black", vBold=False, vUnderline=False, vOpenSpoiler="", vCloseSpoiler=False)
def _getGameYear(self): zturn = gc.getGame().getGameTurn() + 1 zyear = gc.getGame().getTurnYear(zturn) if (zyear < 0): return str(-zyear) + BugUtil.getPlainText("TXT_KEY_AUTOLOG_BC") else: return str(zyear) + BugUtil.getPlainText("TXT_KEY_AUTOLOG_AD")
def _getRemoteRevision(url): """ Parses and returns the revision number from a remote SVN repository. The URL must be correctly escaped (+ for space, etc). A BugError exception is raised if the URL can't be connected to or it doesn't have the expected format. This function looks specifically for the string 'Revision: ####' anywhere in the first MAX_READ_LINES """ try: timer = BugUtil.Timer("SvnUtil.getRevision") try: BugUtil.debug("SvnUtil.getRevision - opening '%s'", url) web = urllib.urlopen(urllib.quote(url, "/:")) count = 0 try: for line in web: result = REVISION_PATTERN.search(line) if result: BugUtil.debug("SvnUtil.getRevision - found '%s'", result.group()) try: return int(result.group(1)) except ValueError: raise BugUtil.BugError("invalid SVN revision format '%s'" % result.group(1)) count += 1 if count > MAX_READ_LINES: return None finally: web.close() except IOError, e: raise BugUtil.BugError("failed to access SVN repository: %s" % str(e)) return None
def init(): """ Segregates units into two sets: those that require resources and those that don't. Creates a map of units from ID to the set of tech prerequisites. """ global NUM_UNITS, NUM_CLASSES NUM_UNITS = gc.getNumUnitInfos() NUM_CLASSES = gc.getNumUnitClassInfos() global NUM_OR_BONUSES, NUM_AND_TECHS NUM_OR_BONUSES = gc.getNUM_UNIT_PREREQ_OR_BONUSES() NUM_AND_TECHS = gc.getNUM_UNIT_AND_TECH_PREREQS() for eUnit in range(NUM_UNITS): unitInfo = gc.getUnitInfo(eUnit) BugUtil.debug("==== %s ====", unitInfo.getDescription()) # generic unit classInfo = gc.getUnitClassInfo(unitInfo.getUnitClassType()) eGenericUnit = classInfo.getDefaultUnitIndex() genericUnitIDs[eUnit] = eGenericUnit if eUnit == eGenericUnit: genericUnits.add(eUnit) else: BugUtil.debug(" unique of %s", gc.getUnitInfo(eGenericUnit).getDescription()) # resource sets found = False eBonus = unitInfo.getPrereqAndBonus() if eBonus != -1: found = True strategicBonuses.add(eBonus) BugUtil.debug(" requires %s", gc.getBonusInfo(eBonus).getDescription()) for i in range(NUM_OR_BONUSES): eBonus = unitInfo.getPrereqOrBonuses(i) if eBonus != -1: found = True strategicBonuses.add(eBonus) BugUtil.debug(" requires %s", gc.getBonusInfo(eBonus).getDescription()) if found: unitsWithBonuses.add(eUnit) else: unitsWithoutBonuses.add(eUnit) # tech map techs = set() unitTechs[eUnit] = techs eTech = unitInfo.getPrereqAndTech() if eTech != -1: techs.add(eTech) for i in range(NUM_AND_TECHS): eTech = unitInfo.getPrereqAndTechs(i) if eTech != -1: techs.add(eTech) for eTech in techs: BugUtil.debug(" requires %s", gc.getTechInfo(eTech).getDescription()) # upgrade maps for eUnit in range(NUM_UNITS): getOlderUnits(eUnit) getNewerUnits(eUnit)
def _findTable(self, key): if self._hasTable(key): BugUtil.debug("BugTable - found %s in %s", key, self) return self._getTable(key) else: BugUtil.debug("BugTable - %s not found in %s", key, self) return None
def run(self): try: self._rev = _getRemoteRevision(self._url) BugUtil.debug("RemoteRevisionThread.run - found revision %d", self._rev) except BugError, e: self._error = e BugUtil.debug("RemoteRevisionThread.run - %s", self._error.message)
def __init__(self): Grouping.__init__(self, "level", "TXT_KEY_UNIT_GROUPER_LEVEL_GROUPING") self.MAX_LEVEL = 50 for i in range(self.MAX_LEVEL): self._addGroup(Group(self, i, BugUtil.getText("TXT_KEY_UNIT_GROUPER_LEVEL_GROUP", (str(i),)))) self._addGroup(Group(self, self.MAX_LEVEL, BugUtil.getText("TXT_KEY_UNIT_GROUPER_LEVEL_GROUP", ("%d+" % self.MAX_LEVEL,))))
def initHelpers (): """ Initialize the helper data structures, clearing all previous data. Because most of the functions in this module always start out checking whether detection is necessary, this is stored in a global Boolean which is set here based on game options and then directly accessed everywhere else; it can be also accessed outside the module via an accessor function. The other helper which is setup here is a dict of civics keyed on their category. This is useful because the civic detection algorithms often need to exclude either an entire category or all but one civic in a given category. This data structure allows us to simply iterate over a specific category instead of having to iterate over all civics each time. """ global gDetectionNecessary gDetectionNecessary = gc.getGame().isOption(GameOptionTypes.GAMEOPTION_RANDOM_PERSONALITIES) BugUtil.debug("FavoriteCivicDetector.initHelpers() gDetectionNecessary: %s" % (str(gDetectionNecessary))) if gDetectionNecessary: BugUtil.debug("FavoriteCivicDetector.initHelpers() initializing gCivicsByCategory") global gCivicsByCategory gCivicsByCategory = {} for eCategory in range(gc.getNumCivicOptionInfos()): gCivicsByCategory[eCategory] = set() for eCivic in range(gc.getNumCivicInfos()): gCivicsByCategory[gc.getCivicInfo(eCivic).getCivicOptionType()].add(eCivic)
def onWarRejected(argsList): #BugUtil.debug("DiplomacyUtil::onWarRejected %s" %(str(argsList))) eTargetPlayer, eDemandPlayer, eVictim = argsList BugUtil.debug("DiplomacyUtil - %s rejects demand from %s to declare war on %s", PlayerUtil.getPlayer(eTargetPlayer).getName(), PlayerUtil.getPlayer(eDemandPlayer).getName(), PlayerUtil.getPlayer(eVictim).getName())
def addOption(self, option): """Adds an Option to the dictionary if its ID doesn't clash.""" if option.id in self.options: BugUtil.error("BugOptions - duplicate option %s", option.id) else: self.options[option.id] = option BugUtil.debug("BugOptions - added option %s", str(option))
def createFileGetter(self, file): """Creates a getter for the given IniFile.""" def get(): return file getter = "get" + file.id setattr(self, getter, get) BugUtil.debug("BugOptions - %s will return IniFile %s", getter, file.id)
def createOption(self, element, id, type, key, default, andId, dll, title, tooltip, dirtyBit, getter, setter): if type == "color": return self.createListOption(element, id, type, key, default, andId, dll, title, tooltip, dirtyBit, getter, setter, type, None, None) mod = element.getState("mod") id = qualify(mod._id, id) andId = qualify(mod._id, andId) dll = self.resolveDll(element, dll) option = None ini = element.getState("ini") if ini and not key: key = id if key: if not ini: BugUtil.warn("BugConfig - <option> %s outside <options> element has a key attribute; making it unsaved", id) else: section = element.getState("ini-section") if not section: BugUtil.warn("BugConfig - <option> %s inside <options> element must be inside a <section> element; making it unsaved", id) else: option = IniOption(mod, id, ini, section, key, type, default, andId, dll, title, tooltip, dirtyBit) if option is None: option = UnsavedOption(mod, id, type, default, andId, dll, title, tooltip, dirtyBit) self.addOption(mod, option, getter, setter) element.setState("option", option) return option
def addFile(self, file): """Adds the given IniFile to the dictionary.""" if file.id in self.files: BugUtil.error("BugOptions - duplicate INI file: %s", file.id) else: self.files[file.id] = file self.createFileGetter(file)
def __delitem__(self, key): BugUtil.debug("BugData - del %s.%s", self, key) try: del self.data[key] self.dirty = True except: pass
def _getCallback(self, name): try: return self._callbacks[name] except KeyError: BugUtil.trace("Unknown GameUtils callback %s", name) raise
def _checkEvent(self, eventType): """Raises ConfigError if the eventType is undefined.""" if not self.hasEvent(eventType): raise BugUtil.ConfigError("Event '%s' is undefined" % eventType)
def hookupPreGameStartEvent(): BugUtil.extend(preGameStart, "CvAppInterface", "preGameStart")
def onCombatLogFlanking(self, argsList): """Fired when a unit inflicts flanking damage to another unit.""" pAttacker, pDefender, iDamage = argsList BugUtil.debug("%s flanks %s for %d HP", pAttacker.getName(), pDefender.getName(), iDamage)
def onCombatLogCollateral(self, argsList): """Fired when a unit inflicts collateral damage to another unit.""" pAttacker, pDefender, iDamage = argsList BugUtil.debug("%s bombards %s for %d HP", pAttacker.getName(), pDefender.getName(), iDamage)
def onCombatRetreat(self, argsList): """Fired when a unit retreats from combat, escaping death.""" pAttacker, pDefender = argsList BugUtil.debug("%s retreats from %s", pAttacker.getName(), pDefender.getName())
def onCombatWithdrawal(self, argsList): """Fired when a unit withdraws from combat after doing maximum damage.""" pAttacker, pDefender = argsList BugUtil.debug("%s withdraws from %s", pAttacker.getName(), pDefender.getName())
def onKbdEvent(self, argsList): """ Handles onKbdEvent by firing the keystroke's handler if it has one registered. """ eventType, key, mx, my, px, py = argsList if eventType == self.EventKeyDown and not InputUtil.isModifier(key): # <advc.007b> # Added not bCtrl/bAlt/bShift checks so that each cheat is triggered by only one combination of modifier keys theKey = int(key) if not self.bShift and self.bCtrl and self.bAlt and theKey == int( InputTypes.KB_R): BugUtil.warn( "Note (AdvCiv): Reloading of Art Defines (Ctrl+Alt+R) is disabled" ) return 1 # Don't use this key combination for anything else # </advc.007b> stroke = InputUtil.Keystroke(key, self.bAlt, self.bCtrl, self.bShift) if stroke in self.shortcuts: BugUtil.debug( "BugEventManager - calling handler for shortcut %s", stroke) self.shortcuts[stroke](argsList) return 1 # <advc.007b> if gc.getGame().isDebugMode(): # Cheats copied from CvEventManager # Shift - T Debug - techs if self.bShift and not self.bCtrl and not self.bAlt and theKey == int( InputTypes.KB_T): self.beginEvent(CvUtil.EventAwardTechsAndGold) return 1 elif self.bShift and self.bCtrl and not self.bAlt and theKey == int( InputTypes.KB_W): self.beginEvent(CvUtil.EventShowWonder) return 1 # Shift - ] Debug - currently mouse-over'd unit: health+=10 elif theKey == int( InputTypes.KB_LBRACKET ) and self.bShift and not self.bCtrl and not self.bAlt: unit = CyMap().plot(px, py).getUnit(0) if not unit.isNone(): d = min(unit.maxHitPoints() - 1, unit.getDamage() + 10) unit.setDamage(d, PlayerTypes.NO_PLAYER) # Shift - [ Debug - currently mouse-over'd unit: health-= 10 elif theKey == int( InputTypes.KB_RBRACKET ) and self.bShift and not self.bCtrl and not self.bAlt: unit = CyMap().plot(px, py).getUnit(0) if not unit.isNone(): d = max(0, unit.getDamage() - 10) unit.setDamage(d, PlayerTypes.NO_PLAYER) # <advc.gfd> Keep Nightinggale's key combination elif theKey == int( InputTypes.KB_F1 ) and self.bShift and self.bCtrl and not self.bAlt: GameFontDisplay.GameFontDisplay().interfaceScreen() return 1 # </advc.gfd> elif theKey == int(InputTypes.KB_F1): if self.bShift and not self.bCtrl and not self.bAlt: CvScreensInterface.replayScreen.showScreen(False) return 1 elif theKey == int(InputTypes.KB_F2): if self.bShift and not self.bCtrl and not self.bAlt: import CvDebugInfoScreen CvScreensInterface.showDebugInfoScreen() return 1 elif theKey == int(InputTypes.KB_F3): if self.bShift and not self.bCtrl and not self.bAlt: CvScreensInterface.showDanQuayleScreen(()) return 1 elif theKey == int(InputTypes.KB_F4): if self.bShift and not self.bCtrl and not self.bAlt: CvScreensInterface.showUnVictoryScreen(()) return 1 # </advc.007b> return 0
def setIsBug(): """ Tells BULL that BUG is ready to receive queries for options. """ BugUtil.debug("BugDll - calling setIsBug()") gc.setIsBug(True)
import BugUtil import InputUtil import types # <advc.007b> import CvUtil import CvScreensInterface # </advc.007b> import GameFontDisplay # advc.gfd # --------- Better BTS AI mod (1/2) ------------- import AIAutoPlay import ChangePlayer import Tester # -- # BUG - Mac Support - start BugUtil.fixSets(globals()) # BUG - Mac Support - end DEFAULT_LOGGING = False DEFAULT_NOLOG_EVENTS = set(("gameUpdate", )) gc = CyGlobalContext() g_eventManager = None class BugEventManager(CvEventManager.CvEventManager): """ Extends the standard event manager by adding support for multiple handlers for each event. Instead of modifying this file as you would have done with CvCustomEventManager,
def getText(self, player, trade): return BugUtil.getPlainText(self.key) + self.text
def display(self, eActivePlayer, key, players): for ePlayer in players: player = gc.getPlayer(ePlayer) if player.isAlive(): message = BugUtil.getText(key, player.getName()) addMessageNoIcon(eActivePlayer, message)
def format(self, player, trade): return BugUtil.getPlainText(self.key)
def format(self, player, trade): return BugUtil.getText(self.key, (self.getParameters(player, trade), ))
def draw(self, screen): """Sorts and draws the scoreboard right-to-left, bottom-to-top.""" timer = BugUtil.Timer("scores") self.hide(screen) self.assignRanks() self.gatherVassals() self.sort() interface = CyInterface() xResolution = screen.getXResolution() yResolution = screen.getYResolution() x = xResolution - 12 # start here and shift left with each column if (interface.getShowInterface() == InterfaceVisibility.INTERFACE_SHOW or interface.isInAdvancedStart()): y = yResolution - 206 else: y = yResolution - 88 totalWidth = 0 height = ScoreOpt.getLineHeight() techIconSize = ScoreOpt.getResearchIconSize() defaultSpacing = ScoreOpt.getDefaultSpacing() spacing = defaultSpacing format = re.findall( '(-?[0-9]+|[^0-9])', ScoreOpt.getDisplayOrder().replace(' ', '').upper()) format.reverse() for k in format: if k == '-': spacing = 0 continue if k[0] in string.digits or k[0] == '-': spacing = int(k) continue if (not columnsByKey.has_key(k)): spacing = defaultSpacing continue column = columnsByKey[k] c = column.id if (not self._anyHas[c]): #spacing = defaultSpacing # disabled by K-Mod continue type = column.type if (c == RESEARCH and not ScoreOpt.isShowResearchIcons()): # switch SPECIAL research icon to DYNAMIC name type = DYNAMIC if (type == SKIP): spacing = defaultSpacing continue elif (type == FIXED): width = column.width value = column.text x -= spacing for p, playerScore in enumerate(self._playerScores): if (playerScore.has(c) and playerScore.value(c)): name = "ScoreText%d-%d" % (p, c) widget = playerScore.widget(c) if widget is None: if (playerScore.value(ALIVE)): widget = (WidgetTypes.WIDGET_CONTACT_CIV, playerScore.getID(), -1) else: widget = (WidgetTypes.WIDGET_GENERAL, -1, -1) screen.setText(name, "Background", value, CvUtil.FONT_RIGHT_JUSTIFY, x, y - p * height, Z_DEPTH, FontTypes.SMALL_FONT, *widget) screen.show(name) x -= width totalWidth += width + spacing spacing = defaultSpacing elif (type == DYNAMIC): width = 0 for playerScore in self._playerScores: if (playerScore.has(c)): value = playerScore.value(c) if (c == NAME and playerScore.isVassal() and ScoreOpt.isGroupVassals()): if (ScoreOpt.isLeftAlignName()): value = VASSAL_PREFIX + value else: value += VASSAL_POSTFIX newWidth = interface.determineWidth(value) if (newWidth > width): width = newWidth if (width == 0): spacing = defaultSpacing continue x -= spacing for p, playerScore in enumerate(self._playerScores): if (playerScore.has(c)): name = "ScoreText%d-%d" % (p, c) value = playerScore.value(c) if (c == NAME and playerScore.isVassal() and ScoreOpt.isGroupVassals()): if (ScoreOpt.isLeftAlignName()): value = VASSAL_PREFIX + value else: value += VASSAL_POSTFIX align = CvUtil.FONT_RIGHT_JUSTIFY adjustX = 0 if (c == NAME): name = "ScoreText%d" % p if (ScoreOpt.isLeftAlignName()): align = CvUtil.FONT_LEFT_JUSTIFY adjustX = width widget = playerScore.widget(c) if widget is None: if (playerScore.value(ALIVE)): widget = (WidgetTypes.WIDGET_CONTACT_CIV, playerScore.getID(), -1) else: widget = (WidgetTypes.WIDGET_GENERAL, -1, -1) screen.setText(name, "Background", value, align, x - adjustX, y - p * height, Z_DEPTH, FontTypes.SMALL_FONT, *widget) screen.show(name) x -= width totalWidth += width + spacing spacing = defaultSpacing else: # SPECIAL if (c == RESEARCH): x -= spacing for p, playerScore in enumerate(self._playerScores): if (playerScore.has(c)): tech = playerScore.value(c) name = "ScoreTech%d" % p info = gc.getTechInfo(tech) screen.addDDSGFC( name, info.getButton(), x - techIconSize, y - p * height - 1, techIconSize, techIconSize, WidgetTypes.WIDGET_PEDIA_JUMP_TO_TECH, tech, -1) x -= techIconSize totalWidth += techIconSize + spacing spacing = defaultSpacing for playerScore in self._playerScores: interface.checkFlashReset(playerScore.getID()) if (interface.getShowInterface() == InterfaceVisibility.INTERFACE_SHOW or interface.isInAdvancedStart()): y = yResolution - 186 else: y = yResolution - 68 screen.setPanelSize("ScoreBackground", xResolution - 21 - totalWidth, y - (height * self.size()) - 4, totalWidth + 12, (height * self.size()) + 8) screen.show("ScoreBackground") timer.log()
def getTradePeaceDeal(player, trade): BugUtil.debug("TradeUtil - peace treaty has iData %d", trade.iData) return BugUtil.getText("TXT_KEY_TRADE_PEACE_TREATY_STRING", (gc.getDefineINT("PEACE_TREATY_LENGTH"), ))
def addListener(self, func, log=None): BugUtil.debug("BugGameUtils - %s - adding %s listener", self.name, func.__module__) self.listeners.append(func) self.setLogging(log)
def setLogging(self, log=None): if log is not None: self.log = log BugUtil.debug("BugGameUtils - callback %s logging is now %s", self.name, self.log)
def init(): global _saveDir _saveDir = BugPath.join(BugPath.getRootDir(), "Saves") if not _saveDir: BugUtil.error("Could not find Saves directory")
def setDefault(self, default): BugUtil.debug("BugGameUtils - %s - setting default to %s", self.name, default) self.default = default
except OSError, (errno, strerror): BugUtil.trace("Error accessing directory from CvAltRoot.py: [%d] %s", errno, strerror) # K-Mod. I'd like to set the user directory like this: # if not setUserDir(os.path.expanduser(join("~", MY_GAMES_FOLDER))): # BugUtil.debug("BugPath - default user dir failed ('%s')" % (os.path.expanduser(join("~", MY_GAMES_FOLDER)))) # but unfortunately, this misses the "documents" part of the path name. Oh well. # user dir if isMac(): # Mac OS X if not setUserDir(join(os.environ['HOME'], "Documents")): BugUtil.warn("Cannot find user's Documents folder") else: # Windows import _winreg import re # used in a bugfix by K-Mod def getRegValue(root, subkey, name): key = _winreg.OpenKey(root, subkey) try: value = _winreg.QueryValueEx(key, name) # K-Mod. We may need to expand environment variables. # unfortuantely, expandvars in this particular version of python can't handle %variables%, so we need to first translate... if value[1] == _winreg.REG_EXPAND_SZ: # here we go... return os.path.expandvars( re.sub(r'%([a-zA-Z_]+)%', r'${\1}', value[0]))
def getGreatPeopleText(city, iGPTurns, iGPBarWidth, bGPBarTypesNone, bGPBarTypesOne, bIncludeCityName): sGreatPeopleChar = u"%c" % CyGame().getSymbolID( FontSymbols.GREAT_PEOPLE_CHAR) if not city: szText = BugUtil.getText("INTERFACE_GREAT_PERSON_NONE", (sGreatPeopleChar, )) elif bGPBarTypesNone: if iGPTurns: if bIncludeCityName: szText = BugUtil.getText( "INTERFACE_GREAT_PERSON_CITY_TURNS", (sGreatPeopleChar, city.getName(), iGPTurns)) else: szText = BugUtil.getText("INTERFACE_GREAT_PERSON_TURNS", (sGreatPeopleChar, iGPTurns)) else: if bIncludeCityName: szText = BugUtil.getText("INTERFACE_GREAT_PERSON_CITY", (sGreatPeopleChar, city.getName())) else: szText = sGreatPeopleChar else: lPercents = calcPercentages(city) if not lPercents: if iGPTurns: if bIncludeCityName: szText = BugUtil.getText( "INTERFACE_GREAT_PERSON_CITY_TURNS", (sGreatPeopleChar, city.getName(), iGPTurns)) else: szText = BugUtil.getText("INTERFACE_GREAT_PERSON_TURNS", (sGreatPeopleChar, iGPTurns)) else: if bIncludeCityName: szText = BugUtil.getText( "INTERFACE_GREAT_PERSON_CITY", (sGreatPeopleChar, city.getName())) else: szText = sGreatPeopleChar else: lPercents.sort() lPercents.reverse() if bGPBarTypesOne or len(lPercents) == 1: iPercent, iUnit = lPercents[0] pInfo = gc.getUnitInfo(iUnit) if iGPTurns: if bIncludeCityName: szText = BugUtil.getText( "INTERFACE_GREAT_PERSON_CITY_TURNS", (pInfo.getDescription(), city.getName(), iGPTurns)) else: szText = BugUtil.getText( "INTERFACE_GREAT_PERSON_TURNS", (pInfo.getDescription(), iGPTurns)) else: if bIncludeCityName: szText = BugUtil.getText( "INTERFACE_GREAT_PERSON_CITY", (pInfo.getDescription(), city.getName())) else: szText = unicode(pInfo.getDescription()) else: if iGPTurns: if bIncludeCityName: szText = BugUtil.getText( "INTERFACE_GREAT_PERSON_CITY_TURNS", (sGreatPeopleChar, city.getName(), iGPTurns)) else: szText = BugUtil.getText( "INTERFACE_GREAT_PERSON_TURNS", (sGreatPeopleChar, iGPTurns)) else: if bIncludeCityName: szText = BugUtil.getText( "INTERFACE_GREAT_PERSON_CITY", (sGreatPeopleChar, city.getName())) else: szText = sGreatPeopleChar + u":" szTypes = "" for iPercent, iUnit in lPercents: szNewTypes = szTypes + u" %c%d%%" % (getUnitIcon(iUnit), iPercent) szNewText = szText + u"<font=2> -%s</font>" % szTypes if CyInterface().determineWidth( szNewText) > iGPBarWidth - 10: # Keep under width break szTypes = szNewTypes if szTypes: szText += u"<font=2> -%s</font>" % szTypes return szText
def translate(self): xmlKey = "TXT_KEY_BUG_OPTTAB_" + self.name.upper() self.title = BugUtil.getPlainText(xmlKey, self.title) self.translated = True
def __init__(self, log=None): self._log = log self._callbacks = {} self._baseUtils = CvGameUtils.CvGameUtils() clazz = CvGameUtils.CvGameUtils for name, func in clazz.__dict__.iteritems(): if not name.startswith("_") and isinstance(func, types.FunctionType): self._createCallback( name, BugUtil.bindFunction(self._baseUtils, name), None, self._log) # setup defaults self._setDefault("isPlayerResearch", True) self._setDefault("createBarbarianUnits", False) self._setDefault("skipResearchPopup", False) self._setDefault("showTechChooserButton", True) self._setDefault("getFirstRecommendedTech", TechTypes.NO_TECH) self._setDefault("getSecondRecommendedTech", TechTypes.NO_TECH) self._setDefault("canRazeCity", True) self._setDefault("canDeclareWar", True) self._setDefault("skipProductionPopup", False) self._setDefault("showExamineCityButton", True) self._setDefault("getRecommendedUnit", UnitTypes.NO_UNIT) self._setDefault("getRecommendedBuilding", BuildingTypes.NO_BUILDING) self._setDefault("updateColoredPlots", False) self._setDefault("unitCannotMoveInto", False) self._setDefault("cannotHandleAction", False) self._setDefault("cannotFoundCity", False) self._setDefault("cannotSelectionListMove", False) self._setDefault("cannotSelectionListGameNetMessage", False) self._setDefault("cannotDoControl", False) self._setDefault("canDoCivic", False) self._setDefault("cannotDoCivic", False) self._setDefault("canTrain", False) self._setDefault("cannotTrain", False) self._setDefault("canConstruct", False) self._setDefault("cannotConstruct", False) self._setDefault("AI_chooseTech", TechTypes.NO_TECH) self._setDefault("AI_chooseProduction", False) self._setDefault("AI_unitUpdate", False) self._setDefault("AI_doDiplo", False) self._setDefault("doHolyCity", False) self._setDefault("doResearch", False) self._setDefault("doGoody", False) self._setDefault("doGrowth", False) self._setDefault("doProduction", False) self._setDefault("doCulture", False) self._setDefault("doPlotCulture", False) self._setDefault("doReligion", False) self._setDefault("cannotSpreadReligion", False) self._setDefault("doGreatPeople", False) self._setDefault("doMeltdown", False) self._setDefault("doReviveActivePlayer", False) self._setDefault("citiesDestroyFeatures", True) self._setDefault("canFoundCitiesOnWater", False) self._setDefault("doCombat", False) self._setDefault("getConscriptUnitType", UnitTypes.NO_UNIT) self._setDefault("canPickPlot", True) self._setDefault("getUnitCostMod", -1) self._setDefault("getBuildingCostMod", -1) self._setDefault("canUpgradeAnywhere", False) self._setDefault("getWidgetHelp", u"")
def safeDebugPath(message, path): try: BugUtil.debug(message, path) except: pass
def getUnitIcon(iUnit): try: return g_unitIcons[iUnit] except: BugUtil.warn("no GP icon for unit %d", iUnit) return u"%c" % CyGame().getSymbolID(FontSymbols.GREAT_PEOPLE_CHAR)
def fillTable(self, screen, table, eYield, eTileType): """Fills the given GFC table control with the chosen yield values.""" self.iRow = 0 # Tiles iTotal = self.getYield(eYield, eTileType) self.appendTable( screen, table, False, BugUtil.getText(LABEL_KEYS[eTileType], (self.tileCounts[eTileType], )), eYield, iTotal) # Trade for eType in (DOMESTIC_TRADE, FOREIGN_TRADE): iValue = self.getYield(eYield, eType) if iValue != 0: self.appendTable(screen, table, False, BugUtil.getPlainText(LABEL_KEYS[eType]), eYield, iValue, TradeUtil.isFractionalTrade()) iValue = self.getYield(eYield, DOMESTIC_TRADE) + self.getYield( eYield, FOREIGN_TRADE) if TradeUtil.isFractionalTrade(): iValue //= 100 iTotal += iValue # Buildings, Corporations, Specialists for eType in (BUILDINGS, CORPORATIONS, SPECIALISTS): iValue = self.getYield(eYield, eType) if iValue != 0: iTotal += iValue self.appendTable(screen, table, False, BugUtil.getPlainText(LABEL_KEYS[eType]), eYield, iValue) # Subtotal and Base Modifiers iModifier = self.getYield(eYield, BASE_MODIFIER) if iModifier != 0: # Subtotal self.appendTableTotal(screen, table, eYield, iTotal) #self.appendTable(screen, table, True, BugUtil.getPlainText("TXT_KEY_CONCEPT_SUBTOTAL"), eYield, iTotal) # Modifier iValue = (iTotal * (iModifier + 100) // 100) - iTotal iSubtotal = iTotal + iValue self.appendTable( screen, table, False, BugUtil.getText("TXT_KEY_CONCEPT_BASE_MODIFIER", (iModifier, )), eYield, iValue) else: iSubtotal = iTotal # Subtotal and Production Modifiers if eYield == YieldTypes.YIELD_PRODUCTION and self.iProductionModifier != 0: # Subtotal self.appendTableTotal(screen, table, eYield, iSubtotal) #self.appendTable(screen, table, True, BugUtil.getPlainText("TXT_KEY_CONCEPT_SUBTOTAL"), eYield, iSubtotal) # Total iTotal = iTotal * (iModifier + self.iProductionModifier + 100) // 100 # Modifier iValue = iTotal - iSubtotal self.appendTable( screen, table, False, BugUtil.getText( "TXT_KEY_CONCEPT_PRODUCTION_MODIFIER", (self.sModifierDetail, self.iProductionModifier)), eYield, iValue) else: iTotal = iSubtotal # Total self.appendTableTotal(screen, table, eYield, iTotal)
def safeInfoPath(message, path): try: BugUtil.info(message, path) except: pass
def getGameData(): if not g_data: BugUtil.warn("BugData not loaded; loading now") initGameData().load() return g_data
def initModFolder(): """ Checks if BUG is running as a mod and sets the folder and name if so. """ global _modFolderInitDone if _modFolderInitDone: return if not CyGame().isFinalInitialized(): BugUtil.debug("BugInit - game not fully initialized") return BugUtil.debug("BugPath - initializing mod folder") global _modDir, _modFolder try: replay = CyReplayInfo() replay.createInfo(0) modDir = replay.getModName().replace('\\', r'/') except: BugUtil.trace("replay not ready") else: if modDir and len(modDir) > 2: if not setModDir(abspath(modDir)): BugUtil.error("Replay provided invalid mod directory") if not _modDir: BugUtil.debug("BugPath - checking CvModFolder") try: import CvModFolder modFolder = CvModFolder.modFolder except ImportError: BugUtil.debug("BugPath - CvModFolder module not present") except AttributeError: BugUtil.error("CvModFolder.py module has no modFolder setting") else: if not setModDir(join(getRootDir(), MODS_FOLDER, modFolder)): if not setModDir(join(getAppDir(), MODS_FOLDER, modFolder)): BugUtil.error( "Cannot find mod folder using '%s' from CvModFolder.py", modFolder) if not _modFolder: BugUtil.debug("BugPath - no mod directory found") _modFolderInitDone = True