Completed
Push — master ( 994cf3...bb27bc )
by Marek
17s queued 14s
created

ige.ospace.ISystem.ISystem.cmpPlanetByEnergy()   A

Complexity

Conditions 1

Size

Total Lines 4
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nop 4
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
#
2
#  Copyright 2001 - 2016 Ludek Smid [http://www.ospace.net/]
3
#
4
#  This file is part of Outer Space.
5
#
6
#  Outer Space is free software; you can redistribute it and/or modify
7
#  it under the terms of the GNU General Public License as published by
8
#  the Free Software Foundation; either version 2 of the License, or
9
#  (at your option) any later version.
10
#
11
#  Outer Space is distributed in the hope that it will be useful,
12
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
#  GNU General Public License for more details.
15
#
16
#  You should have received a copy of the GNU General Public License
17
#  along with Outer Space; if not, write to the Free Software
18
#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
#
20
import random
21
import copy
22
23
from xml.dom.minidom import Node
24
25
import ige
26
import Rules
27
import Utils
28
29
from Const import *
30
from ige import log
31
from ige.IObject import IObject, public
32
from ige.IDataHolder import IDataHolder
33
34
class ISystem(IObject):
35
36
    typeID = T_SYSTEM
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable T_SYSTEM does not seem to be defined.
Loading history...
37
38
    def init(self, obj):
39
        IObject.init(self, obj)
40
        #
41
        obj.x = 0.0
42
        obj.y = 0.0
43
        obj.planets = []
44
        obj.fleets = []
45
        obj.closeFleets = []
46
        obj.starClass = u'---' # Star clasification
47
        obj.signature = 100
48
        # rotation
49
        #~ obj.dist = 0.0
50
        #~ obj.dAngle = 0.0
51
        #~ obj.sAngle = 0.0
52
        # renaming
53
        obj.lastNameChng = 0
54
        # combat
55
        obj.combatCounter = 0
56
        # system wide data
57
        obj.scannerPwrs = {}
58
        # mine field
59
        obj.minefield = {}  # for every owner (key) list of minefield (triplet) exists (mine_id, amount, last_deployed)
60
61
    def update(self, tran, obj):
62
        # check existence of all planets
63
        if 0:
64
            for planetID in obj.planets:
65
                if not tran.db.has_key(planetID):
66
                    log.debug("CONSISTENCY - planet %d from system %d does not exists" % (planetID, obj.oid))
67
                elif tran.db[planetID].type != T_PLANET:
68
                    log.debug("CONSISTENCY - planet %d from system %d is not a T_PLANET" % (planetID, obj.oid))
69
        if not hasattr(obj,'minefield'):
70
            obj.minefield = {}
71
        # TODO: only needed for 0.5.72 update
72
        old_minefields = False
73
        for ownerID in obj.minefield:
74
            if obj.minefield[ownerID] and type(obj.minefield[ownerID][0]) is not tuple:
75
                old_minefields = True
76
        if old_minefields:
77
            for ownerID in obj.minefield:
78
                temp_mine_dict = {}
79
                for mine_id in obj.minefield[ownerID]:
80
                    try:
81
                        temp_mine_dict[mine_id] += 1
82
                    except KeyError:
83
                        temp_mine_dict[mine_id] = 1
84
                # now translate dictionary into list of tuples
85
                owners_minefields = []
86
                turn = tran.db[OID_UNIVERSE].turn
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable OID_UNIVERSE does not seem to be defined.
Loading history...
87
                for mine_id, amount in temp_mine_dict.iteritems():
88
                    owners_minefields.append((mine_id, amount, turn))
89
                obj.minefield[ownerID] = owners_minefields
90
91
        # check that all .fleet are in .closeFleets
92
        for fleetID in obj.fleets:
93
            if fleetID not in obj.closeFleets:
94
                log.debug("CONSISTENCY - fleet %d is in .fleet but not in .closeFleets - adding" % fleetID)
95
                obj.closeFleets.append(fleetID)
96
        # check existence of all fleets
97
        for fleetID in obj.closeFleets:
98
            if not tran.db.has_key(fleetID):
99
                log.debug("CONSISTENCY - fleet %d from system %d does not exists" % (fleetID, obj.oid))
100
            elif tran.db[fleetID].type not in (T_FLEET, T_ASTEROID):
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable T_FLEET does not seem to be defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable T_ASTEROID does not seem to be defined.
Loading history...
101
                log.debug("CONSISTENCY - fleet %d from system %d is not a T_FLEET" % (fleetID, obj.oid))
102
        # delete nonexistent fleets
103
        index = 0
104
        while index < len(obj.closeFleets) and obj.closeFleets:
105
            fleet = tran.db.get(obj.closeFleets[index], None)
106
            if fleet == None:
107
                log.debug("CONSISTENCY - fleet %d does not exists" % obj.closeFleets[index])
108
                fleetID = obj.closeFleets[index]
109
                obj.closeFleets.remove(fleetID)
110
                obj.fleets.remove(fleetID)
111
            else:
112
                index += 1
113
        # check compOf
114
        if not tran.db.has_key(obj.compOf) or tran.db[obj.compOf].type != T_GALAXY:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable T_GALAXY does not seem to be defined.
Loading history...
115
            log.debug("CONSISTENCY invalid compOf for system", obj.oid)
116
        # rebuild closeFleets attribute
117
        old = obj.closeFleets
118
        obj.closeFleets = []
119
        for fleetID in old:
120
            fleet = tran.db.get(fleetID, None)
121
            if fleet and fleet.closeSystem == obj.oid and fleetID not in obj.closeFleets:
122
                obj.closeFleets.append(fleetID)
123
        if old != obj.closeFleets:
124
            log.debug("System close fleets fixed", obj.oid, old, obj.closeFleets)
125
        # TODO: remove, no need to start players on random systems
126
        # try to find starting planets
127
        #starting = 0
128
        #free = 1
129
        #for planetID in obj.planets:
130
        #    planet = tran.db[planetID]
131
        #    if planet.plStarting:
132
        #        starting = planetID
133
        #    if planet.owner != OID_NONE:
134
        #        free = 0
135
        #if starting and free:
136
        #    # good starting position
137
        #    #@log.debug("Found starting position", obj.oid, starting)
138
        #    # get galaxy
139
        #    galaxy = tran.db[obj.compOf]
140
        #    if starting not in galaxy.startingPos:
141
        #        log.debug("Adding to starting positions of galaxy", galaxy.oid)
142
        #        galaxy.startingPos.append(starting)
143
        # check if system has planets
144
        hasHabitable = 0
145
        for planetID in obj.planets:
