Imported Upstream version 2008.1+svn1553
[opeanno-debian-packaging.git] / game / world / storage.py
blobc8e4bd35e1831bf0c8eea3049b85520c45be0063
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 game.util.stablelist import stablelist
23 from game.util import WorldObject
24 import game.main
26 class Storage(WorldObject):
27 """Class that represent a storage compartment with fixed resources slots
29 Used e.g. by production buildings (e.g. PrimaryProducer)
30 """
31 def __init__(self, **kwargs):
32 super(Storage, self).__init__(**kwargs)
33 # inventory: a dict with this pattern: _inventory[res_id] = [amount, size]
34 self._inventory = {}
36 def addSlot(self, res_id, size):
37 """ Add the possibility to save size amount of res_id
38 @param res_id: id of the resource
39 @param size: maximum amount of res_id that can be stored here; -1 for infinity
40 """
41 self._inventory[res_id] = [0, size]
42 self._changed()
44 def hasSlot(self, res_id):
45 """ Returns wether slot for res_id exists"""
46 return (res_id in self._inventory.keys())
48 def alter_inventory(self, res_id, amount):
49 """Alters the inventory for the resource res_id with amount.
50 @param res_id: int resource_id
51 @param amount: amount that is to be added.
52 @return: amount that couldn't be stored in this storage"""
53 new_amount = 0
54 try:
55 new_amount = self._inventory[res_id][0] + amount
56 except KeyError:
57 return amount
58 if new_amount > self.get_size(res_id) and self.get_size(res_id) != -1:
59 # stuff doesn't fit in inventory
60 ret = new_amount - self.get_size(res_id)
61 self._inventory[res_id][0] = self.get_size(res_id)
62 self._changed()
63 return ret
64 elif new_amount < 0:
65 # trying to take more stuff than inventory contains
66 ret = new_amount
67 self._inventory[res_id][0] = 0
68 self._changed()
69 return ret
70 else:
71 # new amount is in boundaries
72 self._inventory[res_id][0] = new_amount
73 self._changed()
74 return 0
76 def get_value(self, res_id):
77 """Returns amount of resource res_id in the storage
78 NOTE: this returns "false" value depending on carriages, that are on their way
79 alter_inventory always returns acctual value of res currently in the building
80 @param res_id: int resource_id
81 @return: int amount of resources for res_id in inventory.
82 """
83 try:
84 value = self._inventory[res_id][0]
86 # subtract/add carriage stuff
87 """
88 for carriage in self.building.pickup_carriages:
89 if len(carriage.target) > 0:
90 if carriage.target[1] == res_id:
91 value -= carriage.target[2]
92 for carriage in self.building.local_carriages:
93 if len(carriage.target) > 0:
94 if carriage.target[1] == res_id:
95 value += carriage.target[2]
96 """
98 return value
99 except KeyError:
100 return 0
102 def get_size(self, res_id):
103 """ Returns the capacity of the storage for resource res_id
104 @param res_id: int resource_id
106 return self._inventory[res_id][1]
108 def __repr__(self):
109 return repr(self._inventory)
111 def __str__(self):
112 return str(self._inventory)
114 def save(self, db, ownerid):
115 super(Storage, self).save(db)
116 for (res, (value, size)) in self._inventory.iteritems():
117 db("INSERT INTO storage (object, resource, amount) VALUES (?, ?, ?) ",
118 ownerid, res, value)
120 def load(self, db, ownerid):
121 for (res, amount) in db("SELECT resource, amount FROM storage WHERE object = ?", ownerid):
122 self.alter_inventory(res, amount)
125 class ArbitraryStorage(WorldObject):
126 """Class that represents a storage compartment for ships
127 Storages have a certain number of slots and a certain maximum number of
128 resources that they can store for a certain slot.
130 def __init__(self, slots, size):
131 self._inventory = stablelist()
132 self.slots = slots
133 self.size = size
135 def alter_inventory(self, res_id, amount):
136 # try using existing slots
137 for slot in self._inventory:
138 if slot[0] == res_id:
139 new_amount = slot[1] + amount
140 if new_amount < 0:
141 slot[1] = 0
142 amount = new_amount
143 elif new_amount > self.size:
144 slot[1] = self.size
145 amount = new_amount - self.size
146 else:
147 slot[1] = new_amount
148 self._changed()
149 return 0
151 # handle stuff that couldn't be handled with existing slots
152 if amount > 0:
153 if len(self._inventory) < self.slots:
154 if amount > self.size:
155 self._inventory.append([res_id, self.size])
156 self._changed()
157 return self.alter_inventory(res_id, amount - self.size)
158 else:
159 self._inventory.append([res_id, amount])
160 amount = 0
162 # return what couldn't be added/taken
163 self._changed()
164 return amount
166 def get_value(self, res_id):
167 ret = 0
168 for slot in self._inventory:
169 if slot[0] == res_id:
170 ret += slot[1]
171 return ret
173 def get_size(self, res_id):
174 """This just ensures compatibility with Storage"""
175 ## TODO: if carriage is on the way, ensure that other slots won't get filled
176 size = 0
177 for slot in self._inventory:
178 if slot[0] == res_id and slot[1] < self.size:
179 size += self.size - slot[1]
181 size += (self.slots - len(self._inventory)) * self.size
182 return size
184 def save(self, db, ownerid):
185 super(Storage, self).save(db)
186 for slot in self._inventory:
187 db("INSERT INTO storage (object, resource, amount) VALUES (?, ?, ?) ",
188 ownerid, slot[0], slot[1])
190 def load(self, db, ownerid):
191 #super(Storage, self).load(db)
192 for (res, amount) in db("SELECT resource, amount FROM storage WHERE object = ?", ownerid):
193 self.alter_inventory(res, amount)
196 class GenericStorage(object):
197 def __init__(self, **kwargs):
198 super(GenericStorage, self).__init__(**kwargs)
199 self._storage = {}
201 def alter(res, amount):
202 if res in self._storage:
203 self._storage[res] += amount
204 else:
205 self._storage[res] = amount
206 return 0
208 def __getitem__(self, res):
209 return self._storage[res] if res in self._storage else 0
211 class SpecializedStorage(GenericStorage):
212 def alter(res, amount):
213 return super(SpecializedStorage, self).alter(res, amount) if res in self._storage else amount
215 def addResourceSlot(res):
216 super(SpecializedStorage, self).alter(res, 0)
218 def hasResourceSlot(res):
219 return res in self._storage
221 class SizedSpecializedStorage(SpecializedStorage):
222 def __init__(self, **kwargs):
223 super(SizedSpecializedStorage, self).__init__(**kwargs)
224 self.__size = {}
226 def alter(res, amount):
227 return amount - super(SizedSpecializedStorage, self).alter(res, amount - max(0, amount + self[res] - self.__size.get(res,0)))
229 def addResourceSlot(res, size, **kwargs):
230 super(SpecializedStorage, self).addResourceSlot(res = res, size = size, **kwargs)
231 self.__size[res] = size
233 class TotalStorage(GenericStorage):
234 def __init__(self, space, **kwargs):
235 super(TotalStorage, self).__init__(space = space, **kwargs)
236 self.__space = space
238 def alter(self, res, amount):
239 return amount - super(TotalStorage, self).alter(res, amount - max(0, amount + sum(self._storage.values()) - self.__space))
241 class PositiveStorage(GenericStorage):
242 def alter(res, amount):
243 return amount - super(PositiveStorage, self).alter(res, amount - min(0, amount + self[res]))
245 class PositiveTotalStorage(PositiveStorage, TotalStorage):
246 pass
248 class PositiveSizedSpecializedStorage(PositiveStorage, SizedSpecializedStorage):
249 pass