Imported Upstream version 2008.1+svn1553
[opeanno-debian-packaging.git] / game / world / production.py
blobdb7e511e2ce066cf54fbb9beb92c911c43fb9e4a
1 # ###################################################
2 # Copyright (C) 2008 The OpenAnno Team
3 # team@openanno.org
4 # This file is part of OpenAnno.
6 # OpenAnno 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.
11 # This program 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.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the
18 # Free Software Foundation, Inc.,
19 # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 # ###################################################
22 from provider import Provider
23 from consumer import Consumer
24 from game.world.units.unit import Unit
25 import game.main
26 from game.util import WeakList
27 from game.gui.tabwidget import TabWidget
28 from game.world.building.building import Building
29 import weakref
31 class PrimaryProducer(Provider):
32 """Class used for production buildings"""
33 def __init__(self, **kwargs):
34 """
35 """
36 super(PrimaryProducer, self).__init__(**kwargs)
37 self.active_production_line = None
38 self.__init()
40 def __init(self):
41 self.production = {}
42 self.active = False
44 for (id,) in game.main.db("SELECT rowid FROM data.production_line where %(type)s = ?" % {'type' : 'building' if self.object_type == 0 else 'unit'}, self.id):
45 self.production[id] = ProductionLine(id)
47 self.__used_resources = {}
48 self.toggle_active() # start production
49 if isinstance(self, Building):
50 self.toggle_costs() # needed to get toggle to the right position
52 def toggle_active(self):
53 if self.active:
54 print "Toggled inactive"
55 self.active_production_line = None
56 if self.hasChangeListener(self.check_production_startable):
57 self.removeChangeListener(self.check_production_startable)
58 game.main.session.scheduler.rem_call(self, self.production_step)
59 if isinstance(self, Building):
60 self.toggle_costs()
61 else:
62 print "Toggled active"
63 if self.active_production_line is None and len(self.production) > 0:
64 self.active_production_line = min(self.production.keys())
65 if self.active_production_line is not None:
66 self.addChangeListener(self.check_production_startable)
67 self.check_production_startable()
68 if isinstance(self, Building):
69 self.toggle_costs()
70 self.active = (not self.active)
71 self._changed()
73 def save(self, db):
74 super(PrimaryProducer, self).save(db)
75 # insert active prodline if it isn't in the db
76 if len(db("SELECT active_production_line FROM production WHERE rowid = ?", self.getId())) == 0:
77 db("INSERT INTO production(rowid, active_production_line) VALUES(?, ?)", self.getId(), self.active_production_line)
79 def load(self, db, worldid):
80 super(PrimaryProducer, self).load(db, worldid)
81 active_production_line = db("SELECT active_production_line FROM production WHERE rowid = ?", worldid)
82 assert(0 <= len(active_production_line) <= 1)
83 if len(active_production_line) == 0:
84 self.active_production_line = None
85 else:
86 self.active_production_line = active_production_line[0][0]
87 self.__init()
89 def check_production_startable(self):
90 for res, amount in self.production[self.active_production_line].production.items():
91 if amount > 0 and self.inventory.get_value(res) + amount > self.inventory.get_size(res):
92 return
93 usable_resources = {}
94 if min(self.production[self.active_production_line].production.values()) < 0:
95 for res, amount in self.production[self.active_production_line].production.items():
96 #we have something to work with, if the res is needed, we have something in the inv and we dont already have used everything we need from that resource
97 if amount < 0 and self.inventory.get_value(res) > 0 and self.__used_resources.get(res, 0) < -amount:
98 usable_resources[res] = -amount - self.__used_resources.get(res, 0)
99 if len(usable_resources) == 0:
100 return
101 time = int(round(self.production[self.active_production_line].time * sum(self.__used_resources.values()) / -sum(p for p in self.production[self.active_production_line].production.values() if p < 0)))
102 else:
103 time = 0
104 self.removeChangeListener(self.check_production_startable)
105 for res, amount in usable_resources.items():
106 if res in self.__used_resources:
107 self.__used_resources[res] += amount
108 else:
109 self.__used_resources[res] = amount
110 for res, amount in usable_resources.items():
111 assert(self.inventory.alter_inventory(res, -amount) == 0)
112 game.main.session.scheduler.add_new_object(self.production_step, self, 16 *
113 (self.production[self.active_production_line].time if min(self.production[self.active_production_line].production.values()) >= 0
114 else (int(round(self.production[self.active_production_line].time * sum(self.__used_resources.values()) / -sum(p for p in self.production[self.active_production_line].production.values() if p < 0))
115 ) - time)))
116 self._instance.act("working", self._instance.getFacingLocation(), True)
117 #print self.getId(), "begin working"
119 def production_step(self):
120 #print self.getId(), "production_step"
121 if sum(self.__used_resources.values()) >= -sum(p for p in self.production[self.active_production_line].production.values() if p < 0):
122 for res, amount in self.production[self.active_production_line].production.items():
123 if amount > 0:
124 self.inventory.alter_inventory(res, amount)
125 self.__used_resources = {}
126 self._instance.act("default", self._instance.getFacingLocation(), True)
127 self.addChangeListener(self.check_production_startable)
128 self.check_production_startable()
130 def save(self, db):
131 super(PrimaryProducer, self).save(db)
132 db("INSERT INTO producer (rowid, active_production_line) VALUES(?,?)", self.getId(), self.active_production_line)
135 class SecondaryProducer(Consumer, PrimaryProducer):
136 """Represents a producer, that consumes ressources for production of other ressources (e.g. blacksmith)"""
138 def show_menu(self):
139 callbacks = {
140 'building_production_overview': {
141 'toggle_active': self.toggle_active
144 game.main.session.ingame_gui.show_menu(TabWidget(4, self, callbacks))
147 class ProductionLine(object):
148 def __init__(self, id):
149 self.id = id
150 self.time = game.main.db("SELECT time FROM data.production_line WHERE rowid = ?", self.id)[0][0]
151 self.production = {}
152 for res, amount in game.main.db("SELECT resource, amount FROM data.production WHERE production_line = ?", self.id):
153 self.production[res] = amount