146
            if tran.db[planetID].plSlots > 0:
147
                hasHabitable = 1
148
                break
149
        if (not obj.planets or not hasHabitable) and obj.starClass[0] != "b" and obj.starClass != "wW0":
150
            log.debug("No planet for system", obj.oid, obj.name, obj.starClass)
151
            # delete old planets
152
            for planetID in obj.planets:
153
                del tran.db[planetID]
154
            obj.planets = []
155
            # find matching systems
156
            avail = []
157
            for systemID in tran.db[obj.compOf].systems:
158
                system = tran.db[systemID]
159
                if system.starClass[1] == obj.starClass[1] \
160
                    or (obj.starClass[1] == "G" and system.starClass[1] == "F"):
161
                    ok = 0
162
                    for planetID in system.planets:
163
                        planet = tran.db[planetID]
164
                        if planet.plStarting:
165
                            ok = 0
166
                            break
167
                        if planet.plSlots > 0:
168
                            ok = 1
169
                    if ok and system.planets:
170
                        avail.append(systemID)
171
            # select random system
172
            log.debug("Can copy", avail)
173
            try:
174
                systemID = random.choice(avail)
175
                # copy it
176
                log.debug("Will copy system", systemID)
177
                nType = Utils.getPlanetNamesType()
178
                orbit = 1
179
                for planetID in tran.db[systemID].planets:
180
                    orig = tran.db[planetID]
181
                    planet = tran.db[self.createPlanet(tran, obj)]
182
                    planet.name = Utils.getPlanetName(obj.name, nType, orbit - 1)
183
                    planet.x = obj.x
184
                    planet.y = obj.y
185
                    planet.plDiameter = orig.plDiameter
186
                    planet.plType = orig.plType
187
                    planet.plMin = orig.plMin
188
                    planet.plBio = orig.plBio
189
                    planet.plEn = orig.plEn
190
                    planet.plEnv = orig.plEnv
191
                    planet.plSlots = orig.plSlots
192
                    planet.plMaxSlots = orig.plMaxSlots
193
                    planet.plStratRes = 0
194
                    planet.plDisease = 0
195
                    planet.plStarting = 0
196
                    planet.orbit = orbit
197
                    planet.storPop = 0
198
                    planet.slots = []
199
                    orbit += 1
200
            except:
201
                log.debug("Copy failed")
202
        # TODO: remove in version 0.5.73
203
        if True:
204
            owners = []
205
            for planetID in obj.planets:
206
                planet = tran.db[planetID]
207
                if planet.owner not in owners + [OID_NONE]:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable OID_NONE does not seem to be defined.
Loading history...
208
                    owners.append(planet.owner)
209
            for owner_id in owners:
210
                for tech, struct in self.getSystemMineLauncher(tran, obj, owner_id):
211
                    if not struct[STRUCT_IDX_STATUS] & STRUCT_STATUS_ON:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable STRUCT_IDX_STATUS does not seem to be defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable STRUCT_STATUS_ON does not seem to be defined.
Loading history...
212
                        # structure is offline, reset timer
213
                        self.addMine(tran, obj, owner_id, tech.mineclass, 0)
214
                        continue
215
                    efficiency = struct[STRUCT_IDX_HP] / float(tech.maxHP)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable STRUCT_IDX_HP does not seem to be defined.
Loading history...
216
                    minenum = int(tech.minenum * efficiency)
217
                    # by setting minerate to None, we are forcing a creation of one - so it grabs
218
                    # galaxyTurn instead of universe.turn
219
                    if self.addMine(tran, obj, owner_id, tech.mineclass, None, None):
220
                        log.debug('ISystem', 'Mine timer reset for owner %d in system %d' % (owner_id, obj.oid))
221
222
    update.public = 0
223
224
    def getReferences(self, tran, obj):
225
        return obj.planets
226
227
    getReferences.public = 0
228
229
    def getScanInfos(self, tran, obj, scanPwr, player):
230
        result = IDataHolder()
231
        results = [result]
232
        if scanPwr >= Rules.level1InfoScanPwr:
233
            result._type = T_SCAN
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable T_SCAN does not seem to be defined.
Loading history...
234
            result.scanPwr = scanPwr
235
            result.oid = obj.oid
236
            result.x = obj.x
237
            result.y = obj.y
238
            if hasattr(obj, 'destinationOid'):
239
                result.destinationOid = obj.destinationOid
240
            # multiply by 1000 to increase accuracy
241
            #~ result.dist = obj.dist * 1000
242
            #~ result.dAngle = obj.dAngle * 1000
243
            #~ result.sAngle = obj.sAngle * 1000
244
            result.signature = obj.signature
245
            result.type = obj.type
246
            result.compOf = obj.compOf
247
            result.starClass = obj.starClass
248
        if scanPwr >= Rules.level2InfoScanPwr:
249
            result.name = obj.name
250
            result.combatCounter = obj.combatCounter
251
        if scanPwr >= Rules.level3InfoScanPwr:
252
            result.planets = obj.planets
253
            result.owner = obj.owner
254
            for planetID in obj.planets:
255
                planet = tran.db[planetID]
256
                if planet.owner == player: ####### This was player.owner, which made no sense. Hope this change doesn't break something
257
                    continue
258
                newPwr = scanPwr * planet.signature / obj.signature
259
                results.extend(self.cmd(planet).getScanInfos(tran, planet, newPwr, player))
260
        if scanPwr >= Rules.level4InfoScanPwr:
261
            result.fleets = obj.fleets
262
            for fleetID in obj.fleets:
263
                fleet = tran.db[fleetID]
264
                if fleet.owner == player:
265
                    continue
266
                newPwr = scanPwr * fleet.signature / obj.signature
267
                results.extend(self.cmd(fleet).getScanInfos(tran, fleet, newPwr, player))
268
            result.hasmines = 0 # no
269
            if len(obj.minefield) > 0:
270
                result.hasmines = 1 # yes
271
            result.minefield = self.getMines(obj, player.oid) # only shows mines you own
272
            if len(obj.minefield) > 1 or (len(obj.minefield) == 1 and len(result.minefield) == 0):
273
                result.hasmines = 2 # yes, and some aren't my mines
274
        return results
275
276
    @public(AL_ADMIN)
277
    def processINITPhase(self, tran, obj, data):
278
        obj.scannerPwrs = {}
279
280
        return obj.planets
281
282
    @public(AL_ADMIN)
283
    def processPRODPhase(self, tran, obj, data):
284
        # mine deployment
285
        owners = []
286
        for planetID in obj.planets:
287
            planet = tran.db[planetID]
288
            if planet.owner not in owners + [OID_NONE]:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable OID_NONE does not seem to be defined.
