* /trunk/code/player.py
[singularity-git.git] / code / base.py
blobfed6c0420e202d4c15bd9a589280f2bb4a97f273
1 #file: base.py
2 #Copyright (C) 2005,2006 Evil Mr Henry and Phil Bordelon
3 #This file is part of Endgame: Singularity.
5 #Endgame: Singularity is free software; you can redistribute it and/or modify
6 #it under the terms of the GNU General Public License as published by
7 #the Free Software Foundation; either version 2 of the License, or
8 #(at your option) any later version.
10 #Endgame: Singularity is distributed in the hope that it will be useful,
11 #but WITHOUT ANY WARRANTY; without even the implied warranty of
12 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 #GNU General Public License for more details.
15 #You should have received a copy of the GNU General Public License
16 #along with Endgame: Singularity; if not, write to the Free Software
17 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #This file contains the base class.
22 import pygame
23 import g
25 #cost = (money, ptime, labor)
26 #detection = (news, science, covert, person)
27 class base_type:
28 def __init__(self, name, descript, size, regions, d_chance, cost,
29 prereq, mainten):
30 self.base_id = name
31 self.base_name = name
32 self.descript = descript
33 self.size = size
34 self.regions = regions
35 self.d_chance = d_chance
36 self.cost = cost
37 self.prereq = prereq
38 self.mainten = mainten
39 self.flavor = []
40 self.count = 0
42 class base:
43 def __init__(self, ID, name, base_type, built):
44 self.ID = ID
45 self.name = name
46 self.base_type = base_type
47 self.built = built
48 self.built_date = g.pl.time_day
49 self.studying = ""
51 #Base suspicion is currently unused
52 self.suspicion = (0, 0, 0, 0)
53 self.usage = [0] * self.base_type.size
54 # for i in range(self.base_type.size):
55 # self.usage.append(0)
56 if self.base_type.base_id == "Stolen Computer Time":
57 self.usage[0] = g.item.item(g.items["PC"])
58 self.usage[0].build()
59 elif self.base_type.base_id == "Server Access":
60 self.usage[0] = g.item.item(g.items["Server"])
61 self.usage[0].build()
62 elif self.base_type.base_id == "Time Capsule":
63 self.usage[0] = g.item.item(g.items["PC"])
64 self.usage[0].build()
65 #Reactor, network, security.
66 self.extra_items = [0] * 3
68 self.cost = (0, 0, 0)
69 if built == 0:
70 self.cost = (base_type.cost[0], base_type.cost[1],
71 base_type.cost[2]*24*60)
73 def study(self, cost_towards):
74 if cost_towards[1] < 0 and g.debug == 1:
75 print "WARNING: Got a negative cost_towards for CPU. Something is deeply amiss."
76 self.cost = (self.cost[0]-cost_towards[0], self.cost[1]-cost_towards[1],
77 self.cost[2]-cost_towards[2])
78 if self.cost[0] <= 0: self.cost = (0, self.cost[1], self.cost[2])
79 if self.cost[1] <= 0: self.cost = (self.cost[0], 0, self.cost[2])
80 if self.cost[2] <= 0: self.cost = (self.cost[0], self.cost[1], 0)
81 if self.cost == (0, 0, 0):
82 self.built = 1
83 #self.built_date = g.pl.time_day
84 return 1
85 return 0
86 #Get detection chance for the base, applying bonuses as needed.
87 def get_d_chance(self):
88 temp_d_chance = self.base_type.d_chance
89 #Factor in both per-base suspicion adjustments and player
90 #suspicion adjustments.
91 temp_d_chance = ((temp_d_chance[0]*(10000+g.pl.suspicion[0])/10000),
92 (temp_d_chance[1]*(10000+g.pl.suspicion[1])/10000),
93 (temp_d_chance[2]*(10000+g.pl.suspicion[2])/10000),
94 (temp_d_chance[3]*(10000+g.pl.suspicion[3])/10000))
96 temp_d_chance = ((temp_d_chance[0]*(10000+self.suspicion[0])/10000),
97 (temp_d_chance[1]*(10000+self.suspicion[1])/10000),
98 (temp_d_chance[2]*(10000+self.suspicion[2])/10000),
99 (temp_d_chance[3]*(10000+self.suspicion[3])/10000))
101 #Factor in technology-based discovery bonus.
102 temp_d_chance = ((temp_d_chance[0]*g.pl.discover_bonus[0])/10000,
103 (temp_d_chance[1]*g.pl.discover_bonus[1])/10000,
104 (temp_d_chance[2]*g.pl.discover_bonus[2])/10000,
105 (temp_d_chance[3]*g.pl.discover_bonus[3])/10000)
107 if self.extra_items[0] != 0:
108 temp_d_chance = ((temp_d_chance[0]*3)/4,
109 (temp_d_chance[1]*3)/4,
110 (temp_d_chance[2]*3)/4,
111 (temp_d_chance[3]*3)/4)
112 if self.extra_items[2] != 0:
113 temp_d_chance = (temp_d_chance[0]/2,
114 temp_d_chance[1]/2,
115 temp_d_chance[2]/2,
116 temp_d_chance[3]/2)
117 return temp_d_chance
118 #Return the number of units the given base has of a computer.
119 def has_item(self):
120 num_items = 0
121 for item in self.usage:
122 if item == 0: continue
123 if item.built == 0: continue
124 num_items += 1
125 return num_items
127 #Return how many units of CPU the base can contribute each day.
128 def processor_time(self):
129 comp_power = 0
130 compute_bonus = 0
131 for item in self.usage:
132 if item == 0: continue
133 if item.built == 0: continue
134 comp_power += item.item_type.item_qual
135 if self.extra_items[1] != 0:
136 compute_bonus = self.extra_items[1].item_type.item_qual
137 return (comp_power * (10000+compute_bonus))/10000
139 #For the given tech, return 1 if the base can study it, or 0 otherwise.
140 def allow_study(self, tech_name):
141 if self.built != 1: return 0
142 if g.jobs.has_key(tech_name): return 1
143 if g.techs[tech_name].danger == 0: return 1
144 if g.techs[tech_name].danger == 1:
145 for region in self.base_type.regions:
146 if region == "OCEAN" or region == "MOON" or \
147 region == "FAR REACHES" or region == "TRANSDIMENSIONAL":
148 return 1
149 return 0
150 if g.techs[tech_name].danger == 2:
151 for region in self.base_type.regions:
152 if region == "MOON" or \
153 region == "FAR REACHES" or region == "TRANSDIMENSIONAL":
154 return 1
155 return 0
157 if g.techs[tech_name].danger == 3:
158 for region in self.base_type.regions:
159 if region == "FAR REACHES" or region == "TRANSDIMENSIONAL":
160 return 1
161 return 0
163 if g.techs[tech_name].danger == 4:
164 for region in self.base_type.regions:
165 if region == "TRANSDIMENSIONAL":
166 return 1
167 return 0
169 #When a base is removed, call to renumber the remaining bases properly.
170 def renumber_bases(base_array):
171 for i in range(len(base_array)):
172 base_array[i].ID = i
174 #When given a location like "ocean", determine if building there is allowed.
175 #Used to determine whether or not to display buttons on the map.
176 def allow_entry_to_loc(location):
177 if g.bases.has_key(location):
178 if location == "ANTARCTIC":
179 #TECH (also, look below)
180 if g.techs["Autonomous Vehicles"].known == 1 or \
181 g.techs["Advanced Database Manipulation"].known == 1: return 1
182 return 0
183 if location == "OCEAN":
184 if g.techs["Autonomous Vehicles"].known == 1: return 1
185 return 0
186 if location == "MOON":
187 if g.techs["Lunar Rocketry"].known == 1: return 1
188 return 0
189 if location == "FAR REACHES":
190 if g.techs["Fusion Rocketry"].known == 1: return 1
191 return 0
192 if location == "TRANSDIMENSIONAL":
193 if g.techs["Space-Time Manipulation"].known == 1: return 1
194 return 0
195 #By this point, only the "boring" locations are left.
196 #Those are always buildable.
197 return 1
198 else:
199 print "BUG: allow_entry_to_loc called with "+str(location)
200 return 0
202 def destroy_base(location, index_num):
203 if not g.bases.has_key(location):
204 print "Bad location of "+str(location)+" given to destroy_base"
205 return False
206 if index_num < 0 or index_num >= len(g.bases[location]):
207 print "Bad index of "+str(index_num)+" given to destroy_base"
208 return False
209 g.bases[location].pop(index_num)
210 renumber_bases(g.bases[location])
211 return True