Пример #1
0
	def getScanInfos(self, tran, obj, scanPwr, player):
		if obj.owner == player.oid:
			return []
		if scanPwr >= Rules.level1InfoScanPwr:
			result = IDataHolder()
			result._type = T_SCAN
			result.scanPwr = scanPwr
			result.oid = obj.oid
			result.x = obj.x
			result.y = obj.y
			result.oldX = obj.oldX
			result.oldY = obj.oldY
			result.eta = obj.eta
			result.signature = obj.signature
			result.type = obj.type
			result.orbiting = obj.orbiting
			if obj.orbiting == OID_NONE and obj.actionIndex < len(obj.actions):
				target = obj.actions[obj.actionIndex][1]
				targetObj = tran.db[target]
				if targetObj.type == T_PLANET:
					result.target = targetObj.compOf
				else:
					result.target = target
		else:
			return []
		if scanPwr >= Rules.level2InfoScanPwr:
			result.owner = obj.owner
			if obj.customname:
				result.name = obj.customname
			else:
				result.name = obj.name
		if scanPwr >= Rules.level3InfoScanPwr:
			result.isMilitary = obj.isMilitary
			result.combatPwr = obj.combatPwr
		if scanPwr >= Rules.level4InfoScanPwr:
			# provide less information
			result.shipScan = {}
			owner = tran.db[obj.owner]
			for designID, hp, shield, exp in obj.ships:
				tech = owner.shipDesigns[designID]
				key = tech.name, tech.combatClass, tech.isMilitary
				result.shipScan[key] = result.shipScan.get(key, 0) + 1
		if scanPwr >= Rules.partnerScanPwr:
			result.scannerPwr = obj.scannerPwr
			result.allowmerge = obj.allowmerge
			result.customname = obj.customname
			result.name = obj.name
		return [result]
Пример #2
0
    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
Пример #3
0
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
Пример #4
0
 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
Пример #5
0
    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
Пример #6
0
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
Пример #7
0
	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
Пример #8
0
 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
Пример #9
0
	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
Пример #10
0
            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()
Пример #11
0
    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
Пример #12
0
	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