Loading history...
289
                owners.append(planet.owner)
290
        for owner_id in owners:
291
            self.deployMines(tran, obj, owner_id)
292
        return obj.planets
293
294
    @public(AL_ADMIN)
295
    def processACTIONPhase(self, tran, obj, data):
296
        # distribute resources
297
        planets = {}
298
        # group planets by owner
299
        for planetID in obj.planets:
300
            planet = tran.db[planetID]
301
            if planet.owner != OID_NONE:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable OID_NONE does not seem to be defined.
Loading history...
302
                tmp = planets.get(planet.owner, [])
303
                tmp.append(planet)
304
                planets[planet.owner] = tmp
305
        # group planets if owners are allied
306
        # TODO
307
        # process each group
308
        for owner in planets.keys():
309
            # skip alone planets
310
            if len(planets[owner]) < 2:
311
                continue
312
            # process each resource
313
            for resName in ('Bio', 'En'):
314
                donors = []
315
                donees = []
316
                minRes = 'min%s' % resName
317
                maxRes = 'max%s' % resName
318
                storRes = 'stor%s' % resName
319
                donorsSum = 0
320
                doneesSum = 0
321
                # put planets into donors/donees
322
                for planet in planets[owner]:
323
                    if getattr(planet, storRes) > getattr(planet, minRes):
324
                        donors.append(planet)
325
                        donorsSum += getattr(planet, storRes) - getattr(planet, minRes)
326
                    elif getattr(planet, storRes) < getattr(planet, minRes):
327
                        donees.append(planet)
328
                        doneesSum += getattr(planet, minRes) - getattr(planet, storRes)
329
                #@log.debug('ISystem', obj.oid, 'Donors / donees for %s' % resName, donorsSum, doneesSum)
330
                # there are requests for donation and there is somebody able to donate
331
                if doneesSum > 0 and donorsSum > 0:
332
                    #@log.debug('ISystem', 'Redistributin %s for' % resName, owner)
333
                    # give
334
                    balance = 0
335
                    tmpRatio = min(float(doneesSum) / donorsSum, 1.0)
336
                    for planet in donees:
337
                        diff = getattr(planet, minRes) - getattr(planet, storRes)
338
                        amount = int(float(diff) / doneesSum * donorsSum * tmpRatio)
339
                        #@log.debug('ISystem', 'Give res', planet.oid, amount)
340
                        balance -= amount
341
                        setattr(planet, storRes, getattr(planet, storRes) + amount)
342
                    # take
343
                    assert donorsSum + balance >= 0
344
                    lastPlanet = None
345
                    tmpRatio = min(float(donorsSum) / doneesSum, 1.0)
346
                    for planet in donors:
347
                        diff = getattr(planet, storRes) - getattr(planet, minRes)
348
                        amount = int(float(diff) / donorsSum * doneesSum * tmpRatio)
349
                        balance += amount
350
                        #@log.debug('ISystem', 'Take res', planet.oid, amount)
351
                        setattr(planet, storRes, getattr(planet, storRes) - amount)
352
                        lastPlanet = planet
353
                    # fix rounding error
354
                    setattr(lastPlanet, storRes, getattr(lastPlanet, storRes) + balance)
355
                    #@log.debug('ISystem', 'Rounding error', balance)
356
                # try to move additional resources to the other planets
357
                for planet in planets[owner]:
358
                    if getattr(planet, storRes) > getattr(planet, maxRes):
359
                        excess = getattr(planet, storRes) - getattr(planet, maxRes)
360
                        #@log.debug('ISystem', 'Trying to move excess rsrcs from', planet.oid, excess)
361
                        for planet2 in planets[owner]:
362
                            if planet == planet2:
363
                                continue
364
                            if getattr(planet2, storRes) < getattr(planet2, maxRes):
365
                                space = getattr(planet2, maxRes) - getattr(planet2, storRes)
366
                                amount = min(space, excess)
367
                                #@log.debug('ISystem', 'Moved to', planet2.oid, amount)
368
                                setattr(planet2, storRes, getattr(planet2, storRes) + amount)
369
                                excess -= amount
370
                                if excess == 0:
371
                                    break
372
                        #@log.debug('ISystem', 'Cannot move excess rsrcs on', planet.oid, excess)
373
                        setattr(planet, storRes, getattr(planet, maxRes) + excess)
374
        #~ # rotate system around the galaxy core
375
        #~ #log.debug("Rotate, old coords", obj.x, obj.y)
376
        #~ turn = tran.db[OID_UNIVERSE].turn
377
        #~ galaxy = tran.db[obj.compOf]
378
        #~ angle = obj.sAngle + (turn / Rules.rotationMod) * obj.dAngle
379
        #~ obj.x = galaxy.x + obj.dist * math.cos(angle)
380
        #~ obj.y = galaxy.y + obj.dist * math.sin(angle)
381
        #~ #log.debug("Rotate, new coords", obj.x, obj.y)
382
        #~ # change positions of planets and orbitting fleets
383
        #~ for planetID in obj.planets:
384
            #~ planet = tran.db[planetID]
385
            #~ planet.x = obj.x
386
            #~ planet.y = obj.y
387
        #~ for fleetID in obj.fleets:
388
            #~ fleet = tran.db[fleetID]
389
            #~ fleet.x = obj.x
390
            #~ fleet.y = obj.y
391
        # process planets and fleets
392
        #@log.debug("System close fleets", obj.oid, obj.closeFleets)
393
        return obj.planets[:] + obj.closeFleets[:]
394
395
    @public(AL_ADMIN)
396
    def getObjectsInSpace(self, tran, obj):
397
        inSpace = obj.closeFleets[:]
398
        for fleetID in obj.fleets:
399
            try:
400
                inSpace.remove(fleetID)
401
            except ValueError:
402
                log.warning(obj.oid, "Cannot remove fleet from closeFleets", fleetID, obj.fleets, obj.closeFleets)
403
        return inSpace
404
405
    @public(AL_ADMIN)
406
    def processBATTLEPhase(self, tran, obj, data):
407
        system = obj
408
        #@log.debug('ISystem', 'BATTLE - system', obj.oid)
409
        # we are processing fleets, planets, ...
410
        objects = obj.planets[:] + obj.fleets[:]
411
        # shuffle them to prevent predetermined one-sided battles (temporary hack)
412
        random.shuffle(objects)
413
        # store owners of objects
414
        # find enemies and allies
415
        attack = {}
416
        allies = {}
417
        owners = {}
418
        ownerIDs = {}
419
        systemAtt = {}
420
        systemDef = {}
421
        hasMine = {}
422
        isOwnedObject = 0
