Total Complexity | 373 |
Total Lines | 1361 |
Duplicated Lines | 1.18 % |
Changes | 0 |
Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like ige.ospace.IPlayer often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
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 | |||
21 | import math |
||
22 | import re |
||
23 | import time |
||
24 | |||
25 | import ige |
||
26 | import Rules |
||
27 | import Utils |
||
28 | import ShipUtils |
||
29 | |||
30 | from ige import log |
||
31 | from ige.IObject import IObject, public |
||
32 | from ige.IDataHolder import IDataHolder |
||
33 | import Const |
||
34 | |||
35 | class IPlayer(IObject): |
||
36 | |||
37 | typeID = Const.T_PLAYER |
||
38 | resignTo = Const.T_AIPLAYER |
||
39 | forums = {"INBOX": 56, "OUTBOX": 56, "EVENTS": 4} |
||
40 | |||
41 | def init(self, obj): |
||
42 | IObject.init(self, obj) |
||
43 | # |
||
44 | obj.login = u'' |
||
45 | obj.name = u'' |
||
46 | obj.fullName = u'' |
||
47 | # |
||
48 | obj.buoys = {} |
||
49 | obj.alliedBuoys = {} |
||
50 | obj.planets = [] |
||
51 | obj.fleets = [] |
||
52 | obj.techs = {} # techs and their sublevel |
||
53 | obj.obsoleteTechs = set() |
||
54 | obj.rsrchQueue = [] |
||
55 | obj.sciPoints = 0 |
||
56 | obj.effSciPoints = 0 |
||
57 | obj.techLevel = 1 |
||
58 | obj.shipDesigns = {} |
||
59 | obj.race = "H" # race Bionic, Human, Cyborg |
||
60 | # bonuses |
||
61 | obj.prodEff = 1.0 |
||
62 | obj.sciEff = 1.0 |
||
63 | # |
||
64 | obj.govPwr = 0 |
||
65 | obj.govPwrCtrlRange = 1 |
||
66 | # fleet support |
||
67 | obj.fleetUpgradePool = 0.0 |
||
68 | obj.fleetUpgradeInProgress = 0 |
||
69 | # production |
||
70 | obj.prodQueues = [[],[],[],[],[]] |
||
71 | obj.prodIncreasePool = 0.0 |
||
72 | # diplomacy |
||
73 | obj.diplomacyRels = {} |
||
74 | obj.defaultRelation = Rules.defaultRelation |
||
75 | obj.voteFor = Const.OID_NONE |
||
76 | obj.governorOf = Const.OID_NONE |
||
77 | obj.governors = [] |
||
78 | # obj.alliance = Const.OID_NONE # not utilized, but can be in DB somewhere |
||
79 | obj.imperator = 0 |
||
80 | # combat |
||
81 | # anti-small, anti-medium, anti-large, shield generator |
||
82 | obj.planetWeapons = [None, None, None, None, None] |
||
83 | # |
||
84 | obj.staticMap = {} |
||
85 | obj.dynamicMap = {} |
||
86 | obj.galaxy = None |
||
87 | obj.validSystems = [] |
||
88 | # |
||
89 | obj.stats = IDataHolder() |
||
90 | obj.stats.type = Const.T_STATS |
||
91 | obj.timeEnabled = 0 |
||
92 | obj.stratRes = {} |
||
93 | obj.lastLogin = 0.0 |
||
94 | # |
||
95 | obj.shipRedirections = {} |
||
96 | obj.buoys = {} |
||
97 | # |
||
98 | obj.clientStats = {} |
||
99 | |||
100 | def update(self, tran, obj): |
||
101 | # refresh technologies |
||
102 | self.setStartingTechnologies(obj) |
||
103 | # clean up obsoleted technologies |
||
104 | obsoleted = set(obj.techs.keys()).difference(Rules.techs.keys()) |
||
105 | for techID in obsoleted: |
||
106 | log.debug("Deleting obsoleted technology", obj.oid, techID) |
||
107 | del obj.techs[techID] |
||
108 | # update all designs |
||
109 | for designID in obj.shipDesigns: |
||
110 | old = obj.shipDesigns[designID] |
||
111 | new = ShipUtils.makeShipMinSpec(obj, old.name, old.hullID, |
||
112 | old.eqIDs, old.improvements, raiseExs = False) |
||
113 | new.built = old.built |
||
114 | if hasattr(old, "upgradeTo"): |
||
115 | new.upgradeTo = old.upgradeTo |
||
116 | obj.shipDesigns[designID] = new |
||
117 | # check all diplomacyRels |
||
118 | for partyID in obj.diplomacyRels.keys(): |
||
119 | party = tran.db.get(partyID, None) |
||
120 | if not party or party.type not in Const.PLAYER_TYPES: |
||
121 | log.debug("Deleting party", obj.oid, partyID) |
||
122 | del obj.diplomacyRels[partyID] |
||
123 | # delete obj with low scan pwr |
||
124 | # check type of the objects in the map |
||
125 | for objID in obj.staticMap.keys(): |
||
126 | obj.staticMap[objID] = min(obj.staticMap[objID], Rules.maxScanPwr) |
||
127 | if obj.staticMap[objID] < Rules.level1InfoScanPwr: |
||
128 | del obj.staticMap[objID] |
||
129 | if objID not in tran.db or tran.db[objID].type not in (Const.T_SYSTEM, Const.T_WORMHOLE): |
||
130 | log.debug("Deleting non system %d from static map of player %d" % (objID, obj.oid)) |
||
131 | del obj.staticMap[objID] |
||
132 | for objID in obj.dynamicMap.keys(): |
||
133 | if obj.dynamicMap[objID] < Rules.level1InfoScanPwr: |
||
134 | del obj.dynamicMap[objID] |
||
135 | if objID not in tran.db or tran.db[objID].type != Const.T_FLEET: |
||
136 | log.debug("Deleting obj %d from dynamic map of player %d" % (objID, objID)) |
||
137 | del obj.dynamicMap[objID] |
||
138 | # check if all planets are planets |
||
139 | for objID in obj.planets[:]: |
||
140 | try: |
||
141 | if objID not in tran.db: |
||
142 | log.debug("Planet does not exists - removing", obj.oid, objID) |
||
143 | obj.planets.remove(objID) |
||
144 | if tran.db[objID].type != Const.T_PLANET: |
||
145 | log.debug("Planet is not a planet - removing", obj.oid, objID) |
||
146 | obj.planets.remove(objID) |
||
147 | except: |
||
148 | log.warning("There is a problem when processing planet - removing", obj.oid, objID) |
||
149 | obj.planets.remove(objID) |
||
150 | # check if systems in buoys are systems |
||
151 | for objID in obj.buoys.keys(): |
||
152 | try: |
||
153 | if objID not in tran.db: |
||
154 | log.debug("System for buoy does not exists - removing", obj.oid, objID) |
||
155 | del obj.buoys[objID] |
||
156 | if tran.db[objID].type not in (Const.T_SYSTEM, Const.T_WORMHOLE): |
||
157 | log.debug("System for buoy is not a system - removing", obj.oid, objID) |
||
158 | del obj.buoys[objID] |
||
159 | except: |
||
160 | log.warning("There is a problem when processing system for buoy - removing", obj.oid, objID) |
||
161 | del obj.buoys[objID] |
||
162 | # check if fleets are fleets |
||
163 | for objID in obj.fleets[:]: |
||
164 | try: |
||
165 | if objID not in tran.db: |
||
166 | log.debug("Fleet does not exists - removing", obj.oid, objID) |
||
167 | obj.fleets.remove(objID) |
||
168 | if tran.db[objID].type != Const.T_FLEET: |
||
169 | log.debug("Fleet is not a fleet - removing", obj.oid, objID) |
||
170 | obj.fleets.remove(objID) |
||
171 | except: |
||
172 | log.warning("There is a problem when processing planet - removing", obj.oid, objID) |
||
173 | # check accessible technologies |
||
174 | wip = 1 |
||
175 | while wip: |
||
176 | wip = 0 |
||
177 | for techID in obj.techs.keys(): |
||
178 | if techID not in Rules.techs: |
||
179 | wip = 1 |
||
180 | log.debug("Deleting nonexistent tech", techID, "player", obj.oid) |
||
181 | del obj.techs[techID] |
||
182 | continue |
||
183 | tech = Rules.techs[techID] |
||
184 | # check tech level |
||
185 | if tech.level > obj.techLevel: |
||
186 | wip = 1 |
||
187 | log.debug("Deleting tech", techID, "player", obj.oid) |
||
188 | if techID in obj.techs: del obj.techs[techID] |
||
189 | for rTask in obj.rsrchQueue[:]: |
||
190 | if rTask.techID not in Rules.techs: |
||
191 | log.debug("Deleting res task for nonexistent tech", rTask.techID, "player", obj.oid) |
||
192 | obj.rsrchQueue.remove(rTask) |
||
193 | continue |
||
194 | tech = Rules.techs[rTask.techID] |
||
195 | if tech.level == 99: |
||
196 | log.debug("Deleting res task", rTask.techID, "player", obj.oid) |
||
197 | obj.rsrchQueue.remove(rTask) |
||
198 | # check if player is in the universe |
||
199 | universe = tran.db[Const.OID_UNIVERSE] |
||
200 | if obj.oid not in universe.players and obj.oid not in (Const.OID_NATURE, Const.OID_ADMIN): |
||
201 | log.debug(obj.oid, "Adding player to the universe") |
||
202 | universe.players.append(obj.oid) |
||
203 | # check if player is a leader |
||
204 | if not obj.galaxy: |
||
205 | log.debug(obj.oid, obj.name, "IS NOT IN ANY GALAXY") |
||
206 | else: |
||
207 | galaxy = tran.db[obj.galaxy] |
||
208 | if galaxy.imperator != obj.oid and obj.imperator > 0: |
||
209 | log.debug(obj.oid, "Removing imperator/leader bonus") |
||
210 | obj.imperator = 0 |
||
211 | ## NON VALIDATING CODE (DERIVED ATTRS AND SO ON) |
||
212 | # get best technologies for planet weapons |
||
213 | bestScores = [0, 0, 0, 0] |
||
214 | obj.planetWeapons = [None, None, None, None, None] |
||
215 | for techID in obj.techs: |
||
216 | tech = Rules.techs[techID] |
||
217 | if tech.isShipEquip and tech.weaponDmgMin > 0 and not tech.buildSRes\ |
||
218 | and tech.weaponGoodForFlak: |
||
219 | # compute score |
||
220 | weaponEff = Rules.techImprEff[obj.techs.get(techID, Rules.techBaseImprovement)] |
||
221 | score = (tech.weaponDmgMin + tech.weaponDmgMax) / 2.0 * \ |
||
222 | tech.weaponROF * (tech.weaponAtt + 10.0)/10 * weaponEff |
||
223 | if score > bestScores[tech.weaponClass]: |
||
224 | obj.planetWeapons[tech.weaponClass] = techID |
||
225 | bestScores[tech.weaponClass] = score |
||
226 | #@log.debug(obj.oid, "Planet weapons", obj.planetWeapons) |
||
227 | # update all ship designs |
||
228 | for designID in obj.shipDesigns: |
||
229 | old = obj.shipDesigns[designID] |
||
230 | new = ShipUtils.makeShipMinSpec(obj, old.name, old.hullID, |
||
231 | old.eqIDs, old.improvements, raiseExs = False) |
||
232 | new.built = old.built |
||
233 | new.upgradeTo = old.upgradeTo |
||
234 | obj.shipDesigns[designID] = new |
||
235 | |||
236 | @staticmethod |
||
237 | def setStartingPlanet(tran, playerID, planet): |
||
238 | planet.plSlots = max(planet.plSlots, 9) |
||
239 | planet.plMaxSlots = max(planet.plMaxSlots, 9) |
||
240 | planet.plDiameter = max(planet.plDiameter, 9000) |
||
241 | planet.slots = [ |
||
242 | Utils.newStructure(tran, Rules.Tech.PWRPLANTNUK1, playerID, Const.STRUCT_STATUS_ON, Rules.structNewPlayerHpRatio), |
||
243 | Utils.newStructure(tran, Rules.Tech.FARM1, playerID, Const.STRUCT_STATUS_ON, Rules.structNewPlayerHpRatio), |
||
244 | Utils.newStructure(tran, Rules.Tech.FARM1, playerID, Const.STRUCT_STATUS_ON, Rules.structNewPlayerHpRatio), |
||
245 | Utils.newStructure(tran, Rules.Tech.ANCFACTORY, playerID, Const.STRUCT_STATUS_ON, Rules.structNewPlayerHpRatio), |
||
246 | Utils.newStructure(tran, Rules.Tech.ANCFACTORY, playerID, Const.STRUCT_STATUS_ON, Rules.structNewPlayerHpRatio), |
||
247 | Utils.newStructure(tran, Rules.Tech.ANCRESLAB, playerID, Const.STRUCT_STATUS_ON, Rules.structNewPlayerHpRatio), |
||
248 | Utils.newStructure(tran, Rules.Tech.REPAIR1, playerID, Const.STRUCT_STATUS_ON, Rules.structNewPlayerHpRatio), |
||
249 | ] |
||
250 | planet.storPop = Rules.startingPopulation |
||
251 | planet.storBio = Rules.startingBio |
||
252 | planet.storEn = Rules.startingEn |
||
253 | planet.scannerPwr = Rules.startingScannerPwr |
||
254 | planet.morale = Rules.maxMorale |
||
255 | |||
256 | @staticmethod |
||
257 | def setStartingTechnologies(obj): |
||
258 | for techID, tech in Rules.techs.iteritems(): |
||
259 | if tech.isStarting and techID not in obj.techs: |
||
260 | obj.techs[techID] = (Rules.techBaseImprovement + tech.maxImprovement) / 2 |
||
261 | |||
262 | @staticmethod |
||
263 | def setStartingShipDesigns(obj): |
||
264 | obj.shipDesigns[1] = ShipUtils.makeShipMinSpec(obj, 'Scout', Rules.Tech.SMALLHULL0, |
||
265 | {Rules.Tech.SCOCKPIT0:1, Rules.Tech.SCANNERMOD0:1, Rules.Tech.FTLENG0:3}, []) |
||
266 | obj.shipDesigns[2] = ShipUtils.makeShipMinSpec(obj, 'Fighter', Rules.Tech.SMALLHULL0, |
||
267 | {Rules.Tech.SCOCKPIT0:1, Rules.Tech.CANNON0:2, Rules.Tech.FTLENG0:3}, []) |
||
268 | obj.shipDesigns[3] = ShipUtils.makeShipMinSpec(obj, 'Bomber', Rules.Tech.SMALLHULL0, |
||
269 | {Rules.Tech.SCOCKPIT0:1, Rules.Tech.CONBOMB0:1, Rules.Tech.FTLENG0:3}, []) |
||
270 | obj.shipDesigns[4] = ShipUtils.makeShipMinSpec(obj, 'Patrol Corvette', Rules.Tech.SMALLHULL0, |
||
271 | {Rules.Tech.SCOCKPIT0:1, Rules.Tech.CANNON0:3, Rules.Tech.FTLENG0:1, Rules.Tech.STLENG1:2}, []) |
||
272 | obj.shipDesigns[5] = ShipUtils.makeShipMinSpec(obj, 'Colony Ship', Rules.Tech.MEDIUMHULL0, |
||
273 | {Rules.Tech.SCOCKPIT0:1, Rules.Tech.COLONYMOD0:1, Rules.Tech.FTLENG0:5}, []) |
||
274 | |||
275 | @staticmethod |
||
276 | def setStartingFleet(tran, playerID, system): |
||
277 | # add small fleet |
||
278 | log.debug('Creating fleet') |
||
279 | fleet = tran.gameMngr.cmdPool[Const.T_FLEET].new(Const.T_FLEET) |
||
280 | tran.db.create(fleet) |
||
281 | log.debug('Creating fleet - created', fleet.oid) |
||
282 | tran.gameMngr.cmdPool[Const.T_FLEET].create(tran, fleet, system, playerID) |
||
283 | log.debug('Creating fleet - addShips') |
||
284 | # for IDs, see setStartingShipDesigns |
||
285 | tran.gameMngr.cmdPool[Const.T_FLEET].addNewShip(tran, fleet, 1) |
||
286 | tran.gameMngr.cmdPool[Const.T_FLEET].addNewShip(tran, fleet, 1) |
||
287 | tran.gameMngr.cmdPool[Const.T_FLEET].addNewShip(tran, fleet, 2) |
||
288 | tran.gameMngr.cmdPool[Const.T_FLEET].addNewShip(tran, fleet, 2) |
||
289 | tran.gameMngr.cmdPool[Const.T_FLEET].addNewShip(tran, fleet, 5) |
||
290 | |||
291 | @public(Const.AL_FULL) |
||
292 | def startGlobalConstruction(self, tran, player, techID, quantity, isShip, reportFinished, queue): |
||
293 | if len(player.prodQueues) <= queue: |
||
294 | raise ige.GameException('Invalid queue.') |
||
295 | if len(player.prodQueues[queue]) > Rules.maxProdQueueLen: |
||
296 | raise ige.GameException('Queue is full.') |
||
297 | if quantity < 1: |
||
298 | raise ige.GameException("Quantity must be greater than 0") |
||
299 | if techID not in player.techs and isShip == 0: |
||
300 | raise ige.GameException('You do not own this kind of technology.') |
||
301 | if techID not in player.shipDesigns and isShip == 1: |
||
302 | raise ige.GameException('You do not own this ship design.') |
||
303 | if isShip: |
||
304 | tech = player.shipDesigns[techID] |
||
305 | if tech.upgradeTo: |
||
306 | raise ige.GameException("You cannot build obsolete ship design.") |
||
307 | else: |
||
308 | tech = Rules.techs[techID] |
||
309 | if tech.isStructure or not tech.isProject: |
||
310 | raise ige.GameException('You cannot construct this technology.') |
||
311 | elif tech.globalDisabled: |
||
312 | raise ige.GameException('You cannot construct targeted project.') |
||
313 | neededSR = {} |
||
314 | for sr in tech.buildSRes: |
||
315 | nSR = neededSR.get(sr, 0) + tech.buildSRes[sr] * quantity |
||
316 | if player.stratRes.get(sr, 0) < nSR: |
||
317 | raise ige.GameException("You do not own required strategic resource(s)") |
||
318 | neededSR[sr] = nSR |
||
319 | # consume strategic resources |
||
320 | for sr in neededSR: |
||
321 | player.stratRes[sr] -= neededSR[sr] |
||
322 | # start construction |
||
323 | item = IDataHolder() |
||
324 | item.techID = techID |
||
325 | item.quantity = int(quantity) |
||
326 | item.changePerc = 0 |
||
327 | item.isShip = bool(isShip) |
||
328 | item.reportFin = bool(reportFinished) |
||
329 | item.type = Const.T_TASK |
||
330 | player.prodQueues[queue].append(item) |
||
331 | return player.prodQueues[queue], player.stratRes |
||
332 | |||
333 | @public(Const.AL_FULL) |
||
334 | def changeGlobalConstruction(self, tran, player, queue, index, quantity): |
||
335 | if index < 0 or index >= len(player.prodQueues[queue]): |
||
336 | raise ige.GameException("No such item in the construction queue.") |
||
337 | |||
338 | if quantity < 1: |
||
339 | raise ige.GameException("Quantity must be greater than 0") |
||
340 | |||
341 | item = player.prodQueues[queue][index] |
||
342 | if item.isShip: |
||
343 | tech = player.shipDesigns[item.techID] |
||
344 | else: |
||
345 | tech = Rules.techs[item.techID] |
||
346 | |||
347 | quantityChange = quantity - player.prodQueues[queue][index].quantity |
||
348 | |||
349 | neededSR = {} |
||
350 | for sr in tech.buildSRes: |
||
351 | nSR = neededSR.get(sr, 0) + tech.buildSRes[sr] * quantityChange |
||
352 | if player.stratRes.get(sr, 0) < nSR: |
||
353 | raise ige.GameException("You do not own required strategic resource(s)") |
||
354 | neededSR[sr] = nSR |
||
355 | # consume strategic resources |
||
356 | for sr in neededSR: |
||
357 | player.stratRes[sr] += (-1 * neededSR[sr]) |
||
358 | |||
359 | player.prodQueues[queue][index].quantity = quantity |
||
360 | player.prodQueues[queue][index].const = tech.buildProd * quantity |
||
361 | return player.prodQueues[queue], player.stratRes |
||
362 | |||
363 | @public(Const.AL_FULL) |
||
364 | def abortGlobalConstruction(self, tran, player, queue, index): |
||
365 | if len(player.prodQueues) <= queue or queue < 0: |
||
366 | raise ige.GameException('Invalid queue.') |
||
367 | if len(player.prodQueues[queue]) <= index or index < 0: |
||
368 | raise ige.GameException('Invalid task.') |
||
369 | item = player.prodQueues[queue][index] |
||
370 | # return strategic resources |
||
371 | #is ship |
||
372 | if item.techID < 1000: |
||
373 | tech = player.shipDesigns[item.techID] |
||
374 | else: |
||
375 | tech = Rules.techs[item.techID] |
||
376 | for sr in tech.buildSRes: |
||
377 | player.stratRes[sr] += item.quantity * tech.buildSRes[sr] |
||
378 | player.prodQueues[queue].pop(index) |
||
379 | return player.prodQueues[queue], player.stratRes |
||
380 | |||
381 | @public(Const.AL_FULL) |
||
382 | def moveGlobalConstrItem(self, tran, player, queue, index, rel): |
||
383 | if index >= len(player.prodQueues[queue]): |
||
384 | raise ige.GameException('No such item in the construction queue.') |
||
385 | if index + rel < 0 or index + rel >= len(player.prodQueues[queue]): |
||
386 | raise ige.GameException('Cannot move.') |
||
387 | item = player.prodQueues[queue][index] |
||
388 | del player.prodQueues[queue][index] |
||
389 | player.prodQueues[queue].insert(index + rel, item) |
||
390 | return player.prodQueues[queue] |
||
391 | |||
392 | def getReferences(self, tran, obj): |
||
393 | return obj.fleets |
||
394 | |||
395 | def loggedIn(self, tran, obj): |
||
396 | obj.lastLogin = time.time() |
||
397 | |||
398 | @public(Const.AL_OWNER) |
||
399 | def resign(self, tran, obj): |
||
400 | """Remove player from the game. Give remaining planets, ... to the REBELS""" |
||
401 | # cannot resign when time is stopped |
||
402 | # TODO smarted conditions (like cannot resign twice a week or so) |
||
403 | galaxy = tran.db[obj.galaxy] |
||
404 | if galaxy.scenario == Const.SCENARIO_SINGLE: |
||
405 | raise ige.GameException('You cannot resign current game - it is single player game.') |
||
406 | if not obj.timeEnabled: |
||
407 | raise ige.GameException('You cannot resign current game - time is stopped.') |
||
408 | log.debug("Resigning player", obj.oid) |
||
409 | # morph player to AI |
||
410 | obj.type = self.resignTo |
||
411 | self.cmd(obj).upgrade(tran, obj) |
||
412 | self.cmd(obj).update(tran, obj) |
||
413 | # reregister |
||
414 | tran.gameMngr.removePlayer(obj.oid) |
||
415 | self.cmd(obj).register(tran, obj, obj.galaxy) |
||
416 | |||
417 | @public(Const.AL_ADMIN) |
||
418 | def delete(self, tran, obj): |
||
419 | # check whether it is AI or normal player |
||
420 | log.debug("Deleting player", obj.oid) |
||
421 | # delete relations |
||
422 | for playerID in tran.db[Const.OID_UNIVERSE].players: |
||
423 | player = tran.db[playerID] |
||
424 | self.cmd(player).deleteDiplomacyWith(tran, player, obj.oid) |
||
425 | # delete fleets |
||
426 | for fleetID in obj.fleets: |
||
427 | fleet = tran.db[fleetID] |
||
428 | self.cmd(fleet).disbandFleet(tran, fleet) |
||
429 | try: |
||
430 | tran.gameMngr.removePlayer(obj.oid) |
||
431 | except Exception: |
||
432 | log.warning("Cannot remove player") |
||
433 | |||
434 | @public(Const.AL_ADMIN) |
||
435 | def giveUp(self, tran, obj, playerID): |
||
436 | """Remove player from the game. Give remaining planets, ... to the specified player""" |
||
437 | # cannot resign when time is stopped |
||
438 | # TODO smarted conditions (like cannot resign twice a week or so) |
||
439 | if not obj.timeEnabled: |
||
440 | raise ige.GameException('You cannot resign current game - time is stopped.') |
||
441 | player = tran.db[playerID] |
||
442 | # give planets |
||
443 | for planetID in obj.planets[:]: # needs a copy - changeOwner modifies this |
||
444 | planet = tran.db[planetID] |
||
445 | self.cmd(planet).changeOwner(tran, planet, playerID, force = 1) |
||
446 | # give fleets |
||
447 | for fleetID in obj.fleets[:]: |
||
448 | fleet = tran.db[fleetID] |
||
449 | fleet.owner = playerID |
||
450 | player.fleets.append(fleetID) |
||
451 | # remove player |
||
452 | tran.gameMngr.removePlayer(obj.oid) |
||
453 | try: |
||
454 | tran.db[Const.OID_UNIVERSE].players.remove(obj.oid) |
||
455 | except ValueError: |
||
456 | pass |
||
457 | |||
458 | @public(Const.AL_OWNER) |
||
459 | def addShipDesign(self, tran, obj, name, hullID, eqIDs): |
||
460 | """Add ship design to the database of designs.""" |
||
461 | # normalize design |
||
462 | name = name.strip() |
||
463 | # check technologies |
||
464 | if hullID not in obj.techs: |
||
465 | raise ige.GameException("You do not posses this hull type.") |
||
466 | for techID in eqIDs: |
||
467 | if techID not in obj.techs: |
||
468 | raise ige.GameException("You do not posses technology(ies) to construct this ship.") |
||
469 | # create spec (throws exception for invad ones) |
||
470 | spec = ShipUtils.makeShipMinSpec(obj, name, hullID, eqIDs, []) |
||
471 | # check number of designs |
||
472 | if len(obj.shipDesigns) > Rules.shipMaxDesigns: |
||
473 | raise ige.GameException("No space to store design.") |
||
474 | # check name of designs |
||
475 | for designID in obj.shipDesigns: |
||
476 | if obj.shipDesigns[designID].name == name: |
||
477 | raise ige.GameException("Design name is already used.") |
||
478 | if re.match("^\s*$",name): |
||
479 | raise ige.GameException("Design name must not be entirely whitespace.") |
||
480 | # find free design id |
||
481 | index = 1 |
||
482 | ids = obj.shipDesigns.keys() |
||
483 | while 1: |
||
484 | if index not in ids: |
||
485 | break |
||
486 | index += 1 |
||
487 | # add design |
||
488 | obj.shipDesigns[index] = spec |
||
489 | return obj.shipDesigns, index |
||
490 | |||
491 | @public(Const.AL_OWNER) |
||
492 | def addBuoy(self, tran, obj, systemID, text, type): |
||
493 | """Add new buoy to player buoys.""" |
||
494 | # delete buoy |
||
495 | if not text: |
||
496 | if systemID in obj.buoys: |
||
497 | del obj.buoys[systemID] |
||
498 | return obj.buoys |
||
499 | else: |
||
500 | raise ige.GameException("Buoy at specified system does not exist.") |
||
501 | |||
502 | if type not in (Const.BUOY_PRIVATE, Const.BUOY_TO_ALLY, Const.BUOY_TO_SCANNERSHARE): |
||
503 | raise ige.GameException("Wrong bouy type.") |
||
504 | |||
505 | # edit buoy |
||
506 | if systemID in obj.buoys: |
||
507 | obj.buoys[systemID] = (text, type) |
||
508 | return obj.buoys |
||
509 | |||
510 | if len(obj.buoys) >= 30: |
||
511 | raise ige.GameException("You cannot add more than 30 buoys.") |
||
512 | |||
513 | if tran.db[systemID].type not in (Const.T_SYSTEM, Const.T_WORMHOLE): |
||
514 | raise ige.GameException("You can add buoy only to system.") |
||
515 | |||
516 | # new buoy |
||
517 | if len(text) > 0: |
||
518 | obj.buoys[systemID] = (text, type) |
||
519 | |||
520 | return obj.buoys |
||
521 | |||
522 | @public(Const.AL_OWNER) |
||
523 | def scrapShipDesign(self, tran, obj, designID): |
||
524 | """Remove ship design from the database of designs and remove all |
||
525 | active ships using this design.""" |
||
526 | # check design ID |
||
527 | if designID not in obj.shipDesigns: |
||
528 | raise ige.GameException("No such design.") |
||
529 | # delete ships |
||
530 | for fleetID in obj.fleets[:]: # make copy, fleet can be deleted |
||
531 | fleet = tran.db[fleetID] |
||
532 | self.cmd(fleet).deleteDesign(tran, fleet, designID) |
||
533 | # delete tasks |
||
534 | for planetID in obj.planets: |
||
535 | planet = tran.db[planetID] |
||
536 | self.cmd(planet).deleteDesign(tran, planet, designID) |
||
537 | # delete from global queues |
||
538 | for queueID in xrange(len(obj.prodQueues)): |
||
|
|||
539 | queue = obj.prodQueues[queueID][:] |
||
540 | for taskID in xrange(len(queue)): |
||
541 | if obj.prodQueues[queueID][taskID].techID == designID: |
||
542 | self.cmd(obj).abortGlobalConstruction(tran, obj, queueID, taskID) |
||
543 | # clear upgradeTo |
||
544 | for tmpDesignID in obj.shipDesigns: |
||
545 | spec = obj.shipDesigns[tmpDesignID] |
||
546 | if spec.upgradeTo == designID: |
||
547 | spec.upgradeTo = 0 |
||
548 | # delete design |
||
549 | del obj.shipDesigns[designID] |
||
550 | return obj.shipDesigns, obj.fleets, obj.stratRes, obj.prodQueues |
||
551 | |||
552 | def getShipDesign(self,tran,obj,designID): |
||
553 | if designID not in obj.shipDesigns: |
||
554 | raise ige.GameException("No such design.") |
||
555 | return obj.shipDesigns[designID] |
||
556 | |||
557 | @public(Const.AL_OWNER) |
||
558 | def upgradeShipDesign(self, tran, obj, oldDesignID, newDesignID): |
||
559 | # check designs ID |
||
560 | if oldDesignID not in obj.shipDesigns: |
||
561 | raise ige.GameException("No such design.") |
||
562 | if newDesignID not in obj.shipDesigns: |
||
563 | raise ige.GameException("No such design.") |
||
564 | if oldDesignID == newDesignID: |
||
565 | raise ige.GameException("Designs are the same.") |
||
566 | oldSpec = obj.shipDesigns[oldDesignID] |
||
567 | newSpec = obj.shipDesigns[newDesignID] |
||
568 | if oldSpec.upgradeTo: |
||
569 | raise ige.GameException("Old design has already been made obsolete.") |
||
570 | if newSpec.upgradeTo: |
||
571 | raise ige.GameException("New design has already been made obsolete.") |
||
572 | if oldSpec.combatClass != newSpec.combatClass: |
||
573 | raise ige.GameException("Designs must be of the same combat class.") |
||
574 | # set old design as upgradable |
||
575 | oldSpec.upgradeTo = newDesignID |
||
576 | # if something is upgraded to oldDesign change it to new design |
||
577 | for desID in obj.shipDesigns: |
||
578 | if obj.shipDesigns[desID].upgradeTo == oldDesignID: |
||
579 | obj.shipDesigns[desID].upgradeTo = newDesignID |
||
580 | # compute strat res difference |
||
581 | stratRes = {} |
||
582 | for sr in oldSpec.buildSRes: |
||
583 | stratRes[sr] = stratRes.get(sr, 0) - oldSpec.buildSRes[sr] |
||
584 | for sr in newSpec.buildSRes: |
||
585 | stratRes[sr] = stratRes.get(sr, 0) + newSpec.buildSRes[sr] |
||
586 | if stratRes[sr] == 0: |
||
587 | del stratRes[sr] |
||
588 | log.debug("upgradeShipDesign", obj.oid, stratRes) |
||
589 | # modify tasks |
||
590 | tasksUpgraded = False |
||
591 | if not stratRes: |
||
592 | log.debug("upgradeShipDesign - upgrading tasks") |
||
593 | for planetID in obj.planets: |
||
594 | planet = tran.db[planetID] |
||
595 | self.cmd(planet).changeShipDesign(tran, planet, oldDesignID, newDesignID) |
||
596 | # upgrade global queue as well |
||
597 | for queue in obj.prodQueues: |
||
598 | for task in queue: |
||
599 | if task.techID == oldDesignID: |
||
600 | task.techID = newDesignID |
||
601 | tasksUpgraded = True |
||
602 | else: |
||
603 | log.debug("upgradeShipDesing - NOT upgrading tasks") |
||
604 | return obj.shipDesigns, obj.stratRes, tasksUpgraded, obj.prodQueues |
||
605 | |||
606 | @public(Const.AL_OWNER) |
||
607 | def cancelUpgradeShipDesign(self, tran, obj, designID): |
||
608 | # check designs ID |
||
609 | if designID not in obj.shipDesigns: |
||
610 | raise ige.GameException("No such design.") |
||
611 | obj.shipDesigns[designID].upgradeTo = Const.OID_NONE |
||
612 | return obj.shipDesigns |
||
613 | |||
614 | @public(Const.AL_FULL) |
||
615 | def startResearch(self, tran, obj, techID, improveToMax = 0): |
||
616 | if len(obj.rsrchQueue) > Rules.maxRsrchQueueLen: |
||
617 | ige.GameException('Queue is full.') |
||
618 | tech = Rules.techs[techID] |
||
619 | # player has to be a right race |
||
620 | if obj.race not in tech.researchRaces: |
||
621 | raise ige.GameException("Your race cannot research this technology.") |
||
622 | # item cannot be researched twice |
||
623 | for tmpTech in obj.rsrchQueue: |
||
624 | if tmpTech.techID == techID: |
||
625 | raise ige.GameException('Technology is already sheduled for research.') |
||
626 | # disabled? |
||
627 | for tmpTechID in obj.techs: |
||
628 | if techID in Rules.techs[tmpTechID].researchDisables: |
||
629 | raise ige.GameException("Previous research has disabled this technology.") |
||
630 | # check requirements |
||
631 | for tmpTechID, improvement in tech.researchRequires: |
||
632 | if tmpTechID not in obj.techs or obj.techs[tmpTechID] < improvement: |
||
633 | raise ige.GameException('You cannot research this technology yet.') |
||
634 | improvement = obj.techs.get(techID, Rules.techBaseImprovement - 1) + 1 |
||
635 | if improvement > Rules.techMaxImprovement or improvement > tech.maxImprovement: |
||
636 | raise ige.GameException('You cannot improve this technology further.') |
||
637 | if tech.level > obj.techLevel: |
||
638 | raise ige.GameException("Your technological level is insufficient.") |
||
639 | # check strategic resources |
||
640 | if improvement == 1: |
||
641 | for stratRes in tech.researchReqSRes: |
||
642 | if obj.stratRes.get(stratRes, 0) < 1: |
||
643 | raise ige.GameException("Required strategy resource missing.") |
||
644 | item = IDataHolder() |
||
645 | item.techID = techID |
||
646 | item.improvement = improvement |
||
647 | item.currSci = 0 |
||
648 | item.changeSci = 0 |
||
649 | item.improveToMax = improveToMax |
||
650 | item.type = Const.T_RESTASK |
||
651 | obj.rsrchQueue.append(item) |
||
652 | return obj.rsrchQueue |
||
653 | |||
654 | @public(Const.AL_FULL) |
||
655 | def abortResearch(self, tran, obj, index): |
||
656 | if index >= len(obj.rsrchQueue) or index < 0: |
||
657 | ige.GameException('No such item in queue.') |
||
658 | del obj.rsrchQueue[index] |
||
659 | return obj.rsrchQueue |
||
660 | |||
661 | @public(Const.AL_FULL) |
||
662 | def editResearch(self, tran, obj, index, improveToMax = 0): |
||
663 | if index >= len(obj.rsrchQueue) or index < 0: |
||
664 | ige.GameException('No such item in queue.') |
||
665 | obj.rsrchQueue[index].improveToMax = improveToMax |
||
666 | return obj.rsrchQueue |
||
667 | |||
668 | @public(Const.AL_FULL) |
||
669 | def moveResearch(self, tran, obj, index, rel): |
||
670 | if index >= len(obj.rsrchQueue): |
||
671 | raise ige.GameException('No such item in the researcg queue.') |
||
672 | if index + rel < 0 or index + rel >= len(obj.rsrchQueue): |
||
673 | raise ige.GameException('Cannot move.') |
||
674 | item = obj.rsrchQueue[index] |
||
675 | del obj.rsrchQueue[index] |
||
676 | obj.rsrchQueue.insert(index + rel, item) |
||
677 | return obj.rsrchQueue |
||
678 | |||
679 | @public(Const.AL_FULL) |
||
680 | def redirectShips(self, tran, obj, sourceSystemID, targetSystemID): |
||
681 | # check sourceSystemID |
||
682 | ok = 0 |
||
683 | if sourceSystemID == targetSystemID: |
||
684 | targetSystemID = Const.OID_NONE |
||
685 | for planetID in tran.db[sourceSystemID].planets: |
||
686 | if tran.db[planetID].owner == obj.oid: |
||
687 | ok = 1 |
||
688 | if not ok: |
||
689 | raise ige.GameException("You must own planet in the source system") |
||
690 | # check targetSystemID |
||
691 | if targetSystemID != Const.OID_NONE and 0: # TODO: switch on |
||
692 | ok = 0 |
||
693 | for planetID in tran.db[targetSystemID].planets: |
||
694 | if tran.db[planetID].owner == obj.oid: |
||
695 | ok = 1 |
||
696 | if not ok: |
||
697 | raise ige.GameException("You must own planet in the target system") |
||
698 | # fine - record it |
||
699 | log.debug(obj.oid, "Adding redirection", sourceSystemID, targetSystemID) |
||
700 | if targetSystemID: |
||
701 | obj.shipRedirections[sourceSystemID] = targetSystemID |
||
702 | else: |
||
703 | try: |
||
704 | del obj.shipRedirections[sourceSystemID] |
||
705 | except KeyError: |
||
706 | pass |
||
707 | return obj.shipRedirections |
||
708 | |||
709 | @public(Const.AL_NONE) |
||
710 | def getPublicInfo(self, tran, obj): |
||
711 | result = IObject.getPublicInfo(self, tran, obj) |
||
712 | result.type = obj.type |
||
713 | result.name = obj.name |
||
714 | return result |
||
715 | |||
716 | @public(Const.AL_OWNER) |
||
717 | def changePactCond(self, tran, obj, playerID, pactID, state, conditions): |
||
718 | log.debug("changePactCond", obj.oid, playerID, pactID) |
||
719 | # must have a contact |
||
720 | if playerID not in obj.diplomacyRels: |
||
721 | raise ige.GameException('No contact with this player.') |
||
722 | player = tran.db[playerID] |
||
723 | # must be a player |
||
724 | if player.type not in Const.PLAYER_TYPES: |
||
725 | raise ige.GameException('Pacts can be offered to players only.') |
||
726 | # check pactID |
||
727 | pact = Rules.pactDescrs.get(pactID, None) |
||
728 | if not pact: |
||
729 | raise ige.GameException('No such pact type.') |
||
730 | # check state |
||
731 | if state not in (Const.PACT_OFF, Const.PACT_INACTIVE, Const.PACT_ACTIVE): |
||
732 | raise ige.GameException("Wrong pact state") |
||
733 | # check conditions |
||
734 | for tmpPactID in conditions: |
||
735 | pact = Rules.pactDescrs.get(tmpPactID, None) |
||
736 | if not pact: |
||
737 | raise ige.GameException('No such pact type.') |
||
738 | # record pact |
||
739 | dipl = self.cmd(obj).getDiplomacyWith(tran, obj, playerID) |
||
740 | dipl.pacts[pactID] = [state] |
||
741 | dipl.pacts[pactID].extend(conditions) |
||
742 | # if state if Const.PACT_OFF, disable state on partner's side |
||
743 | if state == Const.PACT_OFF: |
||
744 | partner = tran.db[playerID] |
||
745 | dipl = self.cmd(partner).getDiplomacyWith(tran, partner, obj.oid) |
||
746 | if pactID in dipl.pacts: |
||
747 | dipl.pacts[pactID][0] = Const.PACT_OFF |
||
748 | else: |
||
749 | dipl.pacts[pactID] = [Const.PACT_OFF] |
||
750 | return obj.diplomacyRels |
||
751 | |||
752 | def getDiplomacyWith(self, tran, obj, playerID): |
||
753 | if obj.governorOf: |
||
754 | # player is a governor |
||
755 | leader = tran.db[obj.governorOf] |
||
756 | return self.cmd(leader).getDiplomacyWith(tran, leader, objID) |
||
757 | # player is independent |
||
758 | dipl = obj.diplomacyRels.get(playerID, None) |
||
759 | View Code Duplication | if not dipl: |
|
760 | # make default |
||
761 | dipl = IDataHolder() |
||
762 | dipl.type = Const.T_DIPLREL |
||
763 | dipl.pacts = { |
||
764 | Const.PACT_ALLOW_CIVILIAN_SHIPS: [Const.PACT_ACTIVE, Const.PACT_ALLOW_CIVILIAN_SHIPS] |
||
765 | } |
||
766 | dipl.relation = obj.defaultRelation |
||
767 | dipl.relChng = 0 |
||
768 | dipl.lastContact = tran.db[Const.OID_UNIVERSE].turn |
||
769 | dipl.contactType = Const.CONTACT_NONE |
||
770 | dipl.stats = None |
||
771 | if playerID != obj.oid: |
||
772 | obj.diplomacyRels[playerID] = dipl |
||
773 | else: |
||
774 | log.debug("getDiplomacyWith myself", obj.oid) |
||
775 | return dipl |
||
776 | |||
777 | @public(Const.AL_OWNER) |
||
778 | def getPartyDiplomacyRels(self, tran, obj, partyID): |
||
779 | if partyID not in obj.diplomacyRels: |
||
780 | return None, None |
||
781 | if obj.diplomacyRels[partyID].contactType == Const.CONTACT_NONE: |
||
782 | return obj.diplomacyRels[partyID], None |
||
783 | party = tran.db[partyID] |
||
784 | return obj.diplomacyRels[partyID], party.diplomacyRels.get(obj.oid, None) |
||
785 | |||
786 | def isPactActive(self, tran, obj, partnerID, pactID): |
||
787 | #@log.debug("isPactActive", obj.oid, partnerID, pactID) |
||
788 | if partnerID not in obj.diplomacyRels: |
||
789 | return 0 |
||
790 | partner = tran.db[partnerID] |
||
791 | partnerDipl = partner.diplomacyRels.get(obj.oid, None) |
||
792 | if not partnerDipl: |
||
793 | return 0 |
||
794 | return partnerDipl.pacts.get(pactID, [Const.PACT_OFF])[0] == Const.PACT_ACTIVE |
||
795 | |||
796 | def deleteDiplomacyWith(self, tran, obj, playerID): |
||
797 | if playerID in obj.diplomacyRels: |
||
798 | del obj.diplomacyRels[playerID] |
||
799 | |||
800 | @public(Const.AL_FULL) |
||
801 | def getRelationTo(self, tran, obj, objID): |
||
802 | if objID == Const.OID_NONE: |
||
803 | return Const.REL_UNDEF |
||
804 | if obj.oid == objID: |
||
805 | return Const.REL_UNITY |
||
806 | if obj.governorOf: |
||
807 | leader = tran.db[obj.governorOf] |
||
808 | return self.cmd(leader).getRelationTo(tran, leader, objID) |
||
809 | dipl = obj.diplomacyRels.get(objID, None) |
||
810 | if dipl: |
||
811 | return dipl.relation |
||
812 | else: |
||
813 | return obj.defaultRelation |
||
814 | |||
815 | @public(Const.AL_OWNER) |
||
816 | def setVoteFor(self, tran, obj, playerID): |
||
817 | if playerID not in obj.diplomacyRels and playerID != obj.oid and playerID != Const.OID_NONE: |
||
818 | raise ige.GameException("No contact with this commander.") |
||
819 | # check type |
||
820 | if playerID != Const.OID_NONE: |
||
821 | player = tran.db[playerID] |
||
822 | if player.type != Const.T_PLAYER: |
||
823 | raise ige.GameException("You cannot vote for this player.") |
||
824 | # set |
||
825 | obj.voteFor = playerID |
||
826 | return obj.voteFor |
||
827 | |||
828 | @public(Const.AL_ADMIN) |
||
829 | def processDIPLPhase(self, tran, obj, data): |
||
830 | if not obj.timeEnabled: |
||
831 | return |
||
832 | turn = tran.db[Const.OID_UNIVERSE].turn |
||
833 | # record changes from valid pacts |
||
834 | for partyID in obj.diplomacyRels: |
||
835 | dipl = obj.diplomacyRels[partyID] |
||
836 | # check contact |
||
837 | if dipl.contactType == Const.CONTACT_NONE: |
||
838 | #@log.debug("Skipping contact", obj.oid, partyID) |
||
839 | continue |
||
840 | # base change of relation |
||
841 | dipl.relChng += Rules.baseRelationChange |
||
842 | # process pacts |
||
843 | for pactID in dipl.pacts: |
||
844 | #@log.debug("Processing pact", obj.oid, partyID, pactID, dipl.pacts[pactID]) |
||
845 | if dipl.pacts[pactID][0] != Const.PACT_ACTIVE: |
||
846 | continue |
||
847 | pactSpec = Rules.pactDescrs[pactID] |
||
848 | if dipl.relation < pactSpec.validityInterval[0] or \ |
||
849 | dipl.relation > pactSpec.validityInterval[1] or \ |
||
850 | dipl.relChng < Rules.relLostWhenAttacked / 2: |
||
851 | # skip this non active pact, mark it as off |
||
852 | # mark all pact off when attacked |
||
853 | dipl.pacts[pactID][0] = Const.PACT_OFF |
||
854 | # TODO report it |
||
855 | continue |
||
856 | # pact is valid |
||
857 | if dipl.relation < pactSpec.targetRel: |
||
858 | #@log.debug("Affecting relation", pactSpec.relChng) |
||
859 | dipl.relChng += min(pactSpec.targetRel - dipl.relation, pactSpec.relChng) |
||
860 | # apply relation changes |
||
861 | for partyID in obj.diplomacyRels: |
||
862 | dipl = obj.diplomacyRels[partyID] |
||
863 | dipl.relation += dipl.relChng |
||
864 | dipl.relation = min(dipl.relation, Const.REL_ALLY_HI) |
||
865 | dipl.relation = max(dipl.relation, Const.REL_ENEMY_LO) |
||
866 | #@log.debug('IPlayer', 'Final relation', obj.oid, partyID, dipl.relation, dipl.relChng) |
||
867 | |||
868 | @public(Const.AL_OWNER) |
||
869 | def getScannerMap(self, tran, obj): |
||
870 | scanLevels = {} |
||
871 | # full map for the admin |
||
872 | if obj.oid == Const.OID_ADMIN: |
||
873 | universe = tran.db[Const.OID_UNIVERSE] |
||
874 | for galaxyID in universe.galaxies: |
||
875 | galaxy = tran.db[galaxyID] |
||
876 | for systemID in galaxy.systems: |
||
877 | system = tran.db[systemID] |
||
878 | obj.staticMap[systemID] = 111111 |
||
879 | for planetID in system.planets: |
||
880 | obj.staticMap[planetID] = 111111 |
||
881 | # adding systems with buoys |
||
882 | for objID in obj.buoys: |
||
883 | scanLevels[objID] = Rules.level1InfoScanPwr |
||
884 | # fixing system scan level for mine fields |
||
885 | systems = {} |
||
886 | for planetID in obj.planets: |
||
887 | systems[tran.db[planetID].compOf] = None |
||
888 | for systemID in systems.keys(): |
||
889 | scanLevels[systemID] = Rules.partnerScanPwr |
||
890 | # player's map |
||
891 | for objID in obj.staticMap: |
||
892 | scanLevels[objID] = max(scanLevels.get(objID, 0), obj.staticMap[objID]) |
||
893 | for objID in obj.dynamicMap: |
||
894 | scanLevels[objID] = max(scanLevels.get(objID, 0), obj.dynamicMap[objID]) |
||
895 | # parties' map |
||
896 | for partnerID in obj.diplomacyRels: |
||
897 | if self.cmd(obj).isPactActive(tran, obj, partnerID, Const.PACT_SHARE_SCANNER): |
||
898 | # load partner's map |
||
899 | partner = tran.db[partnerID] |
||
900 | for objID in partner.staticMap: |
||
901 | scanLevels[objID] = max(scanLevels.get(objID, 0), partner.staticMap[objID]) |
||
902 | for objID in partner.dynamicMap: |
||
903 | scanLevels[objID] = max(scanLevels.get(objID, 0), partner.dynamicMap[objID]) |
||
904 | # partner's fleets and planets |
||
905 | for objID in partner.fleets: |
||
906 | scanLevels[objID] = Rules.partnerScanPwr |
||
907 | for objID in partner.planets: |
||
908 | scanLevels[objID] = Rules.partnerScanPwr |
||
909 | |||
910 | # create map |
||
911 | map = dict() |
||
912 | for objID, level in scanLevels.iteritems(): |
||
913 | tmpObj = tran.db.get(objID, None) |
||
914 | if not tmpObj: |
||
915 | continue |
||
916 | # add movement validation data |
||
917 | if tmpObj.type in (Const.T_SYSTEM,Const.T_WORMHOLE) and objID not in obj.validSystems: |
||
918 | obj.validSystems.append(objID) |
||
919 | for info in self.cmd(tmpObj).getScanInfos(tran, tmpObj, level, obj): |
||
920 | if (info.oid not in map) or (info.scanPwr > map[info.oid].scanPwr): |
||
921 | map[info.oid] = info |
||
922 | |||
923 | return map |
||
924 | |||
925 | #@public(Const.AL_OWNER) |
||
926 | def mergeScannerMap(self, tran, obj, map): |
||
927 | #@log.debug(obj.oid, "Merging scanner map") |
||
928 | contacts = {} |
||
929 | for object, level in map.iteritems(): |
||
930 | objID = object.oid |
||
931 | if object.type in (Const.T_SYSTEM, Const.T_WORMHOLE): |
||
932 | obj.staticMap[objID] = max(obj.staticMap.get(objID, 0), level) |
||
933 | contacts.update(object.scannerPwrs) |
||
934 | elif object.type == Const.T_FLEET: |
||
935 | obj.dynamicMap[objID] = max(obj.dynamicMap.get(objID, 0), level) |
||
936 | contacts[object.owner] = None |
||
937 | else: |
||
938 | raise ige.GameException("Unsupported type %d" % object.type) |
||
939 | if obj.oid in contacts: |
||
940 | del contacts[obj.oid] |
||
941 | if Const.OID_NONE in contacts: |
||
942 | del contacts[Const.OID_NONE] |
||
943 | for partyID in contacts: |
||
944 | # add to player's contacts |
||
945 | dipl = self.cmd(obj).getDiplomacyWith(tran, obj, partyID) |
||
946 | dipl.contactType = max(dipl.contactType, Const.CONTACT_DYNAMIC) |
||
947 | dipl.lastContact = tran.db[Const.OID_UNIVERSE].turn |
||
948 | # add to detected owner's contacts |
||
949 | owner = tran.db[partyID] |
||
950 | assert owner.type in Const.PLAYER_TYPES |
||
951 | dipl = self.cmd(obj).getDiplomacyWith(tran, owner, obj.oid) |
||
952 | dipl.contactType = max(dipl.contactType, Const.CONTACT_DYNAMIC) |
||
953 | dipl.lastContact = tran.db[Const.OID_UNIVERSE].turn |
||
954 | |||
955 | @public(Const.AL_ADMIN) |
||
956 | def processRSRCHPhase(self, tran, obj, data): |
||
957 | if not obj.timeEnabled: |
||
958 | return |
||
959 | # sci pts from allies |
||
960 | pts = obj.sciPoints |
||
961 | for partnerID in obj.diplomacyRels: |
||
962 | if self.cmd(obj).isPactActive(tran, obj, partnerID, Const.PACT_MINOR_SCI_COOP): |
||
963 | partner = tran.db[partnerID] |
||
964 | pactSpec = Rules.pactDescrs[Const.PACT_MINOR_SCI_COOP] |
||
965 | pts += min( |
||
966 | int(partner.sciPoints * pactSpec.effectivity), |
||
967 | int(obj.sciPoints * pactSpec.effectivity), |
||
968 | ) |
||
969 | if self.cmd(obj).isPactActive(tran, obj, partnerID, Const.PACT_MAJOR_SCI_COOP): |
||
970 | partner = tran.db[partnerID] |
||
971 | pactSpec = Rules.pactDescrs[Const.PACT_MAJOR_SCI_COOP] |
||
972 | pts += min( |
||
973 | int(partner.sciPoints * pactSpec.effectivity), |
||
974 | int(obj.sciPoints * pactSpec.effectivity), |
||
975 | ) |
||
976 | # compute effective sci pts |
||
977 | obj.effSciPoints = epts = pts - int(obj.stats.storPop * Rules.sciPtsPerCitizen[obj.techLevel]) |
||
978 | index = 0 |
||
979 | while epts > 0 and obj.rsrchQueue and index < len(obj.rsrchQueue): |
||
980 | item = obj.rsrchQueue[index] |
||
981 | tech = Rules.techs[item.techID] |
||
982 | # check requirements |
||
983 | canResearch = 1 |
||
984 | # player has to be a right race |
||
985 | if obj.race not in tech.researchRaces: |
||
986 | canResearch = 0 |
||
987 | for stratRes in tech.researchReqSRes: |
||
988 | if obj.stratRes.get(stratRes, 0) < 1 and item.improvement == 1: |
||
989 | Utils.sendMessage(tran, obj, Const.MSG_MISSING_STRATRES, Const.OID_NONE, stratRes) |
||
990 | canResearch = 0 |
||
991 | break |
||
992 | for tmpTechID in obj.techs: |
||
993 | if item.techID in Rules.techs[tmpTechID].researchDisables: |
||
994 | canResearch = 0 |
||
995 | Utils.sendMessage(tran, obj, Const.MSG_DELETED_RESEARCH, Const.OID_NONE, item.techID) |
||
996 | del obj.rsrchQueue[index] |
||
997 | index -= 1 |
||
998 | break |
||
999 | if tech.level > obj.techLevel: |
||
1000 | canResearch = 0 |
||
1001 | Utils.sendMessage(tran, obj, Const.MSG_DELETED_RESEARCH, Const.OID_NONE, item.techID) |
||
1002 | del obj.rsrchQueue[index] |
||
1003 | index -= 1 |
||
1004 | if not canResearch: |
||
1005 | index += 1 |
||
1006 | continue |
||
1007 | researchSci = Utils.getTechRCost(obj, item.techID) |
||
1008 | wantSci = min(epts, researchSci - item.currSci, |
||
1009 | researchSci / tech.researchTurns) |
||
1010 | item.currSci += wantSci |
||
1011 | item.changeSci = wantSci |
||
1012 | epts -= wantSci |
||
1013 | if item.currSci >= researchSci: |
||
1014 | del obj.rsrchQueue[index] |
||
1015 | obj.techs[item.techID] = item.improvement |
||
1016 | # call finish handler |
||
1017 | tech = Rules.techs[item.techID] |
||
1018 | tech.finishResearchHandler(tran, obj, tech) |
||
1019 | Utils.sendMessage(tran, obj, Const.MSG_COMPLETED_RESEARCH, Const.OID_NONE, item.techID) |
||
1020 | # update derived attributes of player |
||
1021 | self.cmd(obj).update(tran, obj) |
||
1022 | # repeat research if required by player |
||
1023 | if item.improveToMax == 1 and item.improvement < Rules.techMaxImprovement: |
||
1024 | # reinsert the item on the top of the queue |
||
1025 | self.cmd(obj).startResearch(tran, obj, item.techID, improveToMax = 1) |
||
1026 | idx = len(obj.rsrchQueue) - 1 |
||
1027 | self.cmd(obj).moveResearch(tran, obj, idx, - idx) |
||
1028 | if epts > 0 and 0: # TODO: remove me |
||
1029 | Utils.sendMessage(tran, obj, Const.MSG_WASTED_SCIPTS, Const.OID_NONE, epts) |
||
1030 | return |
||
1031 | # oops we have negative epts (AI does not regress) |
||
1032 | isAI = obj.type in Const.AI_PLAYER_TYPES |
||
1033 | while epts < 0 and not isAI: |
||
1034 | log.debug("Not enough RP", epts, obj.oid) |
||
1035 | if obj.rsrchQueue: |
||
1036 | item = obj.rsrchQueue[0] |
||
1037 | if item.currSci > 0: |
||
1038 | wantSci = min(item.currSci, - epts) |
||
1039 | item.currSci -= wantSci |
||
1040 | item.changeSci = - wantSci |
||
1041 | epts += wantSci |
||
1042 | if item.currSci == 0: |
||
1043 | # remove item from the queue - TODO send message to player |
||
1044 | del obj.rsrchQueue[0] |
||
1045 | # at this point, epts can be zero |
||
1046 | if epts == 0: |
||
1047 | log.debug("RP deficit satisfied", obj.oid) |
||
1048 | break |
||
1049 | # try next project |
||
1050 | if obj.rsrchQueue: |
||
1051 | continue |
||
1052 | # oops we must find technology to degrade |
||
1053 | avail = obj.techs.keys() |
||
1054 | # do not degrade technologies, which enables others |
||
1055 | for techID in obj.techs: |
||
1056 | tech = Rules.techs[techID] |
||
1057 | for tmpTechID, impr in tech.researchRequires: |
||
1058 | if tmpTechID in avail: |
||
1059 | avail.remove(tmpTechID) |
||
1060 | log.debug("Techs avialable for degradation", avail) |
||
1061 | if not avail: |
||
1062 | # no technology... |
||
1063 | break |
||
1064 | # from hight to low IDs |
||
1065 | avail.sort() |
||
1066 | avail.reverse() |
||
1067 | degraded = 0 |
||
1068 | for level in range(obj.techLevel, 0, -1): |
||
1069 | for techID in avail: |
||
1070 | tech = Rules.techs[techID] |
||
1071 | # check level |
||
1072 | if tech.level != level: |
||
1073 | continue |
||
1074 | # do not touch starting technologies |
||
1075 | if tech.isStarting and obj.techs[techID] <= 3: |
||
1076 | continue |
||
1077 | # ok we have one to degrade |
||
1078 | item = IDataHolder() |
||
1079 | item.techID = techID |
||
1080 | item.improvement = obj.techs[techID] |
||
1081 | item.currSci = Utils.getTechRCost(obj, techID, obj.techs[techID]) |
||
1082 | item.changeSci = 0 |
||
1083 | item.improveToMax = 0 |
||
1084 | item.type = Const.T_RESTASK |
||
1085 | obj.rsrchQueue.append(item) |
||
1086 | # degrade tech |
||
1087 | if obj.techs[techID] == 1: |
||
1088 | # TODO send message |
||
1089 | del obj.techs[techID] |
||
1090 | else: |
||
1091 | # TODO send message |
||
1092 | obj.techs[techID] -= 1 |
||
1093 | if tech.recheckWhenTechLost: |
||
1094 | # reset some attributes |
||
1095 | plLevel = obj.techLevel |
||
1096 | obj.techLevel = 1 |
||
1097 | # recheck remaining techs |
||
1098 | for level in range(1, plLevel + 1): |
||
1099 | for techID in obj.techs: |
||
1100 | tech = Rules.techs[techID] |
||
1101 | if tech.level != level: |
||
1102 | continue |
||
1103 | # call finish handler again |
||
1104 | tech.finishResearchHandler(tran, obj, tech) |
||
1105 | degraded = 1 |
||
1106 | break |
||
1107 | if degraded: break |
||
1108 | |||
1109 | return |
||
1110 | |||
1111 | @public(Const.AL_ADMIN) |
||
1112 | def processACTIONPhase(self, tran, obj, data): |
||
1113 | return NotImplementedError() |
||
1114 | |||
1115 | @public(Const.AL_ADMIN) |
||
1116 | def processINITPhase(self, tran, obj, data): |
||
1117 | if not obj.timeEnabled: |
||
1118 | return |
||
1119 | # reset stats |
||
1120 | obj.stats.storPop = 0 |
||
1121 | obj.stats.prodProd = 0 |
||
1122 | obj.stats.effProdProd = 0 |
||
1123 | obj.stats.prodSci = 0 |
||
1124 | obj.stats.effProdSci = 0 |
||
1125 | obj.stats.slots = 0 |
||
1126 | obj.stats.structs = 0 |
||
1127 | obj.stats.planets = 0 |
||
1128 | obj.stats.fleetPwr = 0 |
||
1129 | obj.stats.fleetSupportProd = 0 |
||
1130 | obj.govPwr = Rules.baseGovPwr |
||
1131 | # remove old messages |
||
1132 | self.cmd(obj).deleteOldMsgs(tran, obj) |
||
1133 | # clear fleet upgrade flag |
||
1134 | obj.fleetUpgradeInProgress = 0 |
||
1135 | # clear production pool |
||
1136 | obj.prodIncreasePool = 0 |
||
1137 | # clear map |
||
1138 | obj.dynamicMap.clear() |
||
1139 | # set empty population distribution |
||
1140 | obj.tmpPopDistr = {} |
||
1141 | # do not process other cmds if time disabled |
||
1142 | # clear contacts and delete too old rels |
||
1143 | turn = tran.db[Const.OID_UNIVERSE].turn |
||
1144 | for objID in obj.diplomacyRels.keys(): |
||
1145 | dipl = obj.diplomacyRels[objID] |
||
1146 | # reset contact type |
||
1147 | obj.diplomacyRels[objID].contactType = Const.CONTACT_NONE |
||
1148 | # delete old contacts |
||
1149 | if dipl.lastContact + Rules.contactTimeout < turn: |
||
1150 | del obj.diplomacyRels[objID] |
||
1151 | continue |
||
1152 | # lower scan powers in static map |
||
1153 | for objID in obj.staticMap: |
||
1154 | level = obj.staticMap[objID] |
||
1155 | if level > Rules.level3InfoScanPwr: |
||
1156 | obj.staticMap[objID] = max( |
||
1157 | Rules.level3InfoScanPwr, |
||
1158 | int(level * Rules.mapForgetScanPwr), |
||
1159 | ) |
||
1160 | #@log.debug(obj.oid, "player static map fix", objID, level - obj.staticMap[objID]) |
||
1161 | # clear relations change indicator |
||
1162 | for partyID in obj.diplomacyRels: |
||
1163 | obj.diplomacyRels[partyID].relChng = 0 |
||
1164 | # reset science points |
||
1165 | obj.sciPoints = 0 |
||
1166 | |||
1167 | @public(Const.AL_ADMIN) |
||
1168 | def processFINALPhase(self, tran, obj, data): |
||
1169 | if not obj.timeEnabled: |
||
1170 | return |
||
1171 | #try/except so that entire final process doesn't break on error in sub-phase |
||
1172 | try: |
||
1173 | self.cmd(obj).processRSRCHPhase(tran, obj, data) |
||
1174 | except: |
||
1175 | log.warning('Cannot execute FINAL/RSRCH on %d' % (obj.oid)) |
||
1176 | try: |
||
1177 | self.cmd(obj).processDIPLPhase(tran, obj, data) |
||
1178 | except: |
||
1179 | log.warning('Cannot execute FINAL/DIPL on %d' % (obj.oid)) |
||
1180 | # efficiency |
||
1181 | obj.prodEff = 1.0 |
||
1182 | obj.sciEff = 1.0 |
||
1183 | if obj.imperator == 1: |
||
1184 | log.debug(obj.oid, "Leader bonus") |
||
1185 | obj.prodEff += Rules.galLeaderBonus |
||
1186 | obj.sciEff += Rules.galLeaderBonus |
||
1187 | elif obj.imperator >= 2: |
||
1188 | log.debug(obj.oid, "Imperator bonus") |
||
1189 | obj.prodEff += Rules.galImperatorBonus |
||
1190 | obj.sciEff += Rules.galImperatorBonus |
||
1191 | #@log.debug("Fleet upgrade pool", obj.oid, obj.fleetUpgradePool, obj.fleetUpgradeInProgress) |
||
1192 | # compute some stats |
||
1193 | # TODO remove, RAW SCI PTS represented now obj.stats.prodSci = obj.effSciPoints |
||
1194 | obj.stats.planets = len(obj.planets) |
||
1195 | # fleet support |
||
1196 | #@log.debug("Fleet support", obj.oid, obj.stats.fleetSupportProd, obj.stats.prodProd) |
||
1197 | if obj.stats.fleetSupportProd > 0 and obj.stats.prodProd > 0: |
||
1198 | # TODO 0.1 shall be dependend on the race / government type |
||
1199 | obj.prodEff += min(0.1 - float(obj.stats.fleetSupportProd + obj.fleetUpgradePool * Rules.operProdRatio) / obj.stats.prodProd, 0.0) |
||
1200 | # delete non active player |
||
1201 | if obj.lastLogin + Rules.playerTimeout < time.time(): |
||
1202 | log.message("Resigning inactive player", obj.name, obj.oid) |
||
1203 | # TODO send a message? |
||
1204 | self.cmd(obj).resign(tran, obj) |
||
1205 | # delete nonactive newbie player |
||
1206 | if obj.lastLogin + Rules.novicePlayerTimeout < time.time() \ |
||
1207 | and len(obj.planets) < 4: |
||
1208 | log.message("Resigning inactive novice player", obj.name, obj.oid) |
||
1209 | # TODO send a message? |
||
1210 | self.cmd(obj).resign(tran, obj) |
||
1211 | # acquire government power |
||
1212 | if obj.planets: |
||
1213 | planet = tran.db[obj.planets[0]] |
||
1214 | for slot in planet.slots: |
||
1215 | tech = Rules.techs[slot[Const.STRUCT_IDX_TECHID]] |
||
1216 | if tech.govPwr > 0 and slot[Const.STRUCT_IDX_STATUS] & Const.STRUCT_STATUS_ON: |
||
1217 | eff = Utils.getTechEff(tran, slot[Const.STRUCT_IDX_TECHID], obj.oid) |
||
1218 | obj.govPwr = max(int(tech.govPwr * eff * (slot[Const.STRUCT_IDX_OPSTATUS] / 100.0)), obj.govPwr) |
||
1219 | # compute government controll range |
||
1220 | if not hasattr(obj,"tmpPopDistr"): #when player is force-resigned, tmpPopDistr is unset. This is easiest fix. |
||
1221 | obj.tmpPopDistr = {} |
||
1222 | ranges = obj.tmpPopDistr.keys() |
||
1223 | ranges.sort() |
||
1224 | sum = 0 |
||
1225 | range = 1 |
||
1226 | for range in ranges: |
||
1227 | sum += obj.tmpPopDistr[range] |
||
1228 | if sum > obj.govPwr: |
||
1229 | break |
||
1230 | obj.govPwrCtrlRange = max(1, range) |
||
1231 | if sum < obj.govPwr and sum > 0: |
||
1232 | #@log.debug(obj.oid, "GovPwr compensation", obj.govPwrCtrlRange, obj.govPwr, sum) |
||
1233 | obj.govPwrCtrlRange = int(obj.govPwrCtrlRange * obj.govPwr / float(sum)) |
||
1234 | #@log.debug(obj.oid, "GovPwr control range", obj.govPwrCtrlRange) |
||
1235 | # compute prodBonus and sciBonus |
||
1236 | sum = 0 |
||
1237 | for range in ranges: |
||
1238 | sum += obj.tmpPopDistr[range] |
||
1239 | if sum < obj.govPwr and sum > 0: |
||
1240 | ratio = float(obj.govPwr - sum) / obj.govPwr |
||
1241 | #@log.debug(obj.oid, "SMALL EMPIRE BONUS", ratio, "govPwr", obj.govPwr, "sum", sum) |
||
1242 | # TODO let user to define how much to invest into prod and to sci |
||
1243 | obj.prodEff += ratio / 2 |
||
1244 | obj.sciEff += ratio / 2 |
||
1245 | del obj.tmpPopDistr # delete temporary attribute |
||
1246 | # increase prod eff from pacts |
||
1247 | # CPs from allies |
||
1248 | sum = 0 |
||
1249 | for partnerID in obj.diplomacyRels: |
||
1250 | if self.cmd(obj).isPactActive(tran, obj, partnerID, Const.PACT_MINOR_CP_COOP): |
||
1251 | partner = tran.db[partnerID] |
||
1252 | pactSpec = Rules.pactDescrs[Const.PACT_MINOR_CP_COOP] |
||
1253 | sum += min( |
||
1254 | partner.stats.prodProd * pactSpec.effectivity, |
||
1255 | obj.stats.prodProd * pactSpec.effectivity, |
||
1256 | ) |
||
1257 | if self.cmd(obj).isPactActive(tran, obj, partnerID, Const.PACT_MAJOR_CP_COOP): |
||
1258 | partner = tran.db[partnerID] |
||
1259 | pactSpec = Rules.pactDescrs[Const.PACT_MAJOR_CP_COOP] |
||
1260 | sum += min( |
||
1261 | partner.stats.prodProd * pactSpec.effectivity, |
||
1262 | obj.stats.prodProd * pactSpec.effectivity, |
||
1263 | ) |
||
1264 | # apply production increase pool |
||
1265 | obj.prodIncreasePool += sum |
||
1266 | if obj.stats.prodProd > 0: |
||
1267 | ratio = (Rules.unusedProdMod * obj.prodIncreasePool) / obj.stats.prodProd |
||
1268 | real = min(ratio, math.sqrt(ratio)) |
||
1269 | #@log.debug(obj.oid, "Increase production by", ratio, "real", real) |
||
1270 | obj.prodEff += real |
||
1271 | # clean up prodEff if prodEff < 0 (prevent abuse) |
||
1272 | if obj.prodEff < 0: |
||
1273 | obj.prodEff = 0.0 |
||
1274 | # clean up ship redirections |
||
1275 | systems = {} |
||
1276 | for planetID in obj.planets: |
||
1277 | systems[tran.db[planetID].compOf] = None |
||
1278 | for systemID in obj.shipRedirections.keys(): |
||
1279 | if systemID not in systems: |
||
1280 | del obj.shipRedirections[systemID] |
||
1281 | |||
1282 | # delete allied bouys |
||
1283 | obj.alliedBuoys = {} |
||
1284 | |||
1285 | # find all allies |
||
1286 | for partnerID in obj.diplomacyRels.keys(): |
||
1287 | dipl = obj.diplomacyRels[partnerID] |
||
1288 | getAllyBuoys = False |
||
1289 | getScannerBuoys = False |
||
1290 | if dipl.relation >= Const.REL_ALLY_LO: |
||
1291 | getAllyBuoys = True |
||
1292 | if self.isPactActive(tran, obj, partnerID, Const.PACT_SHARE_SCANNER): |
||
1293 | getScannerBuoys = True |
||
1294 | if (getAllyBuoys or getScannerBuoys): |
||
1295 | partner = tran.db[partnerID] |
||
1296 | if hasattr(partner, "buoys"): |
||
1297 | for systemID in partner.buoys.keys(): |
||
1298 | toAllyBuoy = Const.BUOY_NONE |
||
1299 | if getAllyBuoys and partner.buoys[systemID][1] == Const.BUOY_TO_ALLY: |
||
1300 | toAllyBuoy = (partner.buoys[systemID][0], Const.BUOY_FROM_ALLY, partner.name) |
||
1301 | elif getScannerBuoys and partner.buoys[systemID][1] == Const.BUOY_TO_SCANNERSHARE: |
||
1302 | toAllyBuoy = (partner.buoys[systemID][0], Const.BUOY_FROM_ALLY, partner.name) |
||
1303 | if toAllyBuoy != Const.BUOY_NONE: |
||
1304 | if systemID in obj.alliedBuoys: |
||
1305 | obj.alliedBuoys[systemID].append(toAllyBuoy) |
||
1306 | else: |
||
1307 | obj.alliedBuoys[systemID] = [toAllyBuoy] |
||
1308 | return None |
||
1309 | |||
1310 | ## messaging |
||
1311 | def canSendMsg(self, tran, obj, oid, forum): |
||
1312 | if forum == "INBOX": |
||
1313 | sender = tran.db[oid] |
||
1314 | return oid == Const.OID_ADMIN or (oid in obj.diplomacyRels) or \ |
||
1315 | (obj.oid in sender.diplomacyRels) |
||
1316 | if forum == "OUTBOX": |
||
1317 | return obj.oid == oid |
||
1318 | return 0 |
||
1319 | |||
1320 | @public(Const.AL_OWNER) |
||
1321 | def cleanUpMsgs(self, tran, obj): |
||
1322 | # get messages |
||
1323 | msgs = self.cmd(obj).getMsgs(tran, obj) |
||
1324 | # build list of events |
||
1325 | delete = [] |
||
1326 | for msg in msgs: |
||
1327 | if msg["forum"] == "EVENTS": |
||
1328 | delete.append(msg["id"]) |
||
1329 | # delete |
||
1330 | self.cmd(obj).deleteMsgs(tran, obj, delete) |
||
1331 | return 1 |
||
1332 | |||
1333 | @public(Const.AL_OWNER) |
||
1334 | def setResolution(self, tran, obj, x, y): |
||
1335 | if not hasattr(obj,'clientStats'): |
||
1336 | obj.clientStats = {} |
||
1337 | obj.clientStats['x'] = x; |
||
1338 | obj.clientStats['y'] = y; |
||
1339 | |||
1340 | def getResolution(self, obj): |
||
1341 | if not hasattr(obj,'clientStats'): |
||
1342 | obj.clientStats = {} |
||
1343 | if 'x' in obj.clientStats and 'y' in obj.clientStats: |
||
1344 | return ("%s,%s" % (obj.clientStats['x'],obj.clientStats['y'])) |
||
1345 | else: |
||
1346 | return "0,0" |
||
1347 | |||
1348 | @public(Const.AL_FULL) |
||
1349 | def addObsoleteTechs(self, tran, player, techID): |
||
1350 | # add tech |
||
1351 | temp = set([techID]) |
||
1352 | player.obsoleteTechs = player.obsoleteTechs | temp |
||
1353 | return player.obsoleteTechs |
||
1354 | |||
1355 | @public(Const.AL_FULL) |
||
1356 | def delObsoleteTechs(self, tran, player, techID): |
||
1357 | # del tech |
||
1358 | temp = set([techID]) |
||
1359 | player.obsoleteTechs = player.obsoleteTechs - temp |
||
1360 | return player.obsoleteTechs |
||
1361 | |||
1362 |