def findPopCenterPlanets(db, planetsIDs): """ It finds "center of mass" of population. Returns sorted list of all planets, beginning with those nearest to the found center. """ x = 0 y = 0 population = 0 for planetID in planetsIDs: planet = db[planetID] x += planet.x * planet.storPop y += planet.y * planet.storPop population += planet.storPop x /= population y /= population fakeObj = IDataHolder() fakeObj.x = x fakeObj.y = y return findNearest(db, fakeObj, planetsIDs, maxDist=99999, number=len(planetsIDs))
def getPublicInfo(self, tran, obj): result = IDataHolder() result.oid = obj.oid result.type = obj.type result.name = obj.name result.turn = obj.turn return result
def getTechInfo(techID): player = db[db.playerID] tech = Rules.techs[techID] # player possess this technology if player.techs.has_key(techID): return tech if tech.fullInfo: return tech # player can research this technology canResearch = 1 if player.race not in tech.researchRaces: canResearch = 0 for tmpTechID, improvement in tech.researchRequires: if not player.techs.has_key(tmpTechID) or player.techs[tmpTechID] < improvement: canResearch = 0 break for stratRes in tech.researchReqSRes: if player.stratRes.get(stratRes, 0) < 1: canResearch = 0 break for tmpTechID in player.techs: if techID in Rules.techs[tmpTechID].researchDisables: canResearch = 0 break if tech.level > player.techLevel: canResearch = 0 if canResearch: result = IDataHolder() result.partialData = None for attr in [ "name", "isDiscovery", "isStructure", "isProject", "isShipEquip", "isShipHull", "researchMod", "researchTurns", "textPreRsrch", "researchRequires", "subtype", "researchReqSRes", "researchDisables", "level", "researchRaces", ]: setattr(result, attr, getattr(tech, attr)) return result # player should know only basic params about tech result = IDataHolder() result.partialData = None for attr in ["name", "researchRequires", "subtype", "level", "researchRaces"]: setattr(result, attr, getattr(tech, attr)) return result
def forceAllyWithEDEN(self, tran, obj): for partyID in obj.diplomacyRels.keys(): party = tran.db.get(partyID, None) if party.type == T_AIEDENPLAYER: diplSelf = obj.diplomacyRels.get(party.oid, None) log.debug("Allying Pirate with EDEN (forced)", obj.oid, partyID) diplEDEN = IDataHolder() diplEDEN.type = T_DIPLREL diplEDEN.pacts = { PACT_ALLOW_CIVILIAN_SHIPS: [PACT_ACTIVE, PACT_ALLOW_CIVILIAN_SHIPS], PACT_ALLOW_MILITARY_SHIPS: [PACT_ACTIVE, PACT_ALLOW_MILITARY_SHIPS] } diplEDEN.relation = REL_FRIENDLY diplEDEN.relChng = 0 diplEDEN.lastContact = tran.db[OID_UNIVERSE].turn diplEDEN.contactType = CONTACT_STATIC diplEDEN.stats = None diplSelf.relation = REL_FRIENDLY diplSelf.pacts = { PACT_ALLOW_CIVILIAN_SHIPS: [PACT_ACTIVE, PACT_ALLOW_CIVILIAN_SHIPS], PACT_ALLOW_MILITARY_SHIPS: [PACT_ACTIVE, PACT_ALLOW_MILITARY_SHIPS] } obj.diplomacyRels[party.oid] = diplSelf party.diplomacyRels[obj.oid] = diplEDEN
def forceAllyWithEDEN(self,tran,obj): for partyID in obj.diplomacyRels.keys(): party = tran.db.get(partyID, None) if party.type == T_AIEDENPLAYER: diplSelf = obj.diplomacyRels.get(party.oid, None) log.debug("Allying Pirate with EDEN (forced)", obj.oid, partyID) diplEDEN = IDataHolder() diplEDEN.type = T_DIPLREL diplEDEN.pacts = { PACT_ALLOW_CIVILIAN_SHIPS: [PACT_ACTIVE, PACT_ALLOW_CIVILIAN_SHIPS], PACT_ALLOW_MILITARY_SHIPS: [PACT_ACTIVE, PACT_ALLOW_MILITARY_SHIPS] } diplEDEN.relation = REL_FRIENDLY diplEDEN.relChng = 0 diplEDEN.lastContact = tran.db[OID_UNIVERSE].turn diplEDEN.contactType = CONTACT_STATIC diplEDEN.stats = None diplSelf.relation = REL_FRIENDLY diplSelf.pacts = { PACT_ALLOW_CIVILIAN_SHIPS: [PACT_ACTIVE, PACT_ALLOW_CIVILIAN_SHIPS], PACT_ALLOW_MILITARY_SHIPS: [PACT_ACTIVE, PACT_ALLOW_MILITARY_SHIPS] } obj.diplomacyRels[party.oid] = diplSelf party.diplomacyRels[obj.oid] = diplEDEN
def getDiplomacyWith(self, tran, obj, playerID): # this AI battles with overyone # make default dipl = IDataHolder() dipl.type = Const.T_DIPLREL dipl.pacts = {} if obj.oid == playerID: dipl.relation = Const.REL_UNITY else: dipl.relation = Const.REL_ENEMY dipl.relChng = 0 dipl.lastContact = tran.db[Const.OID_UNIVERSE].turn dipl.contactType = Const.CONTACT_NONE dipl.stats = None return dipl
def init(self, obj): IObject.init(self, obj) # obj.name = "" obj.owner = Const.OID_NONE obj.x = 0.0 obj.y = 0.0 obj.radius = 0.0 obj.centerWeight = 250.0 obj.systems = [] obj.startingPos = [] obj.numOfStartPos = 0 obj.timeEnabled = None # none instead of False, to know when first enablement is happening obj.timePaused = False # this is only used for player-initiated pause, prevents autoenablement obj.creationTurn = 0 obj.imperator = Const.OID_NONE obj.description = "" obj.scenario = Const.SCENARIO_NONE obj.scenarioData = IDataHolder() # electromagnetic radiation obj.emrLevel = 1.0 obj.emrTrend = 1.0 obj.emrTime = 0 # galaxy keeps track of it's own time as well (because of pauses) obj.galaxyTurn = 0
def answer(self, player): answer = IDataHolder() answer.bookings = len(self.players) answer.last_creation = self.last_creation answer.is_booked = player in self.players answer.owner_nick = self.owner_nick answer.gal_type = self.gal_type answer.capacity = self.capacity return answer
def getIntroInfo(self, tran, obj): result = IDataHolder() result.cid = tran.cid result.turn = obj.turn result.serverTime = time.time() result.lastClientVersion = ClientVersion.version result.lastClientRevision = ClientVersion.revision result.rulesetName = Rules.rulesetName return result
def getDiplomacyWith(self, tran, obj, playerID): if obj.oid == playerID: return REL_UNITY # renegade battles with overyone # make default dipl = IDataHolder() dipl.type = T_DIPLREL dipl.pacts = {} dipl.relation = REL_ENEMY dipl.relChng = 0 dipl.lastContact = tran.db[OID_UNIVERSE].turn dipl.contactType = CONTACT_NONE dipl.stats = None return dipl
def getDiplomacyWith(self, tran, obj, playerID): # this AI battles with overyone # make default dipl = IDataHolder() dipl.type = T_DIPLREL dipl.pacts = {} if obj.oid == playerID: dipl.relation = REL_UNITY else: dipl.relation = REL_ENEMY dipl.relChng = 0 dipl.lastContact = tran.db[OID_UNIVERSE].turn dipl.contactType = CONTACT_NONE dipl.stats = None return dipl
def init(self, obj): IObject.init(self, obj) # obj.login = u'' obj.fullName = u'' # obj.buoys = {} obj.alliedBuoys = {} obj.planets = [] obj.fleets = [] obj.techs = {} # techs and their sublevel obj.rsrchQueue = [] obj.sciPoints = 0 obj.effSciPoints = 0 obj.techLevel = 1 obj.shipDesigns = {} obj.race = "H" # race Bionic, Human, Cyborg # bonuses obj.prodEff = 1.0 obj.sciEff = 1.0 # obj.govPwr = 0 obj.govPwrCtrlRange = 1 # fleet support obj.fleetUpgradePool = 0.0 obj.fleetUpgradeInProgress = 0 # production obj.prodIncreasePool = 0.0 # diplomacy obj.diplomacyRels = {} obj.defaultRelation = Rules.defaultRelation obj.voteFor = OID_NONE obj.governorOf = OID_NONE obj.governors = [] obj.alliance = OID_NONE obj.imperator = 0 # combat # anti-small, anti-medium, anti-large, shield generator obj.planetWeapons = [None, None, None, None, None] # obj.staticMap = {} obj.dynamicMap = {} obj.galaxies = [] obj.validSystems = [] # obj.stats = IDataHolder() obj.stats.type = T_STATS obj.timeEnabled = 0 obj.stratRes = {} obj.lastLogin = 0.0 # obj.shipRedirections = {} obj.buoys = {} # obj.clientStats = {}
def newStructure(tran, techID, playerID, status=STRUCT_STATUS_ON | STRUCT_STATUS_NEW): tech = Rules.techs[techID] s = IDataHolder() s = [ techID, int(tech.maxHP * getTechEff(tran, techID, playerID)), status, 0 ] return s
def getIntroInfo(self, tran, obj): result = IDataHolder() result.cid = tran.cid result.turn = obj.turn result.serverTime = time.time() result.version = ige.version.version return result
def getDiplomacyWith(contactID): obj = getPlayer() dipl = obj.diplomacyRels.get(contactID, None) if not dipl: # make default dipl = IDataHolder() dipl.type = T_DIPLREL dipl.pacts = { PACT_ALLOW_CIVILIAN_SHIPS: [PACT_ACTIVE, PACT_ALLOW_CIVILIAN_SHIPS] } dipl.relation = obj.defaultRelation dipl.relChng = 0 dipl.lastContact = 0 dipl.stats = None dipl.contactType = CONTACT_NONE obj.diplomacyRels[playerID] = dipl return dipl
def getDiplomacyWith(contactID): obj = getPlayer() dipl = obj.diplomacyRels.get(contactID, None) if not dipl: # make default dipl = IDataHolder() dipl.type = T_DIPLREL dipl.pacts = {PACT_ALLOW_CIVILIAN_SHIPS: [PACT_ACTIVE, PACT_ALLOW_CIVILIAN_SHIPS]} dipl.relation = obj.defaultRelation dipl.relChng = 0 dipl.lastContact = 0 dipl.stats = None dipl.contactType = CONTACT_NONE obj.diplomacyRels[playerID] = dipl return dipl
def newStructure(tran, techID, playerID, status=Const.STRUCT_STATUS_ON | Const.STRUCT_STATUS_NEW, hpRatio=None): tech = Rules.techs[techID] hp = int(tech.maxHP * getTechEff(tran, techID, playerID)) if hpRatio is None: # default is used hpRatio = Rules.structDefaultHpRatio hp = int(hp * hpRatio) s = IDataHolder() s = [techID, hp, status, 0] return s
def getIntroInfo(self, tran, obj): result = IDataHolder() result.cid = tran.cid result.turn = obj.turn result.serverTime = time.time() result.version = ige.version.version # legacy client side update support # TODO: Remove once not needed result.lastClientVersion = ( ige.version.major, ige.version.minor, ige.version.revision, ige.version.status, ) result.lastClientRevision = ige.version.svnRevision return result
def getDiplomacyWith(self, tran, obj, playerID): if obj.governorOf: # player is a governor leader = tran.db[obj.governorOf] return self.cmd(leader).getDiplomacyWith(tran, leader, objID) # player is independent dipl = obj.diplomacyRels.get(playerID, None) if not dipl: # make default dipl = IDataHolder() dipl.type = T_DIPLREL dipl.pacts = { PACT_ALLOW_CIVILIAN_SHIPS: [PACT_ACTIVE, PACT_ALLOW_CIVILIAN_SHIPS] } dipl.relation = obj.defaultRelation dipl.relChng = 0 dipl.lastContact = tran.db[OID_UNIVERSE].turn dipl.contactType = CONTACT_NONE dipl.stats = None if playerID != obj.oid: obj.diplomacyRels[playerID] = dipl else: log.debug("getDiplomacyWith myself", obj.oid) return dipl
def getTechInfo(techID): player = db[db.playerID] tech = Rules.techs[techID] # player possess this technology if player.techs.has_key(techID): return tech if tech.fullInfo: return tech # player can research this technology canResearch = 1 if player.race not in tech.researchRaces: canResearch = 0 for tmpTechID, improvement in tech.researchRequires: if not player.techs.has_key( tmpTechID) or player.techs[tmpTechID] < improvement: canResearch = 0 break for stratRes in tech.researchReqSRes: if player.stratRes.get(stratRes, 0) < 1: canResearch = 0 break for tmpTechID in player.techs: if techID in Rules.techs[tmpTechID].researchDisables: canResearch = 0 break if tech.level > player.techLevel: canResearch = 0 if canResearch: result = IDataHolder() result.partialData = None for attr in [ 'name', 'isDiscovery', 'isStructure', 'isProject', 'isShipEquip', 'isShipHull', 'researchMod', 'researchTurns', 'textPreRsrch', 'researchRequires', 'subtype', "researchReqSRes", "researchDisables", "level", "researchRaces" ]: setattr(result, attr, getattr(tech, attr)) return result # player should know only basic params about tech result = IDataHolder() result.partialData = None for attr in [ "name", "researchRequires", "subtype", "level", "researchRaces" ]: setattr(result, attr, getattr(tech, attr)) return result
def startResearch(self, tran, obj, techID, improveToMax = 0): if len(obj.rsrchQueue) > Rules.maxRsrchQueueLen: GameException('Queue is full.') tech = Rules.techs[techID] # player has to be a right race if obj.race not in tech.researchRaces: raise GameException("Your race cannot research this technology.") # item cannot be researched twice for tmpTech in obj.rsrchQueue: if tmpTech.techID == techID: raise GameException('Technology is already sheduled for research.') # disabled? for tmpTechID in obj.techs: if techID in Rules.techs[tmpTechID].researchDisables: raise GameException("Previous research has disabled this technology.") # check requirements for tmpTechID, improvement in tech.researchRequires: if not obj.techs.has_key(tmpTechID) or obj.techs[tmpTechID] < improvement: raise GameException('You cannot research this technology yet.') improvement = obj.techs.get(techID, Rules.techBaseImprovement - 1) + 1 if improvement > Rules.techMaxImprovement or improvement > tech.maxImprovement: raise GameException('You cannot improve this technology further.') if tech.level > obj.techLevel: raise GameException("Your technological level is insufficient.") # check strategic resources if improvement == 1: for stratRes in tech.researchReqSRes: if obj.stratRes.get(stratRes, 0) < 1: raise GameException("Required strategy resource missing.") item = IDataHolder() item.techID = techID item.improvement = improvement item.currSci = 0 item.changeSci = 0 item.improveToMax = improveToMax item.type = T_RESTASK obj.rsrchQueue.append(item) return obj.rsrchQueue
def startGlobalConstruction(self, tran, player, techID, quantity, isShip, reportFinished, queue): if len(player.prodQueues) <= queue: raise GameException('Invalid queue.') if len(player.prodQueues[queue]) > Rules.maxProdQueueLen: raise GameException('Queue is full.') if quantity < 1: raise GameException("Quantity must be greater than 0") if not player.techs.has_key(techID) and isShip == 0: raise GameException('You do not own this kind of technology.') if not player.shipDesigns.has_key(techID) and isShip == 1: raise GameException('You do not own this ship design.') if isShip: tech = player.shipDesigns[techID] if tech.upgradeTo: raise GameException("You cannot build obsolete ship design.") else: tech = Rules.techs[techID] if tech.isStructure or not tech.isProject: raise GameException('You cannot construct this technology.') elif tech.globalDisabled: raise GameException('You cannot construct targeted project.') neededSR = {} for sr in tech.buildSRes: if player.stratRes.get(sr, 0) < neededSR.get(sr, 0) + quantity: raise GameException("You do not own required strategic resource(s)") neededSR[sr] = neededSR.get(sr, 0) + quantity # consume strategic resources for sr in neededSR: player.stratRes[sr] -= neededSR[sr] # start construction item = IDataHolder() item.techID = techID item.quantity = int(quantity) item.changePerc = 0 item.isShip = bool(isShip) item.reportFin = bool(reportFinished) item.type = T_TASK player.prodQueues[queue].append(item) return player.prodQueues[queue], player.stratRes
def getScanInfos(self, tran, obj, scanPwr, player): if scanPwr >= Rules.level1InfoScanPwr: result = IDataHolder() result._type = T_SCAN result.scanPwr = scanPwr result.oid = obj.oid result.signature = obj.signature result.type = obj.type result.orbit = obj.orbit result.compOf = obj.compOf result.x = obj.x result.y = obj.y result.plType = obj.plType if scanPwr >= Rules.level2InfoScanPwr: result.plDiameter = obj.plDiameter if getattr(obj, "plType", 'X') != 'G': result.plMin = obj.plMin result.plBio = obj.plBio result.plEn = obj.plEn result.plSlots = obj.plSlots result.plStratRes = obj.plStratRes result.plMaxSlots = obj.plMaxSlots if scanPwr >= Rules.level3InfoScanPwr: result.name = obj.name result.storPop = obj.storPop result.owner = obj.owner if scanPwr >= Rules.level4InfoScanPwr: # TODO provide less information result.hasRefuel = (obj.refuelInc > 0) #simple detect if docks exist for problems dialog result.slots = obj.slots result.shield = obj.shield result.prevShield = -1 result.maxShield = -1 if scanPwr >= Rules.partnerScanPwr: result.maxShield = obj.maxShield result.prevShield = obj.prevShield result.refuelMax = obj.refuelMax result.refuelInc = obj.refuelInc result.scannerPwr = obj.scannerPwr result.trainShipInc = obj.trainShipInc result.trainShipMax = obj.trainShipMax result.upgradeShip = obj.upgradeShip result.repairShip = obj.repairShip result.fleetSpeedBoost = obj.fleetSpeedBoost return [result]
def getScanInfos(self, tran, obj, scanPwr, player): result = IDataHolder() results = [result] if scanPwr >= Rules.level1InfoScanPwr: result._type = T_SCAN result.scanPwr = scanPwr result.oid = obj.oid result.x = obj.x result.y = obj.y if hasattr(obj, 'destinationOid'): result.destinationOid = obj.destinationOid # multiply by 1000 to increase accuracy #~ result.dist = obj.dist * 1000 #~ result.dAngle = obj.dAngle * 1000 #~ result.sAngle = obj.sAngle * 1000 result.signature = obj.signature result.type = obj.type result.compOf = obj.compOf result.starClass = obj.starClass if scanPwr >= Rules.level2InfoScanPwr: result.name = obj.name result.combatCounter = obj.combatCounter if scanPwr >= Rules.level3InfoScanPwr: result.planets = obj.planets result.owner = obj.owner for planetID in obj.planets: planet = tran.db[planetID] if planet.owner == player: ####### This was player.owner, which made no sense. Hope this change doesn't break something continue newPwr = scanPwr * planet.signature / obj.signature results.extend( self.cmd(planet).getScanInfos(tran, planet, newPwr, player)) if scanPwr >= Rules.level4InfoScanPwr: result.fleets = obj.fleets for fleetID in obj.fleets: fleet = tran.db[fleetID] if fleet.owner == player: continue newPwr = scanPwr * fleet.signature / obj.signature results.extend( self.cmd(fleet).getScanInfos(tran, fleet, newPwr, player)) result.hasmines = 0 #no if len(obj.minefield) > 0: result.hasmines = 1 #yes result.minefield = self.getMines( obj, player.oid) #only shows mines you own if len(obj.minefield) > 1 or (len(obj.minefield) == 1 and len(result.minefield) == 0): result.hasmines = 2 #yes, and some aren't my mines return results
def processBATTLEPhase(self, tran, obj, data): system = obj #@log.debug('ISystem', 'BATTLE - system', obj.oid) # we are processing fleets, planets, ... objects = obj.planets[:] + obj.fleets[:] # shuffle them to prevent predetermined one-sided battles (temporary hack) random.shuffle(objects) # store owners of objects # find enemies and allies attack = {} allies = {} owners = {} ownerIDs = {} systemAtt = {} systemDef = {} hasMine = {} isOwnedObject = 0 for objID in objects: attack[objID] = [] allies[objID] = [] owner = tran.db[objID].owner owners[objID] = owner ownerIDs[owner] = owner if owner != Const.OID_NONE: isOwnedObject = 1 for owner in ownerIDs: tempAtt, tempDef = self.getSystemCombatBonuses(tran, system, owner) systemAtt[owner] = tempAtt systemDef[owner] = tempDef hasMine[owner] = self.getSystemMineSource(tran, system, owner) if not isOwnedObject: #@log.debug('ISystem', 'No combat') # reset combat counters system.combatCounter = 0 return # first - direct ones index = 1 for obj1ID in objects: obj1 = tran.db[obj1ID] if obj1.owner == Const.OID_NONE: index += 1 continue commander = tran.db[obj1.owner] # relationships #for obj2ID in objects[index:]: for obj2ID in objects: obj2 = tran.db[obj2ID] if obj2.owner == Const.OID_NONE or obj1 is obj2: continue if obj1.owner == obj2.owner: allies[obj1ID].append(obj2ID) allies[obj2ID].append(obj1ID) continue # planet and military object elif obj1.type == Const.T_PLANET and obj2.isMilitary and \ not self.cmd(commander).isPactActive(tran, commander, obj2.owner, Const.PACT_ALLOW_MILITARY_SHIPS): #@log.debug("ISystem pl - mil", obj1ID, obj2ID) if obj2ID not in attack[obj1ID]: attack[obj1ID].append(obj2ID) if obj1ID not in attack[obj2ID]: attack[obj2ID].append(obj1ID) # planet and civilian object elif obj1.type == Const.T_PLANET and not obj2.isMilitary and \ not self.cmd(commander).isPactActive(tran, commander, obj2.owner, Const.PACT_ALLOW_CIVILIAN_SHIPS): #@log.debug("ISystem pl - civ", obj1ID, obj2ID) if obj2ID not in attack[obj1ID]: attack[obj1ID].append(obj2ID) if obj1ID not in attack[obj2ID]: attack[obj2ID].append(obj1ID) # military and military object elif obj1.isMilitary and obj2.isMilitary and \ not self.cmd(commander).isPactActive(tran, commander, obj2.owner, Const.PACT_ALLOW_MILITARY_SHIPS): #@log.debug("ISystem mil - mil", obj1ID, obj2ID) if obj2ID not in attack[obj1ID]: attack[obj1ID].append(obj2ID) if obj1ID not in attack[obj2ID]: attack[obj2ID].append(obj1ID) # military and civilian object elif obj1.isMilitary and not obj2.isMilitary and \ not self.cmd(commander).isPactActive(tran, commander, obj2.owner, Const.PACT_ALLOW_CIVILIAN_SHIPS): #@log.debug("ISystem mil - civ", obj1ID, obj2ID) if obj2ID not in attack[obj1ID]: attack[obj1ID].append(obj2ID) if obj1ID not in attack[obj2ID]: attack[obj2ID].append(obj1ID) # planet and fleet #elif obj1.type == Const.T_PLANET and obj2.type == Const.T_FLEET and \ # self.cmd(commander).isPactActive(tran, commander, obj2.owner, PACT_MUTUAL_DEFENCE): # allies[obj1ID].append(obj2ID) # allies[obj2ID].append(obj1ID) # fleet and fleet #elif obj1.type == Const.T_FLEET and obj2.type == Const.T_FLEET and \ # self.cmd(commander).isPactActive(tran, commander, obj2.owner, PACT_MUTUAL_OFFENCE): # allies[obj1ID].append(obj2ID) # allies[obj2ID].append(obj1ID) index += 1 #@log.debug('ISystem', 'Targets:', targets) #@log.debug('ISystem', 'Allies:', allies) # find indirect a/e #for objID in objects: # iTargets = [] # iAllies = [] # # find indirect a/e # todo = allies[objID][:] # while todo: # id = todo.pop(0) # iTargets.extend(targets[id]) # for tmpID in allies[id]: # if tmpID not in iAllies: # todo.append(tmpID) # iAllies.append(tmpID) # # remove allies from targets # for id in iAllies: # if id in iTargets: # iTargets.remove(id) # # IMPORTATNT preffer NOT to fire at possible allies # # add my targets # #for id in targets[objID]: # # if id not in iTargets: # # iTargets.append(id) # # that's all folks # for id in iTargets: # if objID not in attack[id]: # attack[id].append(objID) # if id not in attack[objID]: # attack[objID].append(id) # NOT VALID: objects with action ACTION_ATTACK will attack only their targets # check, if there are any targets isCombat = 0 for objID in objects: if attack[objID]: isCombat = 1 break #end loop if not isCombat: #@log.debug('ISystem', 'No combat') # reset combat counters system.combatCounter = 0 for fleetID in system.fleets: tran.db[fleetID].combatCounter = 0 return # increase combat counters system.combatCounter += 1 for fleetID in system.fleets: tran.db[fleetID].combatCounter += 1 # debug log.debug('ISystem', 'Final attacks in system %d:' % system.oid, attack) # mines detonate before battle shots = {} targets = {} firing = {} damageCaused = {} killsCaused = {} damageTaken = {} shipsLost = {} minesTriggered = {} fleetOwners = {} isCombat = False isMineCombat = False for owner in ownerIDs: if owner not in hasMine: # no planets continue if not hasMine[owner]: # no planet with control structure continue controlPlanetID = hasMine[owner][ 0] # there is list returned, all planets have same effect if len(self.getMines(system, owner)) == 0: continue # no mines, something broke if len(attack[controlPlanetID]) == 0: continue # no targets isMineFired = True mineTargets = copy.copy(attack[controlPlanetID]) while isMineFired: while len(mineTargets) > 0: targetID = random.choice( mineTargets) # select random target targetobj = tran.db.get(targetID, None) try: if targetobj.type == Const.T_FLEET: fleetOwners[targetID] = targetobj.owner break # target found mineTargets.remove( targetID ) # remove an object type that a mine can't hit from the temporary targets list except: mineTargets.remove( targetID ) # remove a dead fleet from the temporary targets list if len(mineTargets) == 0: break # no fleet targets for mines temp, temp, firing[targetID] = self.cmd( targetobj).getPreCombatData( tran, targetobj) # fix firing for "surrender to" section damage, att, ignoreshield, mineID = self.cmd(obj).fireMine( system, owner) if not damage: # no more mines isMineFired = False break log.debug('ISystem', 'Mine Shooting (damage, att, ignore shield):', damage, att, ignoreshield) isMineCombat = True minesTriggered[mineID] = minesTriggered.get(mineID, 0) + 1 # Process Combat # for now we assume only one ship can be destroyed by one mine dmg, destroyed = self.cmd(targetobj).applyMine( tran, targetobj, att, damage, ignoreshield) #log.debug('ISystem-Mines', 'Actual Damage Done:',dmg) if dmg > 0: damageTaken[targetID] = damageTaken.get(targetID, 0) + dmg shipsLost[targetID] = shipsLost.get(targetID, 0) + destroyed killsCaused[mineID] = killsCaused.get(mineID, 0) + destroyed if dmg > 0: damageCaused[mineID] = damageCaused.get(mineID, 0) + dmg # send messages about mine effects to the owner of the minefield # collect hit players players = {} for triggerID in firing.keys(): players[owners[triggerID]] = None controllerPlanet = tran.db.get(controlPlanetID, None) damageCausedSum = 0 killsCausedSum = 0 for mineID in damageCaused.keys(): damageCausedSum = damageCausedSum + damageCaused.get(mineID, 0) killsCausedSum = killsCausedSum + killsCaused.get(mineID, 0) Utils.sendMessage(tran, controllerPlanet, Const.MSG_MINES_OWNER_RESULTS, system.oid, (players.keys(), (damageCaused, killsCaused, minesTriggered), damageCausedSum, killsCausedSum)) # send messages to the players whose fleets got hit by minefields for targetID in damageTaken.keys(): targetFleet = tran.db.get(targetID, None) if targetFleet: Utils.sendMessage(tran, targetFleet, Const.MSG_MINES_FLEET_RESULTS, system.oid, (damageTaken[targetID], shipsLost[targetID])) else: targetFleet = IDataHolder() targetFleet.oid = fleetOwners[targetID] Utils.sendMessage(tran, targetFleet, Const.MSG_MINES_FLEET_RESULTS, system.oid, (damageTaken[targetID], shipsLost[targetID])) Utils.sendMessage(tran, targetFleet, Const.MSG_DESTROYED_FLEET, system.oid, ()) damageCaused = {} killsCaused = {} damageTaken = {} shipsLost = {} # now to battle for objID in objects: obj = tran.db.get(objID, None) # get shots from object, should be sorted by weaponClass # shots = [ shot, ...], shot = (combatAtt, weaponID) # get target classes and numbers # (class1, class2, class3, class4) # cls0 == fighters, cls1 == midships, cls2 == capital ships, cls3 == planet installations #@log.debug(objID, obj.name, "getting pre combat data") if obj: # source already destroyed; ignore shots[objID], targets[objID], firing[objID] = self.cmd( obj).getPreCombatData(tran, obj) if firing[objID]: isCombat = True if not isCombat and not isMineCombat: # no shots has been fired #@log.debug('ISystem', 'No combat') # reset combat counters system.combatCounter = 0 for fleetID in system.fleets: tran.db[fleetID].combatCounter = 0 return #@log.debug("Shots:", shots) #@log.debug("Targets", targets) if isCombat: for shotIdx in (3, 2, 1, 0): for objID in objects: # obj CAN be deleted at this point obj = tran.db.get(objID, None) if obj == None: continue # source already destroyed; move to next source # if object is fleet, then it's signature is max if obj and obj.type == Const.T_FLEET: obj.signature = Rules.maxSignature # target preselection totalClass = [0, 0, 0, 0] total = 0 for targetID in attack[objID]: totalClass[0] += targets[targetID][0] totalClass[1] += targets[targetID][1] totalClass[2] += targets[targetID][2] totalClass[3] += targets[targetID][3] total = totalClass[0] + totalClass[1] + totalClass[ 2] + totalClass[3] # process shots for combatAtt, weaponID in shots[objID][shotIdx]: weapon = Rules.techs[weaponID] weaponClass = weapon.weaponClass if total == 0: # there are no targets break #@log.debug('ISystem', 'Processing shot', objID, weapon.name, weaponClass) # process from weaponClass up # never shoot on smaller ships than weaponClass applied = 0 for tmpWpnClass in xrange(weaponClass, 4): #@log.debug('ISystem', 'Trying target class', tmpWpnClass, totalClass[tmpWpnClass]) # select target if totalClass[tmpWpnClass]: target = Utils.rand(0, totalClass[tmpWpnClass]) #@log.debug('ISystem', 'Target rnd num', target, totalClass[tmpWpnClass]) for targetID in attack[objID]: if target < targets[targetID][tmpWpnClass]: #@log.debug(objID, 'attacks', targetID, tmpWpnClass) # targetID can be deleted at this point anObj = tran.db.get(targetID, None) if anObj: dmg, destroyed, destroyedClass = self.cmd( anObj).applyShot( tran, anObj, systemDef[ owners[targetID]], combatAtt + systemAtt[owners[objID]], weaponID, tmpWpnClass, target) #@log.debug("ISystem result", dmg, destroyed, destroyedClass, tmpWpnClass) #@print objID, 'dmg, destroyed', dmg, destroyed damageTaken[ targetID] = damageTaken.get( targetID, 0) + dmg if destroyed > 0: shipsLost[ targetID] = shipsLost.get( targetID, 0) + destroyed total -= destroyed totalClass[ destroyedClass] -= destroyed if dmg > 0 and obj: obj.combatExp += dmg damageCaused[ objID] = damageCaused.get( objID, 0) + dmg applied = 1 else: continue # target already destroyed, move to next target break else: #@log.debug('ISystem', 'Lovering target by', targets[targetID][tmpWpnClass]) target -= targets[targetID][ tmpWpnClass] if applied: break # send messages and modify diplomacy relations # distribute experience pts for objID in objects: obj = tran.db.get(objID, None) if obj: self.cmd(obj).distributeExp(tran, obj) if attack[objID]: source = obj or tran.db[owners[objID]] # collect players players = {} for attackerID in attack[objID]: players[owners[attackerID]] = None d1 = damageTaken.get(objID, 0) d2 = damageCaused.get(objID, 0) l = shipsLost.get(objID, 0) if d1 or d2 or l: # send only if damage is taken/caused Utils.sendMessage(tran, source, Const.MSG_COMBAT_RESULTS, system.oid, (d1, d2, l, players.keys())) if not obj: # report DESTROYED status Utils.sendMessage(tran, source, Const.MSG_DESTROYED_FLEET, system.oid, ()) # modify diplomacy relations objOwner = tran.db[owners[objID]] for attackerID in attack[objID]: attOwner = tran.db.get(owners[attackerID], None) # owner of the fleet rel = self.cmd(objOwner).getDiplomacyWith( tran, objOwner, attOwner.oid) rel.relChng = Rules.relLostWhenAttacked # attacker rel = self.cmd(attOwner).getDiplomacyWith( tran, attOwner, objOwner.oid) rel.rechChng = Rules.relLostWhenAttacked # check if object surrenders for objID in objects: # object surrender IFF it and its allies had target and was not able # to fire at it, planet is not counted as ally in this case obj = tran.db.get(objID, None) if firing[objID] and obj: continue surrenderTo = [] for attID in attack[objID]: if firing[attID] and tran.db.has_key(attID): surrenderTo.append(tran.db[attID].owner) for allyID in allies[objID]: if not tran.db.has_key(allyID): continue ally = tran.db[allyID] if firing[allyID] and ally.type != Const.T_PLANET: surrenderTo = [] break if surrenderTo: index = Utils.rand(0, len(surrenderTo)) if obj: if self.cmd(obj).surrenderTo(tran, obj, surrenderTo[index]): winner = tran.db[surrenderTo[index]] source = tran.db.get(owners[objID], None) log.debug('ISystem', 'BATTLE - surrender', objID, surrenderTo[index], surrenderTo) if source: Utils.sendMessage(tran, source, Const.MSG_COMBAT_LOST, system.oid, winner.oid) Utils.sendMessage(tran, winner, Const.MSG_COMBAT_WON, system.oid, source.oid) else: Utils.sendMessage(tran, winner, Const.MSG_COMBAT_WON, system.oid, obj.oid) else: winner = tran.db[surrenderTo[index]] source = tran.db[owners[objID]] log.debug('ISystem', 'BATTLE - surrender', objID, surrenderTo[index], surrenderTo) Utils.sendMessage(tran, source, Const.MSG_COMBAT_LOST, system.oid, winner.oid) Utils.sendMessage(tran, winner, Const.MSG_COMBAT_WON, system.oid, source.oid) return
def processRSRCHPhase(self, tran, obj, data): if not obj.timeEnabled: return # sci pts from allies pts = obj.sciPoints for partnerID in obj.diplomacyRels: if self.cmd(obj).isPactActive(tran, obj, partnerID, PACT_MINOR_SCI_COOP): partner = tran.db[partnerID] pactSpec = Rules.pactDescrs[PACT_MINOR_SCI_COOP] pts += min( int(partner.sciPoints * pactSpec.effectivity), int(obj.sciPoints * pactSpec.effectivity), ) if self.cmd(obj).isPactActive(tran, obj, partnerID, PACT_MAJOR_SCI_COOP): partner = tran.db[partnerID] pactSpec = Rules.pactDescrs[PACT_MAJOR_SCI_COOP] pts += min( int(partner.sciPoints * pactSpec.effectivity), int(obj.sciPoints * pactSpec.effectivity), ) # compute effective sci pts obj.effSciPoints = epts = pts - int(obj.stats.storPop * Rules.sciPtsPerCitizen[obj.techLevel]) index = 0 while epts > 0 and obj.rsrchQueue and index < len(obj.rsrchQueue): item = obj.rsrchQueue[index] tech = Rules.techs[item.techID] # check requirements canResearch = 1 # player has to be a right race if obj.race not in tech.researchRaces: canResearch = 0 for stratRes in tech.researchReqSRes: if obj.stratRes.get(stratRes, 0) < 1 and item.improvement == 1: Utils.sendMessage(tran, obj, MSG_MISSING_STRATRES, OID_NONE, stratRes) canResearch = 0 break for tmpTechID in obj.techs: if item.techID in Rules.techs[tmpTechID].researchDisables: canResearch = 0 Utils.sendMessage(tran, obj, MSG_DELETED_RESEARCH, OID_NONE, item.techID) del obj.rsrchQueue[index] index -= 1 break if tech.level > obj.techLevel: canResearch = 0 Utils.sendMessage(tran, obj, MSG_DELETED_RESEARCH, OID_NONE, item.techID) del obj.rsrchQueue[index] index -= 1 if not canResearch: index += 1 continue researchSci = Utils.getTechRCost(obj, item.techID) wantSci = min(epts, researchSci - item.currSci, researchSci / tech.researchTurns) item.currSci += wantSci item.changeSci = wantSci epts -= wantSci if item.currSci >= researchSci: del obj.rsrchQueue[index] obj.techs[item.techID] = item.improvement # call finish handler tech = Rules.techs[item.techID] tech.finishResearchHandler(tran, obj, tech) Utils.sendMessage(tran, obj, MSG_COMPLETED_RESEARCH, OID_NONE, item.techID) # update derived attributes of player self.cmd(obj).update(tran, obj) # repeat research if required by player if item.improveToMax == 1 and item.improvement < Rules.techMaxImprovement: # reinsert the item on the top of the queue self.cmd(obj).startResearch(tran, obj, item.techID, improveToMax = 1) idx = len(obj.rsrchQueue) - 1 self.cmd(obj).moveResearch(tran, obj, idx, - idx) if epts > 0 and 0: # TODO: remove me Utils.sendMessage(tran, obj, MSG_WASTED_SCIPTS, OID_NONE, epts) return # oops we have negative epts while epts < 0: log.debug("Not enought RP", epts, obj.oid) if obj.rsrchQueue: item = obj.rsrchQueue[0] if item.currSci > 0: wantSci = min(item.currSci, - epts) item.currSci -= wantSci item.changeSci = - wantSci epts += wantSci if item.currSci == 0: # remove item from the queue - TODO send message to player del obj.rsrchQueue[0] # at this point, epts can be zero if epts == 0: log.debug("RP deficit satisfied", obj.oid) break # try next project if obj.rsrchQueue: continue # oops we must find technology to degrade avail = obj.techs.keys() # do not degrade technologies, which enables others for techID in obj.techs: tech = Rules.techs[techID] for tmpTechID, impr in tech.researchRequires: if tmpTechID in avail: avail.remove(tmpTechID) log.debug("Techs avialable for degradation", avail) if not avail: # no technology... break # from hight to low IDs avail.sort() avail.reverse() degraded = 0 for level in range(obj.techLevel, 0, -1): for techID in avail: tech = Rules.techs[techID] # check level if tech.level != level: continue # do not touch starting technologies if tech.isStarting and obj.techs[techID] <= 3: continue # ok we have one to degrade item = IDataHolder() item.techID = techID item.improvement = obj.techs[techID] item.currSci = Utils.getTechRCost(obj, techID, obj.techs[techID]) item.changeSci = 0 item.improveToMax = 0 item.type = T_RESTASK obj.rsrchQueue.append(item) # degrade tech if obj.techs[techID] == 1: # TODO send message del obj.techs[techID] else: # TODO send message obj.techs[techID] -= 1 if tech.recheckWhenTechLost: # reset some attributes plLevel = obj.techLevel obj.techLevel = 1 # recheck remaining techs for level in range(1, plLevel + 1): for techID in obj.techs: tech = Rules.techs[techID] if tech.level != level: continue # call finish handler again tech.finishResearchHandler(tran, obj, tech) degraded = 1 break if degraded: break return
def getScanInfo(self, tran, obj, scanPwr): result = IDataHolder() result._type = T_SCAN result.scanPwr = scanPwr if scanPwr > Rules.level1InfoScanPwr: result.oid = obj.oid result.x = obj.x result.y = obj.y result.oldX = obj.oldX result.oldY = obj.oldY result.signature = obj.signature result.type = obj.type result.orbiting = obj.orbiting result.speed = obj.speed result.eta = obj.eta if scanPwr > Rules.level2InfoScanPwr: result.name = obj.name if scanPwr > Rules.level3InfoScanPwr: result.asDiameter = obj.asDiameter result.asHP = obj.asHP if scanPwr > Rules.level4InfoScanPwr: pass return result
def _get_system_info(self, system): system_info = IDataHolder() # my planets in the system system_info.system = system system_info.breweries = 0 system_info.shipyards = 0 system_info.prisons = 0 system_info.dens = {} system_info.bases = {} system_info.other_struct_id = {} system_info.idle_planets = self.data.myPlanets & set(system.planets) for planet_id in copy.copy(system_info.idle_planets): planet = self.db[planet_id] system_info.bases[planet_id] = 0 system_info.other_struct_id[planet_id] = None system_info.dens[planet_id] = 0 for struct in planet.slots: if struct[0] == Rules.Tech.PIRATEBASE: system_info.bases[planet_id] += 1 elif struct[0] == Rules.Tech.PIRATEBREWERY: system_info.breweries += 1 elif struct[0] == Rules.Tech.PIRATEDEN: system_info.dens[planet_id] += 1 elif struct[0] == Rules.Tech.PIRATESD: system_info.shipyards += 1 elif struct[0] == Rules.Tech.PIRATEPRISON: system_info.prisons += 1 else: system_info.other_struct_id[planet_id] = struct[0] if getattr(planet, 'prodQueue', None): # something is in the production queue, account it and do next for task in planet.prodQueue: if task.techID == Rules.Tech.PIRATEBREWERY: system_info.breweries += task.quantity elif task.techID == Rules.Tech.PIRATESD: system_info.shipyards += task.quantity elif task.techID == Rules.Tech.PIRATEPRISON: system_info.prisons += task.quantity elif task.techID in (Rules.Tech.PLCOND5, Rules.Tech.PLASSEMBL5): self.data.nonhabPlanets.remove(task.targetID) system_info.idle_planets.remove(planet_id) continue return system_info
def makeShipFullSpec(player, name, hullID, eqIDs, improvements, raiseExs = True): if not hullID: raise GameException("Ship's hull must be specified.") hull = Rules.techs[hullID] if not hull.isShipHull: raise GameException("Ship's hull must be specified.") ship = IDataHolder() ship.type = T_SHIP # initial values techEff = Rules.techImprEff[player.techs.get(hullID, Rules.techBaseImprovement)] ship.name = name ship.hullID = hullID ship.eqIDs = eqIDs ship.level = hull.level ship.combatClass = hull.combatClass ship.improvements = improvements ship.buildProd = hull.buildProd ship.buildSRes = hull.buildSRes[:] # we need copy ship.operEn = hull.operEn ship.storEn = hull.storEn * techEff ship.weight = hull.weight ship.slots = 0 ship.signature = hull.signature ship.negsignature = 0 ship.minSignature = hull.minSignature ship.signatureCloak = 1.0 #NEW; 100% - this is the default rule ship.signatureDecloak = 1.0 #NEW; 100% - this is the default rule ship.combatAttBase = hull.combatAtt * techEff ship.combatAtt = 0 ship.combatAttMultiplier = 1.0 #NEW; 100% - this is the default rule ship.combatDefBase = hull.combatDef * techEff ship.combatDef = 0 ship.combatDefMultiplier = 1.0 #NEW; 100% - this is the default rule ship.missileDefBase = hull.missileDef * techEff ship.missileDef = 0 ship.missileDefMultiplier = 1.0 #NEW; 100% - this is the default rule ship.scannerPwr = max(hull.scannerPwr * techEff, Rules.scannerMinPwr) ship.autoRepairFix = hull.autoRepairFix ship.autoRepairPerc = hull.autoRepairPerc ship.shieldRechargeFix = hull.shieldRechargeFix ship.shieldRechargePerc = hull.shieldRechargePerc ship.hardShield = 0.0 ship.engPwr = 0 ship.upgradeTo = 0 ship.shieldHP = 0 ship.maxHP = int(hull.maxHP * techEff) ship.weaponIDs = [] ship.deployStructs = [] ship.deployHandlers = [] ship.isMilitary = 0 ship.baseExp = 0 ship.damageAbsorb = 0 combatExtra = 0 shieldPerc = 0.0 unpactStruct = 0 deployHandler = 0 currentNegWeight = 0 currentNegSlots = 0 # add equipment #negslots = {} #negweight = {} counter = {} installations = {} equipCounter = {} for techID in eqIDs: tech = Rules.techs[techID] techEff = Rules.techImprEff[player.techs.get(techID, Rules.techBaseImprovement)] # prevent count < 0; allow count == 0 for placeholders. if eqIDs[techID] < 0 and raiseExs: raise GameException("Invalid equipment count (less than 0).") for i in xrange(0, eqIDs[techID]): counter[tech.subtype] = 1 + counter.get(tech.subtype, 0) installations[techID] = 1 + installations.get(techID, 0) # check min hull req if tech.minHull > ship.combatClass and raiseExs: log.warning("Cannot add tech", techID, tech.name) raise GameException("Minimum hull requirement not satisfied.") # check max hull req #NEW if tech.maxHull < ship.combatClass and raiseExs: log.warning("Cannot add tech", techID, tech.name) raise GameException("Maximum hull requirement not satisfied.") # check maximum installations if tech.maxInstallations and installations[tech.id] > tech.maxInstallations \ and raiseExs: raise GameException("Maximum number of equipment installations exceeded.") #check maximum type installations if tech.subtype == "seq_mod" and tech.equipType in Rules.maxEquipType and raiseExs: if tech.equipType in equipCounter: equipCounter[tech.equipType] += 1 else: equipCounter[tech.equipType] = 1 log.debug(equipCounter[tech.equipType]) if equipCounter[tech.equipType] > Rules.maxEquipType[tech.equipType]: raise GameException("Maximum number of restricted type equipment installations exceeded: %s." % tech.equipType) # add values ship.level = max(ship.level, tech.level) ship.buildProd += tech.buildProd ship.buildSRes.extend(tech.buildSRes) ship.storEn += tech.storEn * techEff if (tech.weight > 0): ship.weight += tech.weight else: currentNegWeight += tech.weight #negweight[techID] = tech.weight + negweight.get(techID, 0) #this is complex for items with max installs... if (tech.slots > 0): ship.slots += tech.slots else: currentNegSlots += tech.slots #negslots[techID] = tech.slots + negslots.get(techID, 0) #this is complex for items with max installs... if tech.signature < 0 and tech.subtype == "seq_mod": ship.negsignature = min(tech.signature,ship.negsignature) else: ship.signature += tech.signature ship.minSignature = max(ship.minSignature, tech.minSignature) ship.signatureCloak = min(ship.signatureCloak, tech.signatureCloak) ship.signatureDecloak = min(ship.signatureDecloak, tech.signatureDecloak) if tech.subtype == "seq_mod": #not cumulative for equipment; pick best ship.combatAtt = max(ship.combatAtt, tech.combatAtt * techEff) ship.combatDef = max(ship.combatDef, tech.combatDef * techEff) ship.missileDef = max(ship.missileDef, tech.missileDef * techEff) else : ship.combatDefBase += tech.combatDef * techEff ship.missileDefBase += tech.missileDef * techEff ship.combatAttBase += tech.combatAtt * techEff #not cumulative; pick best ship.combatAttMultiplier = max(ship.combatAttMultiplier, (tech.combatAttPerc-1.0) * techEff + 1.0) #NEW ship.combatDefMultiplier = max(ship.combatDefMultiplier, (tech.combatDefPerc-1.0) * techEff + 1.0) #NEW ship.missileDefMultiplier = max(ship.missileDefMultiplier, (tech.missileDefPerc-1.0) * techEff + 1.0) #NEW ship.engPwr += tech.engPwr * techEff ship.maxHP += tech.maxHP * techEff shieldPerc = max(shieldPerc, tech.shieldPerc * techEff) ship.scannerPwr = max(ship.scannerPwr, tech.scannerPwr * techEff) ship.operEn += tech.operEn ship.autoRepairFix = max(ship.autoRepairFix, tech.autoRepairFix * techEff) ship.autoRepairPerc = max(ship.autoRepairPerc, tech.autoRepairPerc * techEff) ship.shieldRechargeFix = max(ship.shieldRechargeFix, tech.shieldRechargeFix * techEff) ship.shieldRechargePerc = max(ship.shieldRechargePerc, tech.shieldRechargePerc * techEff) ship.hardShield = max(ship.hardShield,tech.hardShield * techEff) ship.damageAbsorb = min(ship.damageAbsorb + tech.damageAbsorb,Rules.maxDamageAbsorb) #limit this by rule combatExtra += tech.addMP # if weapon - register only if tech.subtype == "seq_wpn": ship.weaponIDs.append(techID) ship.isMilitary = 1 weapon = Rules.techs[techID] ship.baseExp += (weapon.weaponDmgMin + weapon.weaponDmgMax) / 2 * weapon.weaponROF # deployables if tech.unpackStruct != OID_NONE: ship.deployStructs.append(tech.unpackStruct) unpactStruct = 1 if tech.deployHandlerID != OID_NONE: #this calls another tech at execute time, so only need the ID ship.deployHandlers.append(tech.deployHandlerID) deployHandler = 1 #fix limiter based attibs; round when needed #currentNegWeight = 0 #for negtech in negweight: # currentNegWeight = min(currentNegWeight,negweight[negtech]) #currentNegSlots = 0 #for negtech in negslots: # currentNegSlots = min(currentNegSlots,negslots[negtech]) ship.weight = max(ship.weight+currentNegWeight,int(hull.weight/2)) ship.slots = max(ship.slots+currentNegSlots,1) ship.combatAtt += ship.combatAttBase ship.combatDef = int((ship.combatDef + ship.combatDefBase) * ship.combatDefMultiplier) ship.missileDef = int((ship.missileDef + ship.missileDefBase) * ship.missileDefMultiplier) ship.hardShield = min(1.0,ship.hardShield) #don't allow this to be more than 100% blocking!! #add some MP for damage absorb: combatExtra += ship.damageAbsorb * 1500 #calculate final signature ship.signature += ship.negsignature ship.signature *= ship.signatureCloak * ship.signatureDecloak # check various conditions # if unpactStruct and deployHandler and raiseExs: #we don't 'need' this, so I'm leaving it disabled for now; however, we might 'want' it to prevent abuse --RC # raise GameException("Cannot have both a deployable structure and a deployable project on the same ship") if counter.get("seq_ctrl", 0) == 0 and raiseExs: raise GameException("No control module in the ship.") if counter.get("seq_ctrl", 0) > 1 and raiseExs: raise GameException("Only one control module in the ship allowed.") if ship.slots > hull.slots and raiseExs: raise GameException("Hull does not have enough slots to hold specified equipment.") if ship.weight > hull.maxWeight and raiseExs: raise GameException("Ship is too heavy.") # compute secondary paramaters ship.speed = float(ship.engPwr) / ship.weight ship.baseExp = int(ship.baseExp * Rules.shipBaseExpMod) + Rules.shipBaseExp[ship.combatClass] # compute base attack/defence ship.combatAtt += int(ship.speed) ship.combatDef += int(ship.speed) ship.missileDef += int(ship.speed / 2.0) # improvements if len(improvements) > Rules.shipMaxImprovements and raiseExs: raise GameException("Too many improvements.") for i in improvements: if i == SI_SPEED: ship.speed *= Rules.shipImprovementMod elif i == SI_TANKS: ship.storEn *= Rules.shipImprovementMod elif i == SI_ATT: ship.combatAtt *= Rules.shipImprovementMod elif i == SI_DEF: ship.combatDef *= Rules.shipImprovementMod ship.missileDef *= Rules.shipImprovementMod elif i == SI_HP: ship.maxHP *= Rules.shipImprovementMod elif i == SI_SHIELDS: ship.shieldHP *= Rules.shipImprovementMod # round values down ship.storEn = int(ship.storEn) ship.combatAtt = int(ship.combatAtt / (ship.combatClass + 1.0)) ship.combatDef = int(ship.combatDef / (ship.combatClass + 1.0)) ship.missileDef = int(ship.missileDef / (ship.combatClass + 1.0)) ship.maxHP = int(ship.maxHP) ship.shieldHP = int(ship.maxHP * shieldPerc) ship.scannerPwr = int(ship.scannerPwr) ship.engPwr = int(ship.engPwr) ship.signature = int(ship.signature) ship.baseExp = int(ship.baseExp) # compute attack power attackPwr = 0.0 refDefence = 10.0 refAttack = 10.0 refDmg = 10.0 refSpeed = 5.0 #average speed of medium and large hulls for weaponID in ship.weaponIDs: weapon = Rules.techs[weaponID] dmg = (weapon.weaponDmgMin + weapon.weaponDmgMax) / 2 * weapon.weaponROF att = int((ship.combatAtt + weapon.weaponAtt) * ship.combatAttMultiplier) #added combat multiplier # attackPwr += (att / float(att + refDefence) * dmg) attackPwr += (att / float(att + refDefence) * dmg) / (max(1,weapon.weaponClass-1)) #9/11/06 - RC; reduce power of bombs and torps in calculation # defence # ship.combatPwr = int(attackPwr * (ship.maxHP + ship.shieldHP) / (refAttack / (refAttack + ship.combatDef) * refDmg)) ship.combatPwr = int(attackPwr * (ship.maxHP + ship.shieldHP) / (refAttack / (refAttack + ship.combatDef) * refDmg) * min(1.33,max(0.5,(ship.speed / refSpeed))) + combatExtra) #9/11/06 - RC; average speed ships get most weight) # fix signature ship.signature = max(hull.minSignature, ship.signature, ship.minSignature) #removed 1 as min signature; use hulls to control that from now on; change Fleet controls to make min signature for fleet rather than ship so that we can have human stealth craft! :) # return ship
def makeShipFullSpec(player, name, hullID, eqIDs, improvements, raiseExs=True): if not hullID: raise GameException("Ship's hull must be specified.") hull = Rules.techs[hullID] if not hull.isShipHull: raise GameException("Ship's hull must be specified.") ship = IDataHolder() ship.type = Const.T_SHIP # initial values hullTechEff = Rules.techImprEff[player.techs.get( hullID, Rules.techBaseImprovement)] ship.name = name ship.hullID = hullID ship.eqIDs = eqIDs ship.level = hull.level ship.combatClass = hull.combatClass ship.improvements = improvements ship.buildProd = hull.buildProd ship.buildSRes = copy.copy(hull.buildSRes) # stats grouped as "Base" ship.operEn = hull.operEn ship.storEn = hull.storEn * hullTechEff ship.weight = hull.weight ship.slots = 0 ship.scannerPwr = max(hull.scannerPwr * hullTechEff, Rules.scannerMinPwr) ship.engPwr = 0 ship.engStlPwr = 0 ship.speed = 0.0 ship.battleSpeed = 0.0 # stats grouped as "Signature" ship.signature = hull.signature ship.negsignature = 0 ship.minSignature = hull.minSignature ship.signatureCloak = 1.0 ship.signatureDecloak = 1.0 # stats grouped as "Combat" ship.combatAttBase = hull.combatAtt * hullTechEff ship.combatAtt = 0 ship.combatAttMultiplier = 1.0 ship.combatDefBase = hull.combatDef * hullTechEff ship.combatDef = 0 ship.combatDefMultiplier = 1.0 ship.missileDefBase = hull.missileDef * hullTechEff ship.missileDef = 0 ship.missileDefMultiplier = 1.0 ship.weaponIDs = [] ship.isMilitary = 0 ship.baseExp = 0 combatExtra = 0 # stats grouped as "Sturdiness" ship.autoRepairFix = hull.autoRepairFix ship.autoRepairPerc = hull.autoRepairPerc ship.shieldRechargeFix = hull.shieldRechargeFix ship.shieldRechargePerc = hull.shieldRechargePerc ship.hardShield = 0.0 ship.shieldHP = 0 ship.maxHP = int(hull.maxHP * hullTechEff) ship.damageAbsorb = 0 shieldPerc = 0.0 # stats grouped as "Deployables" ship.deployStructs = [] ship.deployHandlers = [] ship.upgradeTo = 0 counter = {} installations = {} equipCounter = {} for techID in eqIDs: tech = Rules.techs[techID] techEff = Rules.techImprEff[player.techs.get( techID, Rules.techBaseImprovement)] if eqIDs[techID] < 0 and raiseExs: raise GameException("Invalid equipment count (less than 0).") for i in xrange(0, eqIDs[techID]): counter[tech.subtype] = 1 + counter.get(tech.subtype, 0) installations[techID] = 1 + installations.get(techID, 0) _checkValidity(ship, tech, installations, equipCounter, raiseExs) # add values _moduleBase(ship, tech, techEff) _moduleSignature(ship, tech) _moduleCombat(ship, tech, techEff, combatExtra) _moduleSturdiness(ship, tech, techEff, shieldPerc) _moduleDeployables(ship, tech) _checkValidityWhole(ship, hull, counter, raiseExs) _finalizeBase(ship, hull) _finalizeSignature(ship, hull) _finalizeCombat(ship) _finalizeSturdiness(ship, shieldPerc) _setCombatPower(ship, combatExtra) return ship
def getSystemStructStats(data, client, db, systemID, processQueues=True): """ It go through all planets and structures, and creates IDataHolder object, with roster of buildings, surplus of bio and en. processQueues - if True, it go through all buildQueues and adjust all statistics as it would be all done already. Returns IDataHolder with parameters: .bio - system surplus of biomass .en - system surplus of en .planets - dictionary, keys are planetIDs of players or free planets, and values are dictionaries (huh) with keys being techIDs and values being number of those structs. """ systemStats = IDataHolder() system = db[systemID] player = client.getPlayer() myPlanets = set(system.planets) & data.myPlanets systemStats.planets = {} for planetID in myPlanets: systemStats.planets[planetID] = {} for planetID in set(system.planets) & data.freePlanets: systemStats.planets[planetID] = {} # creation of the .planets dictionary for planetID in myPlanets: planet = db[planetID] for techID, hp, something, eff in planet.slots: try: systemStats.planets[planetID][techID] += 1 except KeyError: systemStats.planets[planetID][techID] = 1 if not processQueues: # do not look into the queue continue for task in getattr(planet, 'prodQueue', []): if not task.isShip: techID = task.techID tech = client.getFullTechInfo(task.techID) if tech.isStructure: if task.targetID not in systemStats.planets.keys(): continue try: systemStats.planets[task.targetID][techID] += 1 except KeyError: systemStats.planets[task.targetID][techID] = 1 if task.demolishStruct: try: systemStats.planets[task.targetID][ task.demolishStruct] -= 1 except KeyError: systemStats.planets[task.targetID][ task.demolishStruct] = -1 # by parsing .planets object, fill the .bio and .en parameters systemStats.bio = 0 systemStats.en = 0 for planetID in systemStats.planets: planet = db[planetID] if planetID not in myPlanets: continue for techID in systemStats.planets[planetID]: quantity = systemStats.planets[planetID][techID] deltaBio, deltaEn, deltaProd = getSystemStatsChange( client, db, techID, planetID, 0) tech = client.getFullTechInfo(techID) systemStats.en += quantity * deltaEn systemStats.bio += quantity * deltaBio return systemStats
def tool_parseDB(client, db, enemyTypes): """ Parses all data in db for needs of other tools. Other in the name means other players. """ data = IDataHolder() data.myPlanets = set() data.myProdPlanets = set() data.mySystems = set() data.freePlanets = set() data.freeSystems = set() data.nonhabPlanets = set() data.unknownSystems = set() data.otherPlanets = set() data.enemyPlanets = set() data.otherSystems = set() data.enemySystems = set() data.systems = set() data.myFleets = set() data.myMPPerSystem = {} data.myTargetedSystems = set() data.endangeredSystems = {} data.otherFleets = set() data.otherInboundFleets = set() data.idleFleets = set() data.myFleetsWithDesign = {} data.myFleetSheets = {} data.pirateSystems = set() data.relevantSystems = set() data.myRelevantSystems = set() data.distanceToRelevance = {} playerID = client.getPlayerID() player = client.getPlayer() owners = {} for objID in db.keys(): try: obj = db[objID] except KeyError: # TODO find out why there are these errors continue objType = getattr(obj, 'type', None) if objType == Const.T_PLANET: ownerID = getattr(obj, 'owner', None) plSlots = getattr(obj, 'plSlots', 0) slots = getattr(obj, 'slots', []) prodProd = getattr(obj, 'prodProd', 0) plType = getattr(obj, 'plType', None) if plType == u'G' or plType == u'A': data.nonhabPlanets.add(objID) continue if ownerID == playerID and prodProd: data.myProdPlanets.add(objID) data.mySystems.add(obj.compOf) elif ownerID == playerID and not prodProd: # myPlanets are later joined by myProdPlanets data.myPlanets.add(objID) data.mySystems.add(obj.compOf) elif ownerID == Const.OID_NONE and plSlots: data.freePlanets.add(objID) elif not plSlots: data.unknownSystems.add(obj.compOf) else: # systems with owner other than myself, ignore EDEN planets if not ownerID: continue elif ownerID not in owners: owners[ownerID] = client.get(ownerID, publicOnly=1) if not getattr(owners[ownerID], 'type', Const.OID_NONE) == Const.T_AIEDENPLAYER: data.otherSystems.add(db[objID].compOf) data.otherPlanets.add(objID) if getattr(owners[ownerID], 'type', Const.OID_NONE) in enemyTypes: data.enemySystems.add(db[objID].compOf) data.enemyPlanets.add(objID) if getattr(owners[ownerID], 'type', Const.OID_NONE) in (Const.T_AIPIRPLAYER, Const.T_PIRPLAYER): data.pirateSystems.add(db[objID].compOf) elif objType == Const.T_SYSTEM: if getattr(obj, "starClass", "a")[0] == 'b': # black hole -> nothing to see here, let's ignore it completely continue data.systems.add(objID) if not hasattr(db[objID], 'planets'): data.unknownSystems.add(objID) elif objType == Const.T_FLEET: ownerID = getattr(obj, 'owner', None) if ownerID == playerID: data.myFleets.add(objID) data.myFleetSheets[objID] = getFleetSheet(obj) if len(obj.actions[obj.actionIndex:]) == 0: data.idleFleets.add(objID) for designID in data.myFleetSheets[objID].keys(): if not data.myFleetsWithDesign.get(designID, set()): data.myFleetsWithDesign[designID] = set([objID]) else: data.myFleetsWithDesign[designID] |= set([objID]) else: data.otherFleets.add(objID) # ================== # second phase # analyzing fleet action queues for fleetID in data.myFleets: fleet = db[fleetID] for orType, orTargID, orData in fleet.actions[fleet.actionIndex:]: if orType == Const.FLACTION_WAIT: continue elif orType == Const.FLACTION_REPEATFROM: continue elif orType == Const.FLACTION_REDIRECT: if orTargID == Const.OID_NONE: continue orTarg = db[orTargID] if orTarg.type == Const.T_SYSTEM: data.unknownSystems -= set([orTargID]) elif orTarg.type == Const.T_PLANET: data.unknownSystems -= set([orTarg.compOf]) # deploy order removes target from free planets set # if deploying to non-free planet, change order TODO [non-systematic] if orType == Const.FLACTION_DEPLOY: if orTargID in data.freePlanets: data.freePlanets -= set([orTargID]) else: client.cmdProxy.deleteAction(fleetID, fleet.actionIndex) # fill data.myMPPerSystem if len(fleet.actions[fleet.actionIndex:]) == 0: if fleet.orbiting in data.mySystems: try: data.myMPPerSystem[fleet.orbiting] += fleet.combatPwr except KeyError: data.myMPPerSystem[fleet.orbiting] = fleet.combatPwr else: lastOrder = fleet.actions[len(fleet.actions) - 1] targetID = lastOrder[1] if targetID in data.myPlanets: sysID = db[targetID].compOf try: data.myMPPerSystem[sysID] += fleet.combatPwr except KeyError: data.myMPPerSystem[sysID] = fleet.combatPwr elif targetID in data.mySystems: try: data.myMPPerSystem[targetID] += fleet.combatPwr except KeyError: data.myMPPerSystem[targetID] = fleet.combatPwr data.myPlanets |= data.myProdPlanets # only systems with free or nonhabitable planets are considered free for systemID in data.systems: isEmpty = True hasEmpty = False planets = set(getattr(db[systemID], 'planets', [])) if planets and not planets - data.freePlanets - data.nonhabPlanets: data.freeSystems.add(systemID) # find attacking fleets for fleetID in data.otherFleets: fleet = db[fleetID] if getattr(fleet, 'target', None): targetID = getattr(fleet, 'target', None) elif not getattr(fleet, 'orbiting', Const.OID_NONE) == Const.OID_NONE: targetID = getattr(fleet, 'orbiting', Const.OID_NONE) if targetID: if targetID in data.myPlanets: data.myTargetedSystems.add(db[targetID].compOf) data.otherInboundFleets.add(fleetID) elif targetID in data.mySystems: data.myTargetedSystems.add(targetID) data.otherInboundFleets.add(fleetID) return data
def getPublicInfo(self, tran, obj): result = IDataHolder() result.oid = obj.oid return result
def new(self, type): obj = IDataHolder() self._cmd[type].init(obj) return obj
def getScanInfos(self, tran, obj, scanPwr, player): result = IDataHolder() results = [result] if scanPwr >= Rules.level1InfoScanPwr: result._type = Const.T_SCAN result.scanPwr = scanPwr result.oid = obj.oid result.x = obj.x result.y = obj.y if hasattr(obj, 'destinationOid'): result.destinationOid = obj.destinationOid result.signature = obj.signature result.type = obj.type result.compOf = obj.compOf result.starClass = obj.starClass if scanPwr >= Rules.level2InfoScanPwr: result.name = obj.name result.combatCounter = obj.combatCounter if scanPwr >= Rules.level3InfoScanPwr: result.planets = obj.planets result.owner = obj.owner for planetID in obj.planets: planet = tran.db[planetID] if planet.owner == player: ####### This was player.owner, which made no sense. Hope this change doesn't break something continue newPwr = scanPwr * planet.signature / obj.signature results.extend( self.cmd(planet).getScanInfos(tran, planet, newPwr, player)) if scanPwr >= Rules.level4InfoScanPwr: result.fleets = obj.fleets for fleetID in obj.fleets: fleet = tran.db[fleetID] if fleet.owner == player: continue newPwr = scanPwr * fleet.signature / obj.signature results.extend( self.cmd(fleet).getScanInfos(tran, fleet, newPwr, player)) result.minefield = self.getMines(obj, player.oid) ownsMines = 1 if result.minefield else 0 result.hasmines = min(2, len(self.getAllMines(obj))) - ownsMines return results
def _create_answer(self, gal_type): template = self.offerings[gal_type] answer = IDataHolder() answer.scenario = template.scenario answer.minPlanets = template.minPlanets answer.maxPlanets = template.maxPlanets answer.radius = template.radius answer.players = template.players answer.resources = template.resources.keys() answer.challenges = self._get_challenges(template) if not template.startR[0] or not template.startR[1]: # that means grouping is used to maximize distance between players # most likely brawl scenario answer.playerGroup = 1 else: answer.playerGroup = template.playerGroup return answer
def getDiplomacyWith(self, tran, obj, playerID): if obj.oid == playerID: return Const.REL_UNITY player = tran.db.get(playerID, None) if player.type in (Const.T_AIPIRPLAYER, Const.T_PIRPLAYER): dipl = obj.diplomacyRels.get(playerID, None) if not dipl: # make default dipl = IDataHolder() dipl.type = Const.T_DIPLREL dipl.pacts = { Const.PACT_ALLOW_CIVILIAN_SHIPS: [Const.PACT_ACTIVE, Const.PACT_ALLOW_CIVILIAN_SHIPS], Const.PACT_ALLOW_MILITARY_SHIPS: [Const.PACT_ACTIVE, Const.PACT_ALLOW_MILITARY_SHIPS] } dipl.relation = Const.REL_FRIENDLY dipl.relChng = 0 dipl.lastContact = tran.db[Const.OID_UNIVERSE].turn dipl.contactType = Const.CONTACT_NONE dipl.stats = None if playerID != obj.oid: obj.diplomacyRels[playerID] = dipl else: log.debug("getDiplomacyWith myself", obj.oid) return dipl # this AI battles with overyone # make default dipl = IDataHolder() dipl.type = Const.T_DIPLREL dipl.pacts = {} dipl.relation = Const.REL_ENEMY dipl.relChng = 0 dipl.lastContact = tran.db[Const.OID_UNIVERSE].turn dipl.contactType = Const.CONTACT_NONE dipl.stats = None return dipl
def makeShipMinSpec(player, name, hullID, eqIDs, improvements, raiseExs = True): ship = makeShipFullSpec(player, name, hullID, eqIDs, improvements, raiseExs) # make 'real' ship spec spec = IDataHolder() spec.type = T_SHIP spec.name = ship.name spec.hullID = ship.hullID spec.level = ship.level spec.eqIDs = ship.eqIDs spec.improvements = ship.improvements spec.combatClass = ship.combatClass spec.signature = ship.signature spec.scannerPwr = ship.scannerPwr spec.speed = ship.speed spec.maxHP = ship.maxHP spec.shieldHP = ship.shieldHP spec.combatAtt = ship.combatAtt spec.combatDef = ship.combatDef spec.missileDef = ship.missileDef spec.storEn = ship.storEn spec.operEn = ship.operEn spec.buildProd = ship.buildProd spec.buildSRes = ship.buildSRes spec.weaponIDs = ship.weaponIDs spec.deployStructs = ship.deployStructs spec.deployHandlers = ship.deployHandlers spec.built = 0 spec.buildTurns = 1 spec.upgradeTo = 0 spec.isMilitary = ship.isMilitary spec.baseExp = ship.baseExp spec.combatPwr = ship.combatPwr spec.autoRepairFix = ship.autoRepairFix spec.autoRepairPerc = ship.autoRepairPerc spec.shieldRechargeFix = ship.shieldRechargeFix spec.shieldRechargePerc = ship.shieldRechargePerc spec.hardShield = ship.hardShield spec.combatAttMultiplier = ship.combatAttMultiplier spec.damageAbsorb = ship.damageAbsorb return spec
self.state = 2 elif self.state == 4 and name == 'preresearch': self.tech.textPreRsrch = self.text self.state = 3 elif self.state == 4 and name == 'description': self.tech.textDescr = self.text self.state = 3 elif self.state == 4 and name == 'flavor': self.tech.textFlavor = self.text self.state = 3 def characters(self, text): self.text += text Tech = IDataHolder() ## init is wrapping all code that needs to be performed before module # is ready. That is checking if techs changed, if not loading pickled # data, othervise rebuild database from source data # We should be able to do server-provided techs in the future (per galaxy # rulesets) def init(configDir): global Tech, techs ## check, if anything has been changed def chsumDir(chsum, dirname, names): names.sort()
def tool_parseDB(client, db, enemyTypes): """ Parses all data in db for needs of other tools. Other in the name means other players. """ data = IDataHolder() data.myPlanets = set() data.myProdPlanets = set() data.mySystems = set() data.freePlanets = set() data.freeSystems = set() data.nonhabPlanets = set() data.unknownSystems = set() data.otherPlanets = set() data.enemyPlanets = set() data.otherSystems = set() data.enemySystems = set() data.systems = set() data.myFleets = set() data.myMPPerSystem = {} data.myTargetedSystems = set() data.endangeredSystems = {} data.otherFleets = set() data.otherInboundFleets = set() data.idleFleets = set() data.myFleetsWithDesign = {} data.myFleetSheets = {} data.pirateSystems = set() data.relevantSystems = set() data.myRelevantSystems = set() data.distanceToRelevance = {} playerID = client.getPlayerID() player = client.getPlayer() owners = {} for objID in db.keys(): try: obj = db[objID] except KeyError: # TODO find out why there are these errors continue objType = getattr(obj, 'type', None) if objType == Const.T_PLANET: ownerID = getattr(obj, 'owner', None) plSlots = getattr(obj, 'plSlots', 0) slots = getattr(obj, 'slots', []) prodProd = getattr(obj, 'prodProd', 0) plType = getattr(obj, 'plType', None) if plType == u'G' or plType == u'A': data.nonhabPlanets.add(objID) continue if ownerID == playerID and prodProd: data.myProdPlanets.add(objID) data.mySystems.add(obj.compOf) elif ownerID == playerID and not prodProd: # myPlanets are later joined by myProdPlanets data.myPlanets.add(objID) data.mySystems.add(obj.compOf) elif ownerID == Const.OID_NONE and plSlots: data.freePlanets.add(objID) elif not plSlots: data.unknownSystems.add(obj.compOf) else: # systems with owner other than myself, ignore EDEN planets if not ownerID: continue elif ownerID not in owners: owners[ownerID] = client.get(ownerID, publicOnly = 1) if not getattr(owners[ownerID], 'type', Const.OID_NONE) == Const.T_AIEDENPLAYER: data.otherSystems.add(db[objID].compOf) data.otherPlanets.add(objID) if getattr(owners[ownerID], 'type', Const.OID_NONE) in enemyTypes: data.enemySystems.add(db[objID].compOf) data.enemyPlanets.add(objID) if getattr(owners[ownerID], 'type', Const.OID_NONE) in (Const.T_AIPIRPLAYER, Const.T_PIRPLAYER): data.pirateSystems.add(db[objID].compOf) elif objType == Const.T_SYSTEM: if getattr(obj, "starClass", "a")[0] == 'b': # black hole -> nothing to see here, let's ignore it completely continue data.systems.add(objID) if not hasattr(db[objID], 'planets'): data.unknownSystems.add(objID) elif objType == Const.T_FLEET: ownerID = getattr(obj, 'owner', None) if ownerID == playerID: data.myFleets.add(objID) data.myFleetSheets[objID] = getFleetSheet(obj) if len(obj.actions[obj.actionIndex:]) == 0: data.idleFleets.add(objID) for designID in data.myFleetSheets[objID].keys(): if not data.myFleetsWithDesign.get(designID, set()): data.myFleetsWithDesign[designID] = set([objID]) else: data.myFleetsWithDesign[designID] |= set([objID]) else: data.otherFleets.add(objID) # ================== # second phase # analyzing fleet action queues for fleetID in data.myFleets: fleet = db[fleetID] for orType, orTargID, orData in fleet.actions[fleet.actionIndex:]: if orType == Const.FLACTION_WAIT: continue elif orType == Const.FLACTION_REPEATFROM: continue elif orType == Const.FLACTION_REDIRECT: if orTargID == Const.OID_NONE: continue orTarg = db[orTargID] if orTarg.type == Const.T_SYSTEM: data.unknownSystems -= set([orTargID]) elif orTarg.type == Const.T_PLANET: data.unknownSystems -= set([orTarg.compOf]) # deploy order removes target from free planets set # if deploying to non-free planet, change order TODO [non-systematic] if orType == Const.FLACTION_DEPLOY: if orTargID in data.freePlanets: data.freePlanets -= set([orTargID]) else: client.cmdProxy.deleteAction(fleetID, fleet.actionIndex) # fill data.myMPPerSystem if len(fleet.actions[fleet.actionIndex:]) == 0: if fleet.orbiting in data.mySystems: try: data.myMPPerSystem[fleet.orbiting] += fleet.combatPwr except KeyError: data.myMPPerSystem[fleet.orbiting] = fleet.combatPwr else: lastOrder = fleet.actions[len(fleet.actions)-1] targetID = lastOrder[1] if targetID in data.myPlanets: sysID = db[targetID].compOf try: data.myMPPerSystem[sysID] += fleet.combatPwr except KeyError: data.myMPPerSystem[sysID] = fleet.combatPwr elif targetID in data.mySystems: try: data.myMPPerSystem[targetID] += fleet.combatPwr except KeyError: data.myMPPerSystem[targetID] = fleet.combatPwr data.myPlanets |= data.myProdPlanets # only systems with free or nonhabitable planets are considered free for systemID in data.systems: isEmpty = True hasEmpty = False planets = set(getattr(db[systemID], 'planets', [])) if planets and not planets - data.freePlanets - data.nonhabPlanets: data.freeSystems.add(systemID) # find attacking fleets for fleetID in data.otherFleets: fleet = db[fleetID] if getattr(fleet, 'target', None): targetID = getattr(fleet, 'target', None) elif not getattr(fleet, 'orbiting', Const.OID_NONE) == Const.OID_NONE: targetID = getattr(fleet, 'orbiting', Const.OID_NONE) if targetID: if targetID in data.myPlanets: data.myTargetedSystems.add(db[targetID].compOf) data.otherInboundFleets.add(fleetID) elif targetID in data.mySystems: data.myTargetedSystems.add(targetID) data.otherInboundFleets.add(fleetID) return data
def getScanInfos(self, tran, obj, scanPwr, player): result = IDataHolder() results = [result] if scanPwr >= Rules.level1InfoScanPwr: result._type = T_SCAN result.scanPwr = scanPwr result.oid = obj.oid result.x = obj.x result.y = obj.y if hasattr(obj, 'destinationOid'): result.destinationOid = obj.destinationOid # multiply by 1000 to increase accuracy #~ result.dist = obj.dist * 1000 #~ result.dAngle = obj.dAngle * 1000 #~ result.sAngle = obj.sAngle * 1000 result.signature = obj.signature result.type = obj.type result.compOf = obj.compOf result.starClass = obj.starClass if scanPwr >= Rules.level2InfoScanPwr: result.name = obj.name result.combatCounter = obj.combatCounter if scanPwr >= Rules.level3InfoScanPwr: result.planets = obj.planets result.owner = obj.owner for planetID in obj.planets: planet = tran.db[planetID] if planet.owner == player: ####### This was player.owner, which made no sense. Hope this change doesn't break something continue newPwr = scanPwr * planet.signature / obj.signature results.extend(self.cmd(planet).getScanInfos(tran, planet, newPwr, player)) if scanPwr >= Rules.level4InfoScanPwr: result.fleets = obj.fleets for fleetID in obj.fleets: fleet = tran.db[fleetID] if fleet.owner == player: continue newPwr = scanPwr * fleet.signature / obj.signature results.extend(self.cmd(fleet).getScanInfos(tran, fleet, newPwr, player)) result.hasmines = 0 #no if len(obj.minefield) > 0: result.hasmines = 1 #yes result.minefield = self.getMines(obj,player.oid) #only shows mines you own if len(obj.minefield) > 1 or (len(obj.minefield) == 1 and len(result.minefield) == 0): result.hasmines = 2 #yes, and some aren't my mines return results
def makeShipFullSpec(player, name, hullID, eqIDs, improvements, raiseExs = True): if not hullID: raise GameException("Ship's hull must be specified.") hull = Rules.techs[hullID] if not hull.isShipHull: raise GameException("Ship's hull must be specified.") ship = IDataHolder() ship.type = Const.T_SHIP # initial values hullTechEff = Rules.techImprEff[player.techs.get(hullID, Rules.techBaseImprovement)] ship.name = name ship.hullID = hullID ship.eqIDs = eqIDs ship.level = hull.level ship.combatClass = hull.combatClass ship.improvements = improvements ship.buildProd = hull.buildProd ship.buildSRes = copy.copy(hull.buildSRes) # stats grouped as "Base" ship.operEn = hull.operEn ship.storEn = hull.storEn * hullTechEff ship.weight = hull.weight ship.slots = 0 ship.scannerPwr = max(hull.scannerPwr * hullTechEff, Rules.scannerMinPwr) ship.engPwr = 0 ship.engStlPwr = 0 ship.speed = 0.0 ship.battleSpeed = 0.0 # stats grouped as "Signature" ship.signature = hull.signature ship.negsignature = 0 ship.minSignature = hull.minSignature ship.signatureCloak = 1.0 ship.signatureDecloak = 1.0 # stats grouped as "Combat" ship.combatAttBase = hull.combatAtt * hullTechEff ship.combatAtt = 0 ship.combatAttMultiplier = 1.0 ship.combatDefBase = hull.combatDef * hullTechEff ship.combatDef = 0 ship.combatDefMultiplier = 1.0 ship.missileDefBase = hull.missileDef * hullTechEff ship.missileDef = 0 ship.missileDefMultiplier = 1.0 ship.weaponIDs = [] ship.isMilitary = 0 ship.baseExp = 0 combatExtra = 0 # stats grouped as "Sturdiness" ship.autoRepairFix = hull.autoRepairFix ship.autoRepairPerc = hull.autoRepairPerc ship.shieldRechargeFix = hull.shieldRechargeFix ship.shieldRechargePerc = hull.shieldRechargePerc ship.hardShield = 0.0 ship.shieldHP = 0 ship.maxHP = int(hull.maxHP * hullTechEff) ship.damageAbsorb = 0 shieldPerc = 0.0 # stats grouped as "Deployables" ship.deployStructs = [] ship.deployHandlers = [] ship.upgradeTo = 0 counter = {} installations = {} equipCounter = {} for techID in eqIDs: tech = Rules.techs[techID] techEff = Rules.techImprEff[player.techs.get(techID, Rules.techBaseImprovement)] if eqIDs[techID] < 0 and raiseExs: raise GameException("Invalid equipment count (less than 0).") for i in xrange(0, eqIDs[techID]): counter[tech.subtype] = 1 + counter.get(tech.subtype, 0) installations[techID] = 1 + installations.get(techID, 0) _checkValidity(ship, tech, installations, equipCounter, raiseExs) # add values _moduleBase(ship, tech, techEff) _moduleSignature(ship, tech) _moduleCombat(ship, tech, techEff, combatExtra) _moduleSturdiness(ship, tech, techEff, shieldPerc) _moduleDeployables(ship, tech) _checkValidityWhole(ship, hull, counter, raiseExs) _finalizeBase(ship, hull) _finalizeSignature(ship, hull) _finalizeCombat(ship) _finalizeSturdiness(ship, shieldPerc) _setCombatPower(ship, combatExtra) return ship
def XXXgetDiplomacyWith(self, tran, obj, playerID): if obj.oid == playerID: return REL_UNITY player = tran.db.get(playerID, None) if player.type == T_AIEDENPLAYER: dipl = obj.diplomacyRels.get(playerID, None) if not dipl: # make default dipl = IDataHolder() dipl.type = T_DIPLREL dipl.pacts = { PACT_ALLOW_CIVILIAN_SHIPS: [PACT_ACTIVE, PACT_ALLOW_CIVILIAN_SHIPS], PACT_ALLOW_MILITARY_SHIPS: [PACT_ACTIVE, PACT_ALLOW_MILITARY_SHIPS] } dipl.relation = REL_FRIENDLY dipl.relChng = 0 dipl.lastContact = tran.db[OID_UNIVERSE].turn dipl.contactType = CONTACT_NONE dipl.stats = None if playerID != obj.oid: obj.diplomacyRels[playerID] = dipl else: log.debug("getDiplomacyWith myself", obj.oid) return dipl # this AI battles with overyone # make default dipl = IDataHolder() dipl.type = T_DIPLREL dipl.pacts = {} dipl.relation = REL_ENEMY dipl.relChng = 0 dipl.lastContact = tran.db[OID_UNIVERSE].turn dipl.contactType = CONTACT_NONE dipl.stats = None return dipl
def getScanInfo(self, tran, obj, scanPwr): result = IDataHolder() result._type = Const.T_SCAN result.scanPwr = scanPwr if scanPwr > Rules.level1InfoScanPwr: result.oid = obj.oid result.x = obj.x result.y = obj.y result.oldX = obj.oldX result.oldY = obj.oldY result.signature = obj.signature result.type = obj.type result.orbiting = obj.orbiting result.speed = obj.speed result.eta = obj.eta if scanPwr > Rules.level2InfoScanPwr: result.name = obj.name if scanPwr > Rules.level3InfoScanPwr: result.asDiameter = obj.asDiameter result.asHP = obj.asHP if scanPwr > Rules.level4InfoScanPwr: pass return result
def processBATTLEPhase(self, tran, obj, data): system = obj #@log.debug('ISystem', 'BATTLE - system', obj.oid) # we are processing fleets, planets, ... objects = obj.planets[:] + obj.fleets[:] # shuffle them to prevent predetermined one-sided battles (temporary hack) random.shuffle(objects) # store owners of objects # find enemies and allies attack = {} allies = {} owners = {} ownerIDs = {} systemAtt = {} systemDef = {} hasMine = {} isOwnedObject = 0 for objID in objects: attack[objID] = [] allies[objID] = [] owner = tran.db[objID].owner owners[objID] = owner ownerIDs[owner] = owner if owner != OID_NONE: isOwnedObject = 1 for owner in ownerIDs: tempAtt, tempDef = self.getSystemCombatBonuses(tran,system,owner) systemAtt[owner] = tempAtt systemDef[owner] = tempDef hasMine[owner] = self.getSystemMineSource(tran,system,owner) if not isOwnedObject: #@log.debug('ISystem', 'No combat') # reset combat counters system.combatCounter = 0 return # first - direct ones index = 1 for obj1ID in objects: obj1 = tran.db[obj1ID] if obj1.owner == OID_NONE: index += 1 continue commander = tran.db[obj1.owner] # relationships #for obj2ID in objects[index:]: for obj2ID in objects: obj2 = tran.db[obj2ID] if obj2.owner == OID_NONE or obj1 is obj2: continue if obj1.owner == obj2.owner: allies[obj1ID].append(obj2ID) allies[obj2ID].append(obj1ID) continue # planet and military object elif obj1.type == T_PLANET and obj2.isMilitary and \ not self.cmd(commander).isPactActive(tran, commander, obj2.owner, PACT_ALLOW_MILITARY_SHIPS): #@log.debug("ISystem pl - mil", obj1ID, obj2ID) if obj2ID not in attack[obj1ID]: attack[obj1ID].append(obj2ID) if obj1ID not in attack[obj2ID]: attack[obj2ID].append(obj1ID) # planet and civilian object elif obj1.type == T_PLANET and not obj2.isMilitary and \ not self.cmd(commander).isPactActive(tran, commander, obj2.owner, PACT_ALLOW_CIVILIAN_SHIPS): #@log.debug("ISystem pl - civ", obj1ID, obj2ID) if obj2ID not in attack[obj1ID]: attack[obj1ID].append(obj2ID) if obj1ID not in attack[obj2ID]: attack[obj2ID].append(obj1ID) # military and military object elif obj1.isMilitary and obj2.isMilitary and \ not self.cmd(commander).isPactActive(tran, commander, obj2.owner, PACT_ALLOW_MILITARY_SHIPS): #@log.debug("ISystem mil - mil", obj1ID, obj2ID) if obj2ID not in attack[obj1ID]: attack[obj1ID].append(obj2ID) if obj1ID not in attack[obj2ID]: attack[obj2ID].append(obj1ID) # military and civilian object elif obj1.isMilitary and not obj2.isMilitary and \ not self.cmd(commander).isPactActive(tran, commander, obj2.owner, PACT_ALLOW_CIVILIAN_SHIPS): #@log.debug("ISystem mil - civ", obj1ID, obj2ID) if obj2ID not in attack[obj1ID]: attack[obj1ID].append(obj2ID) if obj1ID not in attack[obj2ID]: attack[obj2ID].append(obj1ID) # planet and fleet #elif obj1.type == T_PLANET and obj2.type == T_FLEET and \ # self.cmd(commander).isPactActive(tran, commander, obj2.owner, PACT_MUTUAL_DEFENCE): # allies[obj1ID].append(obj2ID) # allies[obj2ID].append(obj1ID) # fleet and fleet #elif obj1.type == T_FLEET and obj2.type == T_FLEET and \ # self.cmd(commander).isPactActive(tran, commander, obj2.owner, PACT_MUTUAL_OFFENCE): # allies[obj1ID].append(obj2ID) # allies[obj2ID].append(obj1ID) # asteroid if obj2.type == T_ASTEROID: attack[obj1ID].append(obj2ID) attack[obj2ID].append(obj1ID) index += 1 #@log.debug('ISystem', 'Targets:', targets) #@log.debug('ISystem', 'Allies:', allies) # find indirect a/e #for objID in objects: # iTargets = [] # iAllies = [] # # find indirect a/e # todo = allies[objID][:] # while todo: # id = todo.pop(0) # iTargets.extend(targets[id]) # for tmpID in allies[id]: # if tmpID not in iAllies: # todo.append(tmpID) # iAllies.append(tmpID) # # remove allies from targets # for id in iAllies: # if id in iTargets: # iTargets.remove(id) # # IMPORTATNT preffer NOT to fire at possible allies # # add my targets # #for id in targets[objID]: # # if id not in iTargets: # # iTargets.append(id) # # that's all folks # for id in iTargets: # if objID not in attack[id]: # attack[id].append(objID) # if id not in attack[objID]: # attack[objID].append(id) # NOT VALID: objects with action ACTION_ATTACK will attack only their targets # check, if there are any targets isCombat = 0 for objID in objects: if attack[objID]: isCombat = 1 break #end loop if not isCombat: #@log.debug('ISystem', 'No combat') # reset combat counters system.combatCounter = 0 for fleetID in system.fleets: tran.db[fleetID].combatCounter = 0 return # increase combat counters system.combatCounter += 1 for fleetID in system.fleets: tran.db[fleetID].combatCounter += 1 # debug log.debug('ISystem', 'Final attacks in system %d:' % system.oid, attack) # mines detonate before battle shots = {} targets = {} firing = {} damageCaused = {} killsCaused = {} damageTaken = {} shipsLost = {} minesTriggered = {} fleetOwners = {} isCombat = False isMineCombat = False for owner in ownerIDs: if not (owner in hasMine): #no planets continue if hasMine[owner] == 0: #no control structure continue objID = hasMine[owner] if len(self.getMines(system,owner)) == 0: continue #no mines, something broke #log.debug('ISystem-Mines', 'Mines Found') if len(attack[objID]) == 0: continue #no targets isMineFired = True mineTargets = copy.copy(attack[objID]) while isMineFired: while len(mineTargets) > 0: targetID = random.choice(mineTargets) #select random target targetobj = tran.db.get(targetID, None) try: if targetobj.type == T_FLEET: fleetOwners[targetID] = targetobj.owner break #target found mineTargets.remove(targetID) #remove an object type that a mine can't hit from the temporary targets list except: mineTargets.remove(targetID) #remove a dead fleet from the temporary targets list if len(mineTargets) == 0: break #no fleet targets for mines temp, temp, firing[targetID] = self.cmd(targetobj).getPreCombatData(tran, targetobj) #fix firing for "surrender to" section damage,att,ignoreshield, mineID = self.cmd(obj).fireMine(system, owner) if not damage: #no more mines isMineFired = False break log.debug('ISystem', 'Mine Shooting (damage, att, ignore shield):',damage,att,ignoreshield) isMineCombat = True minesTriggered[mineID] = minesTriggered.get(mineID, 0) + 1 #Process Combat #for now we assume only one ship can be destroyed by one mine dmg, destroyed = self.cmd(targetobj).applyMine(tran, targetobj, att, damage, ignoreshield) #log.debug('ISystem-Mines', 'Actual Damage Done:',dmg) if dmg > 0: damageTaken[targetID] = damageTaken.get(targetID, 0) + dmg shipsLost[targetID] = shipsLost.get(targetID, 0) + destroyed killsCaused[mineID] = killsCaused.get(mineID, 0) + destroyed if dmg > 0: damageCaused[mineID] = damageCaused.get(mineID, 0) + dmg # send messages about mine effects to the owner of the minefield # collect hit players players = {} for triggerID in firing.keys(): players[owners[triggerID]] = None controllerPlanet = tran.db.get(objID, None) damageCausedSum = 0 killsCausedSum = 0 for mineID in damageCaused.keys(): damageCausedSum = damageCausedSum + damageCaused.get(mineID, 0) killsCausedSum = killsCausedSum + killsCaused.get(mineID, 0) Utils.sendMessage(tran, controllerPlanet, MSG_MINES_OWNER_RESULTS, system.oid, (players.keys(),(damageCaused, killsCaused, minesTriggered),damageCausedSum,killsCausedSum)) # send messages to the players whose fleets got hit by minefields for targetID in damageTaken.keys(): targetFleet = tran.db.get(targetID, None) if targetFleet: Utils.sendMessage(tran, targetFleet, MSG_MINES_FLEET_RESULTS, system.oid, (damageTaken[targetID], shipsLost[targetID])) else: targetFleet = IDataHolder() targetFleet.oid = fleetOwners[targetID] Utils.sendMessage(tran, targetFleet, MSG_MINES_FLEET_RESULTS, system.oid, (damageTaken[targetID], shipsLost[targetID])) Utils.sendMessage(tran, targetFleet, MSG_DESTROYED_FLEET, system.oid, ()) damageCaused = {} killsCaused = {} damageTaken = {} shipsLost = {} # now to battle for objID in objects: obj = tran.db.get(objID, None) # get shots from object, should be sorted by weaponClass # shots = [ shot, ...], shot = (combatAtt, weaponID) # get target classes and numbers # (class1, class2, class3, class4) # cls0 == fighters, cls1 == midships, cls2 == capital ships, cls3 == planet installations #@log.debug(objID, obj.name, "getting pre combat data") if obj: # source already destroyed; ignore shots[objID], targets[objID], firing[objID] = self.cmd(obj).getPreCombatData(tran, obj) if firing[objID]: isCombat = True if not isCombat and not isMineCombat: # no shots has been fired #@log.debug('ISystem', 'No combat') # reset combat counters system.combatCounter = 0 for fleetID in system.fleets: tran.db[fleetID].combatCounter = 0 return #@log.debug("Shots:", shots) #@log.debug("Targets", targets) if isCombat: for shotIdx in (3, 2, 1, 0): for objID in objects: # obj CAN be deleted at this point obj = tran.db.get(objID, None) if obj == None: continue # source already destroyed; move to next source # if object is fleet, then it's signature is max if obj and obj.type == T_FLEET: obj.signature = Rules.maxSignature # target preselection totalClass = [0, 0, 0, 0] total = 0 for targetID in attack[objID]: totalClass[0] += targets[targetID][0] totalClass[1] += targets[targetID][1] totalClass[2] += targets[targetID][2] totalClass[3] += targets[targetID][3] total = totalClass[0] + totalClass[1] + totalClass[2] + totalClass[3] # process shots for combatAtt, weaponID in shots[objID][shotIdx]: weapon = Rules.techs[weaponID] weaponClass = weapon.weaponClass if total == 0: # there are no targets break #@log.debug('ISystem', 'Processing shot', objID, weapon.name, weaponClass) # process from weaponClass up # never shoot on smaller ships than weaponClass applied = 0 for tmpWpnClass in xrange(weaponClass, 4): #@log.debug('ISystem', 'Trying target class', tmpWpnClass, totalClass[tmpWpnClass]) # select target if totalClass[tmpWpnClass]: target = Utils.rand(0, totalClass[tmpWpnClass]) #@log.debug('ISystem', 'Target rnd num', target, totalClass[tmpWpnClass]) for targetID in attack[objID]: if target < targets[targetID][tmpWpnClass]: #@log.debug(objID, 'attacks', targetID, tmpWpnClass) # targetID can be deleted at this point anObj = tran.db.get(targetID, None) if anObj: dmg, destroyed, destroyedClass = self.cmd(anObj).applyShot(tran, anObj, systemDef[owners[targetID]], combatAtt + systemAtt[owners[objID]], weaponID, tmpWpnClass, target) #@log.debug("ISystem result", dmg, destroyed, destroyedClass, tmpWpnClass) #@print objID, 'dmg, destroyed', dmg, destroyed damageTaken[targetID] = damageTaken.get(targetID, 0) + dmg if destroyed > 0: shipsLost[targetID] = shipsLost.get(targetID, 0) + destroyed total -= destroyed totalClass[destroyedClass] -= destroyed if dmg > 0 and obj: obj.combatExp += dmg damageCaused[objID] = damageCaused.get(objID, 0) + dmg applied = 1 else: continue # target already destroyed, move to next target break else: #@log.debug('ISystem', 'Lovering target by', targets[targetID][tmpWpnClass]) target -= targets[targetID][tmpWpnClass] if applied: break # send messages and modify diplomacy relations # distribute experience pts for objID in objects: obj = tran.db.get(objID, None) if obj: self.cmd(obj).distributeExp(tran, obj) if attack[objID]: source = obj or tran.db[owners[objID]] # collect players players = {} for attackerID in attack[objID]: players[owners[attackerID]] = None d1 = damageTaken.get(objID,0) d2 = damageCaused.get(objID,0) l = shipsLost.get(objID, 0) if d1 or d2 or l: # send only if damage is taken/caused Utils.sendMessage(tran, source, MSG_COMBAT_RESULTS, system.oid, (d1, d2, l, players.keys())) if not obj: # report DESTROYED status Utils.sendMessage(tran, source, MSG_DESTROYED_FLEET, system.oid, ()) # modify diplomacy relations objOwner = tran.db[owners[objID]] for attackerID in attack[objID]: attOwner = tran.db.get(owners[attackerID], None) # owner of the fleet rel = self.cmd(objOwner).getDiplomacyWith(tran, objOwner, attOwner.oid) rel.relChng = Rules.relLostWhenAttacked # attacker rel = self.cmd(attOwner).getDiplomacyWith(tran, attOwner, objOwner.oid) rel.rechChng = Rules.relLostWhenAttacked # check if object surrenders for objID in objects: # object surrender IFF it and its allies had target and was not able # to fire at it, planet is not counted as ally in this case obj = tran.db.get(objID, None) if firing[objID] and obj: continue surrenderTo = [] for attID in attack[objID]: if firing[attID] and tran.db.has_key(attID): surrenderTo.append(tran.db[attID].owner) for allyID in allies[objID]: if not tran.db.has_key(allyID): continue ally = tran.db[allyID] if firing[allyID] and ally.type != T_PLANET: surrenderTo = [] break if surrenderTo: index = Utils.rand(0, len(surrenderTo)) if obj: if self.cmd(obj).surrenderTo(tran, obj, surrenderTo[index]): winner = tran.db[surrenderTo[index]] source = tran.db.get(owners[objID], None) log.debug('ISystem', 'BATTLE - surrender', objID, surrenderTo[index], surrenderTo) if source: Utils.sendMessage(tran, source, MSG_COMBAT_LOST, system.oid, winner.oid) Utils.sendMessage(tran, winner, MSG_COMBAT_WON, system.oid, source.oid) else: Utils.sendMessage(tran, winner, MSG_COMBAT_WON, system.oid, obj.oid) else: winner = tran.db[surrenderTo[index]] source = tran.db[owners[objID]] log.debug('ISystem', 'BATTLE - surrender', objID, surrenderTo[index], surrenderTo) Utils.sendMessage(tran, source, MSG_COMBAT_LOST, system.oid, winner.oid) Utils.sendMessage(tran, winner, MSG_COMBAT_WON, system.oid, source.oid) return
def startConstruction(self, tran, obj, techID, quantity, targetID, isShip, reportFinished, demolishStruct): if len(obj.prodQueue) > Rules.maxProdQueueLen: raise GameException('Queue is full.') if quantity < 1: raise GameException("Quantity must be greater than 0") player = tran.db[obj.owner] if not player.techs.has_key(techID) and isShip == 0: raise GameException('You do not own this kind of technology.') if not player.shipDesigns.has_key(techID) and isShip == 1: raise GameException('You do not own this ship design.') if targetID not in tran.db[obj.compOf].planets: raise GameException('You can build only in the same system.') if isShip: tech = player.shipDesigns[techID] if tech.upgradeTo: raise GameException("You cannot build obsolete ship design.") else: tech = Rules.techs[techID] if not (tech.isStructure or tech.isProject): raise GameException('You cannot construct this technology.') if not tech.validateConstrHandler(tran, obj, tran.db[targetID], tech): raise GameException('Conditions for construction are not satisfied.') neededSR = {} for sr in tech.buildSRes: if player.stratRes.get(sr, 0) < neededSR.get(sr, 0) + quantity: raise GameException("You do not own required strategic resource(s)") neededSR[sr] = neededSR.get(sr, 0) + quantity # consume strategic resources for sr in neededSR: player.stratRes[sr] -= neededSR[sr] # start construction item = IDataHolder() item.techID = techID item.currProd = 0 item.currTurn = 0 item.quantity = int(quantity) item.targetID = targetID item.changePerc = 0 item.isShip = bool(isShip) item.reportFin = bool(reportFinished) item.demolishStruct = demolishStruct item.type = T_TASK obj.prodQueue.append(item) return obj.prodQueue, player.stratRes
def makeShipMinSpec(player, name, hullID, eqIDs, improvements, raiseExs=True): ship = makeShipFullSpec(player, name, hullID, eqIDs, improvements, raiseExs) # make 'real' ship spec spec = IDataHolder() spec.type = Const.T_SHIP spec.name = ship.name spec.hullID = ship.hullID spec.level = ship.level spec.eqIDs = ship.eqIDs spec.improvements = ship.improvements spec.combatClass = ship.combatClass spec.signature = ship.signature spec.scannerPwr = ship.scannerPwr spec.speed = ship.speed spec.battleSpeed = ship.battleSpeed spec.maxHP = ship.maxHP spec.shieldHP = ship.shieldHP spec.combatAtt = ship.combatAtt spec.combatDef = ship.combatDef spec.missileDef = ship.missileDef spec.storEn = ship.storEn spec.operEn = ship.operEn spec.buildProd = ship.buildProd spec.buildSRes = ship.buildSRes spec.weaponIDs = ship.weaponIDs spec.deployStructs = ship.deployStructs spec.deployHandlers = ship.deployHandlers spec.built = 0 spec.buildTurns = 1 spec.upgradeTo = 0 spec.isMilitary = ship.isMilitary spec.baseExp = ship.baseExp spec.combatPwr = ship.combatPwr spec.autoRepairFix = ship.autoRepairFix spec.autoRepairPerc = ship.autoRepairPerc spec.shieldRechargeFix = ship.shieldRechargeFix spec.shieldRechargePerc = ship.shieldRechargePerc spec.hardShield = ship.hardShield spec.combatAttMultiplier = ship.combatAttMultiplier spec.damageAbsorb = ship.damageAbsorb return spec
def getSystemStructStats(data, client, db, systemID, processQueues=True): """ It go through all planets and structures, and creates IDataHolder object, with roster of buildings, surplus of bio and en. processQueues - if True, it go through all buildQueues and adjust all statistics as it would be all done already. Returns IDataHolder with parameters: .bio - system surplus of biomass .en - system surplus of en .planets - dictionary, keys are planetIDs of players or free planets, and values are dictionaries (huh) with keys being techIDs and values being number of those structs. """ systemStats = IDataHolder() system = db[systemID] player = client.getPlayer() myPlanets = set(system.planets) & data.myPlanets systemStats.planets = {} for planetID in myPlanets: systemStats.planets[planetID] = {} for planetID in set(system.planets) & data.freePlanets: systemStats.planets[planetID] = {} # creation of the .planets dictionary for planetID in myPlanets: planet = db[planetID] for techID, hp, something, eff in planet.slots: try: systemStats.planets[planetID][techID] += 1 except KeyError: systemStats.planets[planetID][techID] = 1 if not processQueues: # do not look into the queue continue for task in getattr(planet, 'prodQueue', []): if not task.isShip: techID = task.techID tech = client.getFullTechInfo(task.techID) if tech.isStructure: if task.targetID not in systemStats.planets.keys(): continue try: systemStats.planets[task.targetID][techID] += 1 except KeyError: systemStats.planets[task.targetID][techID] = 1 if task.demolishStruct: try: systemStats.planets[task.targetID][task.demolishStruct] -= 1 except KeyError: systemStats.planets[task.targetID][task.demolishStruct] = -1 # by parsing .planets object, fill the .bio and .en parameters systemStats.bio = 0 systemStats.en = 0 for planetID in systemStats.planets: planet = db[planetID] if planetID not in myPlanets: continue for techID in systemStats.planets[planetID]: quantity = systemStats.planets[planetID][techID] deltaBio, deltaEn, deltaProd = getSystemStatsChange(client, db, techID, planetID, 0) tech = client.getFullTechInfo(techID) systemStats.en += quantity * deltaEn systemStats.bio += quantity * deltaBio return systemStats