423
        for objID in objects:
424
            attack[objID] = []
425
            allies[objID] = []
426
            owner = tran.db[objID].owner
427
            owners[objID] = owner
428
            ownerIDs[owner] = owner
429
            if owner != OID_NONE:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable OID_NONE does not seem to be defined.
Loading history...
430
                isOwnedObject = 1
431
        for owner in ownerIDs:
432
            tempAtt, tempDef = self.getSystemCombatBonuses(tran, system, owner)
433
            systemAtt[owner] = tempAtt
434
            systemDef[owner] = tempDef
435
            hasMine[owner] = self.getSystemMineSource(tran, system, owner)
436
        if not isOwnedObject:
437
            #@log.debug('ISystem', 'No combat')
438
            # reset combat counters
439
            system.combatCounter = 0
440
            return
441
        # first - direct ones
442
        index = 1
443
        for obj1ID in objects:
444
            obj1 = tran.db[obj1ID]
445
            if obj1.owner == OID_NONE:
446
                index += 1
447
                continue
448
            commander = tran.db[obj1.owner]
449
            # relationships
450
            #for obj2ID in objects[index:]:
451
            for obj2ID in objects:
452
                obj2 = tran.db[obj2ID]
453
                if obj2.owner == OID_NONE or obj1 is obj2:
454
                    continue
455
                if obj1.owner == obj2.owner:
456
                    allies[obj1ID].append(obj2ID)
457
                    allies[obj2ID].append(obj1ID)
458
                    continue
459
                # planet and military object
460
                elif obj1.type == T_PLANET and obj2.isMilitary and \
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable T_PLANET does not seem to be defined.
Loading history...
461
                    not self.cmd(commander).isPactActive(tran, commander, obj2.owner, PACT_ALLOW_MILITARY_SHIPS):
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable PACT_ALLOW_MILITARY_SHIPS does not seem to be defined.
Loading history...
462
                    #@log.debug("ISystem pl - mil", obj1ID, obj2ID)
463
                    if obj2ID not in attack[obj1ID]:
464
                        attack[obj1ID].append(obj2ID)
465
                    if obj1ID not in attack[obj2ID]:
466
                        attack[obj2ID].append(obj1ID)
467
                # planet and civilian object
468
                elif obj1.type == T_PLANET and not obj2.isMilitary and \
469
                    not self.cmd(commander).isPactActive(tran, commander, obj2.owner, PACT_ALLOW_CIVILIAN_SHIPS):
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable PACT_ALLOW_CIVILIAN_SHIPS does not seem to be defined.
Loading history...
470
                    #@log.debug("ISystem pl - civ", obj1ID, obj2ID)
471
                    if obj2ID not in attack[obj1ID]:
472
                        attack[obj1ID].append(obj2ID)
473
                    if obj1ID not in attack[obj2ID]:
474
                        attack[obj2ID].append(obj1ID)
475
                # military and military object
476
                elif obj1.isMilitary and obj2.isMilitary and \
477
                    not self.cmd(commander).isPactActive(tran, commander, obj2.owner, PACT_ALLOW_MILITARY_SHIPS):
478
                    #@log.debug("ISystem mil - mil", obj1ID, obj2ID)
479
                    if obj2ID not in attack[obj1ID]:
480
                        attack[obj1ID].append(obj2ID)
481
                    if obj1ID not in attack[obj2ID]:
482
                        attack[obj2ID].append(obj1ID)
483
                # military and civilian object
484
                elif obj1.isMilitary and not obj2.isMilitary and \
485
                    not self.cmd(commander).isPactActive(tran, commander, obj2.owner, PACT_ALLOW_CIVILIAN_SHIPS):
486
                    #@log.debug("ISystem mil - civ", obj1ID, obj2ID)
487
                    if obj2ID not in attack[obj1ID]:
488
                        attack[obj1ID].append(obj2ID)
489
                    if obj1ID not in attack[obj2ID]:
490
                        attack[obj2ID].append(obj1ID)
491
                # planet and fleet
492
                #elif obj1.type == T_PLANET and obj2.type == T_FLEET and \
493
                #    self.cmd(commander).isPactActive(tran, commander, obj2.owner, PACT_MUTUAL_DEFENCE):
494
                #    allies[obj1ID].append(obj2ID)
495
                #    allies[obj2ID].append(obj1ID)
496
                # fleet and fleet
497
                #elif obj1.type == T_FLEET and obj2.type == T_FLEET and \
498
                #    self.cmd(commander).isPactActive(tran, commander, obj2.owner, PACT_MUTUAL_OFFENCE):
499
                #    allies[obj1ID].append(obj2ID)
500
                #    allies[obj2ID].append(obj1ID)
501
                # asteroid
502
                if obj2.type == T_ASTEROID:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable T_ASTEROID does not seem to be defined.
Loading history...
503
                    attack[obj1ID].append(obj2ID)
504
                    attack[obj2ID].append(obj1ID)
505
            index += 1
506
        #@log.debug('ISystem', 'Targets:', targets)
507
        #@log.debug('ISystem', 'Allies:', allies)
508
        # find indirect a/e
509
        #for objID in objects:
510
        #    iTargets = []
511
        #    iAllies = []
512
        #    # find indirect a/e
513
        #    todo = allies[objID][:]
514
        #    while todo:
515
        #        id = todo.pop(0)
516
        #        iTargets.extend(targets[id])
517
        #        for tmpID in allies[id]:
518
        #            if tmpID not in iAllies:
519
        #                todo.append(tmpID)
520
        #                iAllies.append(tmpID)
521
        #    # remove allies from targets
522
        #    for id in iAllies:
523
        #        if id in iTargets:
524
        #            iTargets.remove(id)
525
        #    # IMPORTATNT preffer NOT to fire at possible allies
526
        #    # add my targets
527
        #    #for id in targets[objID]:
528
        #    #    if id not in iTargets:
529
        #    #        iTargets.append(id)
530
        #    # that's all folks
531
        #    for id in iTargets:
532
        #        if objID not in attack[id]:
533
        #            attack[id].append(objID)
534
        #        if id not in attack[objID]:
535
        #            attack[objID].append(id)
536
        # NOT VALID: objects with action ACTION_ATTACK will attack only their targets
537
        # check, if there are any targets
538
        isCombat = 0
539
        for objID in objects:
540
            if attack[objID]:
541
                isCombat = 1
542
                break #end loop
543
        if not isCombat:
544
            #@log.debug('ISystem', 'No combat')
545
            # reset combat counters
546
            system.combatCounter = 0
547
            for fleetID in system.fleets:
548
                tran.db[fleetID].combatCounter = 0