Пример #13
0
def initTechnologies(path):
	"""Init technologies from XML files in the path"""
	# holder for all technologies
	techs = {}
	# holder for tech IDs
	Tech = IDataHolder()

	# compute checksum
	file = sys.modules[__name__].__file__
	forceLoad = 0
	if os.path.exists(file):
		# regular module
		chsum = sha.new()
		os.path.walk(path, chsumDir, chsum)
	else:
		# packed, cannot access xml specifications
		path = os.path.join('res', 'rules/standard')
		forceLoad = 1

	# read old checksum
	try:
		fh = open(os.path.join(path, 'checksum'), 'rb')
		oldChsum = fh.read()
		fh.close()
	except IOError:
		oldChsum = ''

	# compare
	if forceLoad or chsum.hexdigest() == oldChsum:
		# load old definitions
		log.message('Loading stored specifications from', path)
		techs = pickle.load(open(os.path.join(path, 'techs.spf'), 'rb'))
		Tech = pickle.load(open(os.path.join(path, 'Tech.spf'), 'rb'))

		log.message("There is %d technologies" % len(techs))

		# clean up 'type' in lists
		for key in attrs.keys():
			if type(attrs[key]) == types.ListType and len(attrs[key]) == 1:
				log.debug("Cleaning up", key)
				attrs[key] = []
		return techs, Tech
	# create new ones
	## load technologies definitions

	def processDir(arg, dirname, names):
		if dirname.find(".svn") >= 0:
			log.message("Skipping directory", dirname)
			return
		log.message('Loading XML files from', dirname)
		names.sort()
		for filename in names:
			if os.path.splitext(filename)[1] == '.xml':
				log.message('Parsing XML file', filename)
				contentHandler = TechTreeContentHandler()
				contentHandler.setGlobals(techs, Tech)
				xml.sax.parse(os.path.join(dirname, filename), contentHandler)

	# collect xml files
	os.path.walk(path, processDir, None)

	# clean up 'type' in lists
	for key in attrs.keys():
		if type(attrs[key]) == types.ListType and len(attrs[key]) == 1:
			log.debug("Cleaning up", key)
			attrs[key] = []

	# link tech tree using researchRequires fields
	# construct researchEnables fields
	log.message('Converting symbolic fields...')
	for techID in techs.keys():
		tech = techs[techID]
		# convert symbolic names to numbers
		techIDs = []
		for techSymName in tech.researchRequires:
			#@log.debug('Converting REQ', techSymName)
			symName, improvement = techSymName.split('-')
			techIDs.append((getattr(Tech, symName), int(improvement)))
		tech.researchRequires = techIDs
		techIDs = {1: [], 2:[], 3:[], 4:[], 5:[], 6:[]}
		for techSymName in tech.researchEnables:
			#@log.debug('Converting EN', techSymName)
			improvement, symName = techSymName.split('-')
			techIDs[int(improvement)].append(getattr(Tech, symName))
		tech.researchEnables = techIDs
		techIDs = []
		for techSymName in tech.researchDisables:
			techIDs.append(getattr(Tech, techSymName))
		tech.researchDisables = techIDs
		techIDs = []
		if tech.unpackStruct:
			tech.unpackStruct = getattr(Tech, tech.unpackStruct)
		else:
			tech.unpackStruct = 0
		# strat. resources
		stratRes = []
		for sr in tech.researchReqSRes:
			stratRes.append(getattr(Const, sr))
		tech.researchReqSRes = stratRes
		stratRes = []
		for sr in tech.buildSRes:
			stratRes.append(getattr(Const, sr))
		tech.buildSRes = stratRes
		# evaluate researchMod
		if tech.researchMod == "expr":
			tech.researchMod = 1.0
		else:
			tech.researchMod = eval(tech.researchMod)
		#~ # convert weapons
		#~ techIDs = []
		#~ for weaponName in tech.weapons:
			#~ techIDs.append(getattr(Tech, weaponName))
		#~ tech.weapons = techIDs

	# link
	log.message('Linking tech tree...')
	for techID in techs.keys():
		tech = techs[techID]
		#@log.debug(techID, 'Req', tech.researchRequires)
		#@log.debug(techID, 'En', tech.researchEnables)
		for tmpTechID, improvement in tech.researchRequires:
			if techID not in techs[tmpTechID].researchEnables[improvement]:
				#@log.debug('Adding', tmpTechID, improvement, 'ENABLES', techID)
				techs[tmpTechID].researchEnables[improvement].append(techID)
		for improvement in tech.researchEnables.keys():
			for tmpTechID in tech.researchEnables[improvement]:
				if (techID, improvement) not in techs[tmpTechID].researchRequires:
					#@log.debug('Adding', tmpTechID, 'REQUIRES', techID, improvement)
					techs[tmpTechID].researchRequires.append((techID, improvement))

	changed = 1
	while changed:
		changed = 0
		log.debug("Tech disable iteration")
		for techID in techs:
			tech = techs[techID]
			for tech2ID in tech.researchDisables:
				tech2 = techs[tech2ID]
				if techID not in tech2.researchDisables and techID != tech2ID:
					tech2.researchDisables.append(techID)
					changed = 1
					log.debug("Adding", tech2ID, "DISABLES", techID, ", NOW", tech2.researchDisables)
				for tech3ID in tech2.researchDisables:
					tech3 = techs[tech3ID]
					if tech3ID not in tech.researchDisables and tech3ID != techID:
						tech.researchDisables.append(tech3ID)
						changed = 1
						log.debug("Adding", techID, "DISABLES", tech3ID, "NOW", tech.researchDisables)
	# just for debug
	#for techID in techs.keys():
	#	tech = techs[techID]
	#	log.debug('Link:', techID, tech.isStarting, tech.researchRequires, tech.researchEnables)

	# save new specification
	log.message('Saving specification...')
	pickle.dump(techs, open(os.path.join(path, 'techs.spf'), 'wb'), 1)
	pickle.dump(Tech, open(os.path.join(path, 'Tech.spf'), 'wb'), 1)
	fh = open(os.path.join(path, 'checksum'), 'wb')
	fh.write(chsum.hexdigest())
	fh.close()

	log.message("There is %d technologies" % len(techs))

	return techs, Tech
Пример #14
0
 def new(self, type):
     obj = IDataHolder()
     self._cmd[type].init(obj)
     return obj
Пример #15
0
 def getPublicInfo(self, tran, obj):
     result = IDataHolder()
     result.oid = obj.oid
     return result
Пример #16
0
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
Пример #17
0
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
Пример #18
0
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
Пример #19
0
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