549
            return
550
        # increase combat counters
551
        system.combatCounter += 1
552
        for fleetID in system.fleets:
553
            tran.db[fleetID].combatCounter += 1
554
        # debug
555
        log.debug('ISystem', 'Final attacks in system %d:' % system.oid, attack)
556
        # mines detonate before battle
557
        shots = {}
558
        targets = {}
559
        firing = {}
560
        damageCaused = {}
561
        killsCaused = {}
562
        damageTaken = {}
563
        shipsLost = {}
564
        minesTriggered = {}
565
        fleetOwners = {}
566
        isCombat = False
567
        isMineCombat = False
568
        for owner in ownerIDs:
569
            if owner not in hasMine: # no planets
570
                continue
571
            if not hasMine[owner]: # no planet with control structure
572
                continue
573
            controlPlanetID = hasMine[owner][0]  # there is list returned, all planets have same effect
574
            if len(self.getMines(system, owner)) == 0:
575
                continue # no mines, something broke
576
            if len(attack[controlPlanetID]) == 0:
577
                continue # no targets
578
            isMineFired = True
579
            mineTargets = copy.copy(attack[controlPlanetID])
580
            while isMineFired:
581
                while len(mineTargets) > 0:
582
                    targetID = random.choice(mineTargets) # select random target
583
                    targetobj = tran.db.get(targetID, None)
584
                    try:
585
                        if targetobj.type == T_FLEET:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable T_FLEET does not seem to be defined.
Loading history...
586
                            fleetOwners[targetID] = targetobj.owner
587
                            break # target found
588
                        mineTargets.remove(targetID)  # remove an object type that a mine can't hit from the temporary targets list
589
                    except:
590
                        mineTargets.remove(targetID)  # remove a dead fleet from the temporary targets list
591
592
                if len(mineTargets) == 0:
593
                    break # no fleet targets for mines
594
                temp, temp, firing[targetID] = self.cmd(targetobj).getPreCombatData(tran, targetobj)  # fix firing for "surrender to" section
0 ignored issues
show
introduced by
The variable targetobj does not seem to be defined for all execution paths.
Loading history...
595
                damage, att, ignoreshield, mineID = self.cmd(obj).fireMine(system, owner)
596
                if not damage: # no more mines
597
                    isMineFired = False
598
                    break
599
                log.debug('ISystem', 'Mine Shooting (damage, att, ignore shield):', damage, att, ignoreshield)
600
                isMineCombat = True
601
                minesTriggered[mineID] = minesTriggered.get(mineID, 0) + 1
602
                # Process Combat
603
                # for now we assume only one ship can be destroyed by one mine
604
                dmg, destroyed = self.cmd(targetobj).applyMine(tran, targetobj, att, damage, ignoreshield)
605
                #log.debug('ISystem-Mines', 'Actual Damage Done:',dmg)
606
                if dmg > 0:
607
                    damageTaken[targetID] = damageTaken.get(targetID, 0) + dmg
0 ignored issues
show
introduced by
The variable targetID does not seem to be defined for all execution paths.
Loading history...
608
                    shipsLost[targetID] = shipsLost.get(targetID, 0) + destroyed
609
                    killsCaused[mineID] = killsCaused.get(mineID, 0) + destroyed
610
                if dmg > 0:
611
                    damageCaused[mineID] = damageCaused.get(mineID, 0) + dmg
612
            # send messages about mine effects to the owner of the minefield
613
            # collect hit players
614
            players = {}
615
            for triggerID in firing.keys():
616
                players[owners[triggerID]] = None
617
            controllerPlanet = tran.db.get(controlPlanetID, None)
618
            damageCausedSum = 0
619
            killsCausedSum = 0
620
            for mineID in damageCaused.keys():
621
                damageCausedSum = damageCausedSum + damageCaused.get(mineID, 0)
622
                killsCausedSum = killsCausedSum + killsCaused.get(mineID, 0)
623
            Utils.sendMessage(tran, controllerPlanet, MSG_MINES_OWNER_RESULTS, system.oid, (players.keys(),(damageCaused, killsCaused, minesTriggered),damageCausedSum,killsCausedSum))
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable MSG_MINES_OWNER_RESULTS does not seem to be defined.
Loading history...
624
        # send messages to the players whose fleets got hit by minefields
625
        for targetID in damageTaken.keys():
626
            targetFleet = tran.db.get(targetID, None)
627
            if targetFleet:
628
                Utils.sendMessage(tran, targetFleet, MSG_MINES_FLEET_RESULTS, system.oid, (damageTaken[targetID], shipsLost[targetID]))
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable MSG_MINES_FLEET_RESULTS does not seem to be defined.
Loading history...
629
            else:
630
                targetFleet = IDataHolder()
631
                targetFleet.oid = fleetOwners[targetID]
632
                Utils.sendMessage(tran, targetFleet, MSG_MINES_FLEET_RESULTS, system.oid, (damageTaken[targetID], shipsLost[targetID]))
633
                Utils.sendMessage(tran, targetFleet, MSG_DESTROYED_FLEET, system.oid, ())
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable MSG_DESTROYED_FLEET does not seem to be defined.
Loading history...
634
        damageCaused = {}
635
        killsCaused = {}
636
        damageTaken = {}
637
        shipsLost = {}
638
        # now to battle
639
        for objID in objects:
640
            obj = tran.db.get(objID, None)
641
            # get shots from object, should be sorted by weaponClass
642
            # shots = [ shot, ...], shot = (combatAtt, weaponID)
643
            # get target classes and numbers
644
            # (class1, class2, class3, class4)
645
            # cls0 == fighters, cls1 == midships, cls2 == capital ships, cls3 == planet installations
646
            #@log.debug(objID, obj.name, "getting pre combat data")
647
            if obj: # source already destroyed; ignore
648
                shots[objID], targets[objID], firing[objID] = self.cmd(obj).getPreCombatData(tran, obj)
649
                if firing[objID]:
650
                    isCombat = True
651
        if not isCombat and not isMineCombat:
652
            # no shots has been fired
653
            #@log.debug('ISystem', 'No combat')
654
            # reset combat counters
655
            system.combatCounter = 0
656
            for fleetID in system.fleets:
657
                tran.db[fleetID].combatCounter = 0
658
            return
659
        #@log.debug("Shots:", shots)
660
        #@log.debug("Targets", targets)
661
        if isCombat:
662
            for shotIdx in (3, 2, 1, 0):
663
                for objID in objects:
664
                    # obj CAN be deleted at this point
665
                    obj = tran.db.get(objID, None)
666
                    if obj == None:
667
                        continue # source already destroyed; move to next source
668
                    # if object is fleet, then it's signature is max
669
                    if obj and obj.type == T_FLEET:
670
                        obj.signature = Rules.maxSignature
671
                    # target preselection
672
                    totalClass = [0, 0, 0, 0]
673
                    total = 0
674
                    for targetID in attack[objID]:
675
                        totalClass[0] += targets[targetID][0]
676
                        totalClass[1] += targets[targetID][1]
677
                        totalClass[2] += targets[targetID][2]
678
                        totalClass[3] += targets[targetID][3]
679
                    total = totalClass[0] + totalClass[1] + totalClass[2] + totalClass[3]
680
                    # process shots
681
                    for combatAtt, weaponID in shots[objID][shotIdx]:
682
                        weapon = Rules.techs[weaponID]
683
                        weaponClass = weapon.weaponClass
684
                        if total == 0:
685
                            # there are no targets
686
                            break
687
                        #@log.debug('ISystem', 'Processing shot', objID, weapon.name, weaponClass)
688
                        # process from weaponClass up
689
                        # never shoot on smaller ships than weaponClass
690
                        applied = 0
691
                        for tmpWpnClass in xrange(weaponClass, 4):
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable xrange does not seem to be defined.
Loading history...
692
                            #@log.debug('ISystem', 'Trying target class', tmpWpnClass, totalClass[tmpWpnClass])
693
                            # select target
694
                            if totalClass[tmpWpnClass]:
695
                                target = Utils.rand(0, totalClass[tmpWpnClass])
696
                                #@log.debug('ISystem', 'Target rnd num', target, totalClass[tmpWpnClass])
697
                                for targetID in attack[objID]:
698
                                    if target < targets[targetID][tmpWpnClass]:
699
                                        #@log.debug(objID, 'attacks', targetID, tmpWpnClass)
700
                                        # targetID can be deleted at this point
701
                                        anObj = tran.db.get(targetID, None)
702
                                        if anObj:
703
                                            dmg, destroyed, destroyedClass = self.cmd(anObj).applyShot(tran, anObj, systemDef[owners[targetID]], combatAtt + systemAtt[owners[objID]], weaponID, tmpWpnClass, target)
704
                                            #@log.debug("ISystem result", dmg, destroyed, destroyedClass, tmpWpnClass)
705
                                            #@print objID, 'dmg, destroyed', dmg, destroyed
706
                                            damageTaken[targetID] = damageTaken.get(targetID, 0) + dmg
707
                                            if destroyed > 0:
708
                                                shipsLost[targetID] = shipsLost.get(targetID, 0) + destroyed
709
                                                total -= destroyed
710
                                                totalClass[destroyedClass] -= destroyed
711
                                            if dmg > 0 and obj:
712
                                                obj.combatExp += dmg
713
                                                damageCaused[objID] = damageCaused.get(objID, 0) + dmg
714
                                            applied = 1
715
                                        else:
716
                                            continue # target already destroyed, move to next target
717
                                        break
718
                                    else:
719
                                        #@log.debug('ISystem', 'Lovering target by', targets[targetID][tmpWpnClass])
720
                                        target -= targets[targetID][tmpWpnClass]
721
                            if applied:
722
                                break
723
        # send messages and modify diplomacy relations
724
        # distribute experience pts
725
        for objID in objects:
726
            obj = tran.db.get(objID, None)
727
            if obj:
728
                self.cmd(obj).distributeExp(tran, obj)
729
            if attack[objID]:
730
                source = obj or tran.db[owners[objID]]
731
                # collect players
732
                players = {}
733
                for attackerID in attack[objID]:
734
                    players[owners[attackerID]] = None
735
                d1 = damageTaken.get(objID,0)
736
                d2 = damageCaused.get(objID,0)
737
                l = shipsLost.get(objID, 0)
738
                if d1 or d2 or l:
739
                    # send only if damage is taken/caused
740
                    Utils.sendMessage(tran, source, MSG_COMBAT_RESULTS, system.oid, (d1, d2, l, players.keys()))
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable MSG_COMBAT_RESULTS does not seem to be defined.
Loading history...
741
                if not obj:
742
                    # report DESTROYED status
743
                    Utils.sendMessage(tran, source, MSG_DESTROYED_FLEET, system.oid, ())
744
                # modify diplomacy relations
745
                objOwner = tran.db[owners[objID]]
746
                for attackerID in attack[objID]:
747
                    attOwner = tran.db.get(owners[attackerID], None)
748
                    # owner of the fleet
749
                    rel = self.cmd(objOwner).getDiplomacyWith(tran, objOwner, attOwner.oid)
750
                    rel.relChng = Rules.relLostWhenAttacked
751
                    # attacker
752
                    rel = self.cmd(attOwner).getDiplomacyWith(tran, attOwner, objOwner.oid)
753
                    rel.rechChng = Rules.relLostWhenAttacked
754
        # check if object surrenders
755
        for objID in objects:
756
            # object surrender IFF it and its allies had target and was not able
757
            # to fire at it, planet is not counted as ally in this case
758
            obj = tran.db.get(objID, None)
759
            if firing[objID] and obj:
760
                continue
761
            surrenderTo = []
762
            for attID in attack[objID]:
763
                if firing[attID] and tran.db.has_key(attID):
764
                    surrenderTo.append(tran.db[attID].owner)
765
            for allyID in allies[objID]:
766
                if not tran.db.has_key(allyID):
767
                    continue
768
                ally = tran.db[allyID]
769
                if firing[allyID] and ally.type != T_PLANET:
770
                    surrenderTo = []
771
                    break
772
            if surrenderTo:
773
                index = Utils.rand(0, len(surrenderTo))
774
                if obj:
775
                    if self.cmd(obj).surrenderTo(tran, obj, surrenderTo[index]):
776
                        winner = tran.db[surrenderTo[index]]
777
                        source = tran.db.get(owners[objID], None)
778
                        log.debug('ISystem', 'BATTLE - surrender', objID, surrenderTo[index], surrenderTo)
779
                        if source:
780
                            Utils.sendMessage(tran, source, MSG_COMBAT_LOST, system.oid, winner.oid)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable MSG_COMBAT_LOST does not seem to be defined.
Loading history...
781
                            Utils.sendMessage(tran, winner, MSG_COMBAT_WON, system.oid, source.oid)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable MSG_COMBAT_WON does not seem to be defined.
Loading history...
782
                        else:
783
                            Utils.sendMessage(tran, winner, MSG_COMBAT_WON, system.oid, obj.oid)
784
                else:
785
                    winner = tran.db[surrenderTo[index]]
786
                    source = tran.db[owners[objID]]
787
                    log.debug('ISystem', 'BATTLE - surrender', objID, surrenderTo[index], surrenderTo)
788
                    Utils.sendMessage(tran, source, MSG_COMBAT_LOST, system.oid, winner.oid)
789
                    Utils.sendMessage(tran, winner, MSG_COMBAT_WON, system.oid, source.oid)
790
        return
791
792
    @public(AL_ADMIN)
793
    def processFINALPhase(self, tran, obj, data):
794
        # TODO find new starting points
795
        # clean up mines if system ownership was lost
796
        owners = []
797
        for planetID in obj.planets:
798
            planet = tran.db[planetID]
799
            if planet.owner not in owners:
800
                owners.append(planet.owner)
801
        for ownerid in obj.minefield:
802
            if ownerid not in owners:
803
                self.clearMines(obj, ownerid)
804
        return obj.planets[:] + obj.closeFleets[:]
805
806
    def sortPlanets(self, tran, obj, data):
807
        obj.planets.sort(key=lambda planetID: tran.db[planetID].plEn, reverse = True)
808
        orbit = 1
809
        for planetID in obj.planets:
810
            planet = tran.db[planetID]
811
            planet.orbit = orbit
812
            orbit += 1
813
814
    sortPlanets.public = 0
815
816
    @public(AL_NONE)
817
    def rename(self, tran, obj, newName, nType):
818
        newName = newName.strip()
819
        # you have to own all planets
820
        # TODO: Throw another cmdr exc AFTER you have no planet
821
        haveOne = 0
822
        anotherComm = 0
823
        for planetID in obj.planets:
824
            planet = tran.db[planetID]
825
            if planet.owner != tran.session.cid and planet.owner != OID_NONE:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable OID_NONE does not seem to be defined.
Loading history...
826
                anotherComm = 1
827
            if planet.owner == tran.session.cid:
828
                haveOne = 1
829
        if not haveOne:
830
            raise ige.GameException('You cannot change name of this system - you have no planet in this system.')
831
        if anotherComm:
832
            raise ige.GameException('You cannot change name of this system - another commander in system.')
833
        # check validity of name
834
        if not Utils.isCorrectName(newName):
835
            raise ige.GameException('Invalid name. Only characters, digits, space, dot and dash permitted, max. length is 30 characters.')
836
        # check if there is other system with this name
837
        galaxy = tran.db[obj.compOf]
838
        for systemID in galaxy.systems:
839
            if tran.db[systemID].name == newName and systemID != obj.oid:
840
                raise ige.GameException('This name is already used.')
841
        # TODO you have to own this system longer than previous owner
842
        # one change per 1 day allowed
843
        turn = tran.db[OID_UNIVERSE].turn
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable OID_UNIVERSE does not seem to be defined.
Loading history...
844
        if obj.lastNameChng + Rules.turnsPerDay <= turn:
845
            # rename system
846
            obj.name = newName
847
            # rename planets
848
            newNames = [obj.name]
849
            for planetID in obj.planets:
850
                planet = tran.db[planetID]
851
                planet.name = Utils.getPlanetName(obj.name, nType, planet.orbit - 1)
852
                newNames.append(planet.name)
853
            obj.lastNameChng = turn
854
        else:
855
            raise ige.GameException('You cannot change name of this system - name has been changed recently (try it one day later).')
856
        return newNames
857
858
    def createPlanet(self, tran, obj):
859
        planet = self.new(T_PLANET)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable T_PLANET does not seem to be defined.
Loading history...
860
        planet.compOf = obj.oid
861
        oid = tran.db.create(planet)
862
        obj.planets.append(oid)
863
        return oid
864
865
    @public(AL_ADMIN)
866
    def deployMines(self, tran, obj, owner_id):
867
        """ Go through all mine control structures and attempt to add mines.
868
869
        """
870
        for tech, struct in self.getSystemMineLauncher(tran, obj, owner_id):
871
            if not struct[STRUCT_IDX_STATUS] & STRUCT_STATUS_ON:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable STRUCT_STATUS_ON does not seem to be defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable STRUCT_IDX_STATUS does not seem to be defined.
Loading history...
872
                # structure is offline, reset timer
873
                self.addMine(tran, obj, owner_id, tech.mineclass, 0)
874
                continue
875
            efficiency = struct[STRUCT_IDX_HP] / float(tech.maxHP)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable STRUCT_IDX_HP does not seem to be defined.
Loading history...
876
            minerate = int(tech.minerate / efficiency)
877
            minenum = int(tech.minenum * efficiency)
878
            if self.addMine(tran, obj, owner_id, tech.mineclass, minenum, minerate):
879
                log.debug('ISystem', 'Mine deployed for owner %d in system %d' % (owner_id, obj.oid))
880
881
    @public(AL_ADMIN)
882
    def addMine(self, tran, obj, owner_id, mine_tech_id, max_amount=None, mine_rate=None):
883
        """ Increment amount within particular minefield of particular player.
884
        Set current turn as a date of latest deployment.
885
886
        Returns True if mine was added.
887
888
        """
889
        current_turn = tran.db[obj.compOf].galaxyTurn
890
        if owner_id in obj.minefield:
891
            index = -1
892
            for mine_id, amount, deploy_turn in obj.minefield[owner_id]:
893
                index += 1
894
                if mine_id != mine_tech_id:
895
                    continue
896
                if max_amount is not None and amount >= max_amount:
897
                    # cannot add more, thus update deploy turn to current one
898
                    # (so replenish starts after that amount of turns if needed)
899
                    obj.minefield[owner_id][index] = (mine_id, amount, current_turn)
900
                    return False
901
                if mine_rate and (current_turn - deploy_turn) < mine_rate:
902
                    # need more time to deploy new mine
903
                    return False
904
                obj.minefield[owner_id][index] = (mine_id, amount + 1, current_turn)
905
                return True
906
            # owner has some minefield, but not this type
907
            obj.minefield[owner_id].append((mine_id, 1, current_turn))
0 ignored issues
show
introduced by
The variable mine_id does not seem to be defined in case the for loop on line 892 is not entered. Are you sure this can never be the case?
Loading history...
908
            return True
909
        else:
910
            # this will be owner's first minefield in this system
911
            obj.minefield[owner_id]= [(mine_tech_id, 1, current_turn)]
912
            return True
913
914
    @public(AL_ADMIN)
915
    def removeMine(self, obj, owner_id, mine_tech_id):
916
        """ Decrement amount within particular minefield of particular player.
917
        If amount drops to zero, remove minefield.
918
        If all minefields are removed, remove player minefield record.
919
920
        """
921
        if owner_id in obj.minefield:
922
            index = -1
923
            for mine_id, amount, deploy_turn in obj.minefield[owner_id]:
924
                index += 1
925
                if mine_id != mine_tech_id:
926
                    continue
927
                amount -= 1
928
                if amount > 0:
929
                    obj.minefield[owner_id][index] = (mine_id, amount, deploy_turn)
930
                else:
931
                    # we have depleted the minefield, remove any notion of it
932
                    del obj.minefield[owner_id][index]
933
                break
934
            if not len(obj.minefield[owner_id]):
935
                # all minefields are depleted, remove player record
936
                del obj.minefield[owner_id]
937
938
    @public(AL_ADMIN)
939
    def getMines(self, obj, owner_id):
940
        """ Return list of tuples representing each minefield.
941
942
        """
943
        if owner_id in obj.minefield:
944
            return obj.minefield[owner_id]
945
        else:
946
            return []
947
948
    def clearMines(self, obj, owner_id):
949
        """ Remove all minefields of given owner from the system.
950
951
        """
952
        if owner_id in obj.minefield:
953
            del obj.minefield[owner_id]
954
955
    clearMines.public = 0
956
957
    @public(AL_ADMIN)
958
    def fireMine(self, obj, owner_id): # shoot the mine
959
        if owner_id not in obj.minefield:
960
            return False, False, False, False
961
962
        mine_ids = []
963
        amounts = []
964
        for mine_id, amount, deploy_turn in obj.minefield[owner_id]:
965
            mine_ids.append(mine_id)
966
            amounts.append(amount)
967
        mine = Utils.weightedRandom(mine_ids, amounts) # select random mine to detonate
968
        self.removeMine(obj, owner_id, mine)
969
        tech = Rules.techs[mine]
970
        damage = random.randrange(tech.weaponDmgMin, tech.weaponDmgMax)
971
        attack = tech.weaponAtt
972
        ignore_shield = tech.weaponIgnoreShield
973
        return damage, attack, ignore_shield, mine
974
975
    def getSystemMineLauncher(self, tran, obj, playerID):
976
        launchers = []
977
        for planetID in obj.planets:
978
            planet = tran.db[planetID]
979
            if planet.owner == playerID:
980
                for struct in planet.slots:
981
                    tech = Rules.techs[struct[STRUCT_IDX_TECHID]]
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable STRUCT_IDX_TECHID does not seem to be defined.
Loading history...
982
                    if tech.mineclass:
983
                        launchtech = tech
984
                        launchers.append((launchtech, struct))
985
        return launchers
986
987
    getSystemMineLauncher.public = 0
988
989
    def getSystemMineSource(self, tran, obj, playerID):
990
        sources = []
991
        for planetID in obj.planets:
992
            planet = tran.db[planetID]
993
            if planet.owner == playerID:
994
                for struct in planet.slots:
995
                    tech = Rules.techs[struct[STRUCT_IDX_TECHID]]
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable STRUCT_IDX_TECHID does not seem to be defined.
Loading history...
996
                    if tech.mineclass:
997
                        sources.append(planetID)
998
        return sources
999
1000
    getSystemMineSource.public = 0
1001
1002
    def getSystemCombatBonuses(self, tran, obj, playerID):
1003
        systemAtt = 0;
1004
        systemDef = 0;
1005
        for planetID in obj.planets:
1006
            planet = tran.db[planetID]
1007
            if planet.owner == playerID:
1008
                for struct in planet.slots:
1009
                    tech = Rules.techs[struct[STRUCT_IDX_TECHID]]
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable STRUCT_IDX_TECHID does not seem to be defined.
Loading history...
1010
                    techEff = Utils.getTechEff(tran, struct[STRUCT_IDX_TECHID], planet.owner)
1011
                    if tech.systemAtt > 0 or tech.systemDef > 0:
1012
                        systemAtt = max(systemAtt, tech.systemAtt * techEff)
1013
                        systemDef = max(systemDef, tech.systemDef * techEff)
1014
        return (systemAtt, systemDef)
1015
1016
    getSystemCombatBonuses.public = 0
1017
1018
    def loadDOMNode(self, tran, obj, xoff, yoff, node):
1019
        obj.x = float(node.getAttribute('x')) + xoff
1020
        obj.y = float(node.getAttribute('y')) + yoff
1021
        orbit = 1
1022
        nType = Utils.getPlanetNamesType()
1023
        for elem in node.childNodes:
1024
            if elem.nodeType == Node.ELEMENT_NODE:
1025
                name = elem.tagName
1026
                if name == 'properties':
1027
                    self.loadDOMAttrs(obj, elem)
1028
                elif name == 'planet':
1029
                    # create planet
1030
                    planet = tran.db[self.createPlanet(tran, obj)]
1031
                    self.cmd(planet).loadDOMNode(tran, planet, obj.x, obj.y, orbit, elem)
1032
                    # planet.name = u'%s %s' % (obj.name, '-ABCDEFGHIJKLMNOPQRSTUVWXYZ'[orbit])
1033
                    planet.name = Utils.getPlanetName(obj.name, nType, orbit - 1)
1034
                    orbit += 1
1035
                else:
1036
                    raise ige.GameException('Unknown element %s' % name)
1037
        #~ # compute rotational constants
1038
        #~ galaxy = tran.db[obj.compOf]
1039
        #~ dx = obj.x - galaxy.x
1040
        #~ dy = obj.y - galaxy.y
1041
        #~ obj.dist = math.sqrt(dx * dx + dy * dy)
1042
        #~ if obj.dist > 0:
1043
            #~ obj.dAngle = math.sqrt(galaxy.centerWeight / obj.dist) / obj.dist
1044
        #~ else:
1045
            #~ obj.dAngle = 0.0
1046
        #~ if dx != 0:
1047
            #~ obj.sAngle = math.atan(dy / dx)
1048
            #~ if dx < 0: obj.sAngle += math.pi
1049
        #~ elif dy > 0:
1050
            #~ obj.sAngle = math.pi / 2
1051
        #~ elif dx < 0:
1052
            #~ obj.sAngle = math.pi * 3 / 2
1053
        #~ # this is a check only
1054
        #~ angle = obj.sAngle + (0 / 384.0) * obj.dAngle
1055
        #~ x = galaxy.x + obj.dist * math.cos(angle)
1056
        #~ y = galaxy.y + obj.dist * math.sin(angle)
1057
        #~ if x != obj.x or y != obj.y:
1058
            #~ log.warning(obj.name, obj.x, obj.y, dx, dy, obj.dist, obj.dAngle, obj.sAngle, x, y)
1059
        return SUCC
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable SUCC does not seem to be defined.
Loading history...
1060