* /trunk/code/g.py
[singularity-git.git] / code / g.py
blob6af5f6a07c2dfe3973d6924f78b8c70c64c013b9
1 #file: g.py
2 #Copyright (C) 2005 Free Software Foundation
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 all global objects.
21 import pygame, sys
22 from os import listdir, path
23 import pickle
24 from random import random
26 import player, base, buttons, tech, item
28 #screen is the actual pygame display.
29 global screen
31 global screen_size
32 screen_size = (800, 600)
34 global clock
35 clock = pygame.time.Clock()
37 global cheater
38 cheater = 0
40 global nosound
41 nosound = 0
43 global debug
44 debug = 0
46 global default_savegame_name
47 default_savegame_name = "player"
49 def quit_game():
50 sys.exit()
52 #colors:
53 colors = {}
55 def fill_colors():
56 colors["white"] = (255, 255, 255, 255)
57 colors["black"] = (0, 0, 0, 255)
58 colors["red"] = (255, 0, 0, 255)
59 colors["green"] = (0, 255, 0, 255)
60 colors["blue"] = (0, 0, 255, 255)
61 colors["dark_red"] = (125, 0, 0, 255)
62 colors["dark_green"] = (0, 125, 0, 255)
63 colors["dark_blue"] = (0, 0, 125, 255)
64 colors["light_red"] = (255, 50, 50, 255)
65 colors["light_green"] = (50, 255, 50, 255)
66 colors["light_blue"] = (50, 50, 255, 255)
69 picts = {}
70 #Load all pictures from the data directory.
71 def load_pictures():
72 global picts
73 if pygame.image.get_extended() == 0:
74 print "Error: SDL_image required. Exiting."
75 sys.exit()
77 temp_pict_array = listdir("../data")
78 for file_name in temp_pict_array:
79 if file_name[-3:] == "png" or file_name[-3:] == "jpg":
80 picts[file_name] = pygame.image.load("../data/"+file_name)
81 picts[file_name] = picts[file_name].convert()
82 picts[file_name].set_colorkey((255, 0, 255, 255), pygame.RLEACCEL)
84 sounds = {}
85 #Load all sounds from the data directory.
86 def load_sounds():
87 global sounds
88 if nosound == 1: return 0
89 #Looking at the pygame docs, I don't see any way to determine if SDL_mixer
90 #is loaded on the target machine. This may crash.
91 pygame.mixer.init()
93 temp_snd_array = listdir("../data")
94 for file_name in temp_snd_array:
95 if file_name[-3:] == "wav":
96 sounds[file_name] = pygame.mixer.Sound("../data/"+file_name)
98 def play_click():
99 #rand_str = str(int(random() * 4))
100 play_sound("click"+str(int(random() * 4))+".wav")
102 def play_sound(sound_file):
103 if nosound == 1: return 0
104 sounds[sound_file].play()
106 # Font functions.
109 #Normal and Acknowledge fonts.
110 global fonts
111 font = []
112 font.append([0] * 51)
113 font.append([0] * 51)
115 #given a surface, string, font, char to underline (int; -1 to len(string)),
116 #xy coord, and color, print the string to the surface.
117 #Align (0=left, 1=Center, 2=Right) changes the alignment of the text
118 def print_string(surface, string_to_print, font, underline_char, xy, color, align=0):
119 if align != 0:
120 temp_size = font.size(string_to_print)
121 if align == 1: xy = (xy[0] - temp_size[0]/2, xy[1])
122 elif align == 2: xy = (xy[0] - temp_size[0], xy[1])
123 if underline_char == -1 or underline_char >= len(string_to_print):
124 temp_text = font.render(string_to_print, 1, color)
125 surface.blit(temp_text, xy)
126 else:
127 temp_text = font.render(string_to_print[:underline_char], 1, color)
128 surface.blit(temp_text, xy)
129 temp_size = font.size(string_to_print[:underline_char])
130 xy = (xy[0] + temp_size[0], xy[1])
131 font.set_underline(1)
132 temp_text = font.render(string_to_print[underline_char], 1, color)
133 surface.blit(temp_text, xy)
134 font.set_underline(0)
135 temp_size = font.size(string_to_print[underline_char])
136 xy = (xy[0] + temp_size[0], xy[1])
137 temp_text = font.render(string_to_print[underline_char+1:], 1, color)
138 surface.blit(temp_text, xy)
140 #Used to display descriptions and such. Automatically wraps the text to fit
141 #within a certain width.
142 def print_multiline(surface, string_to_print, font, width, xy, color):
143 start_xy = xy
144 string_array = string_to_print.split()
146 for string in string_array:
147 string += " "
148 temp_size = font.size(string)
150 if string == "\\n ":
151 xy = (start_xy[0], xy[1]+temp_size[1])
152 continue
153 temp_text = font.render(string, 1, color)
155 if (xy[0]-start_xy[0])+temp_size[0] > width:
156 xy = (start_xy[0], xy[1]+temp_size[1])
157 surface.blit(temp_text, xy)
158 xy = (xy[0]+temp_size[0], xy[1])
160 def create_dialog(string_to_print, box_font, xy, size, bg_color, out_color, text_color):
161 screen.fill(out_color, (xy[0], xy[1], size[0], size[1]))
162 screen.fill(bg_color, (xy[0]+1, xy[1]+1, size[0]-2, size[1]-2))
163 print_multiline(screen, string_to_print, box_font, size[0]-10, (xy[0]+5, xy[1]+5),
164 text_color)
165 menu_buttons = []
166 menu_buttons.append(buttons.button((xy[0]+size[0]/2-50, xy[1]+size[1]+5),
167 (100, 50), "OK", 0, colors["dark_blue"], colors["white"], colors["light_blue"],
168 colors["white"], font[1][30]))
170 for button in menu_buttons:
171 button.refresh_button(0)
172 pygame.display.flip()
174 sel_button = -1
175 while 1:
176 clock.tick(60)
177 for event in pygame.event.get():
178 if event.type == pygame.QUIT: quit_game()
179 elif event.type == pygame.KEYDOWN:
180 if event.key == pygame.K_ESCAPE: return
181 elif event.key == pygame.K_RETURN: return
182 elif event.key == pygame.K_o: return
183 elif event.type == pygame.MOUSEBUTTONUP and event.button == 1:
184 for button in menu_buttons:
185 if button.is_over(event.pos):
186 if button.text == "OK":
187 play_click()
188 return
189 elif event.type == pygame.MOUSEMOTION:
190 sel_button = buttons.refresh_buttons(sel_button, menu_buttons, event)
192 valid_input_characters = ('a','b','c','d','e','f','g','h','i','j','k','l','m',
193 'n','o','p','q','r','s','t','u','v','w','x','y','z',
194 'A','B','C','D','E','F','G','H','I','J','K','L','M',
195 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
196 '0','1','2','3','4','5','6','7','8','9','.',' ')
198 def create_textbox(descript_text, starting_text, box_font, xy, size,
199 max_length, bg_color, out_color, text_color, text_bg_color):
200 screen.fill(out_color, (xy[0], xy[1], size[0], size[1]))
201 screen.fill(bg_color, (xy[0]+1, xy[1]+1, size[0]-2, size[1]-2))
202 screen.fill(out_color, (xy[0]+5, xy[1]+size[1]-30, size[0]-10, 25))
203 # print_string(screen, starting_text, box_font, -1, (xy[0]+5, xy[1]+5), text_color)
204 print_multiline(screen, descript_text, box_font,
205 size[1]-10, (xy[0]+5, xy[1]+5), text_color)
206 #If the cursor is in a blank string, we want it at the beginning;
207 #otherwise put it after the last character.
208 cursor_loc = len(starting_text)
209 # if cursor_loc > 0:
210 # cursor_loc += 1
212 menu_buttons = []
213 menu_buttons.append(buttons.button((xy[0]+size[0]/2-50, xy[1]+size[1]+5),
214 (100, 50), "OK", 0, colors["dark_blue"], colors["white"], colors["light_blue"],
215 colors["white"], font[1][30]))
217 work_string = starting_text
218 for button in menu_buttons:
219 button.refresh_button(0)
220 pygame.display.flip()
221 sel_button = -1
222 need_redraw = True
223 while 1:
224 if need_redraw:
225 draw_cursor_pos = box_font.size(work_string[:cursor_loc])
226 screen.fill(text_bg_color, (xy[0]+6, xy[1]+size[1]-29,
227 size[0]-12, 23))
228 screen.fill(text_color, (xy[0]+6+draw_cursor_pos[0], xy[1]+size[1]-28,
229 1, draw_cursor_pos[1]))
230 print_string(screen, work_string, box_font, -1, (xy[0]+7,
231 xy[1]+size[1]-28), text_color)
232 pygame.display.flip()
233 need_redraw = False
234 for event in pygame.event.get():
235 if event.type == pygame.QUIT: quit_game()
236 elif event.type == pygame.KEYDOWN:
237 if (event.key == pygame.K_ESCAPE): return ""
238 elif (event.key == pygame.K_RETURN): return work_string
239 elif (event.key == pygame.K_BACKSPACE):
240 if cursor_loc > 0:
241 work_string = work_string[:cursor_loc-1]+work_string[cursor_loc:]
242 cursor_loc -= 1
243 need_redraw = True
244 elif (event.key == pygame.K_DELETE):
245 if cursor_loc < len(work_string):
246 work_string = work_string[:cursor_loc]+work_string[cursor_loc+1:]
247 need_redraw = True
248 elif (event.key == pygame.K_LEFT):
249 cursor_loc -= 1
250 if cursor_loc < 0: cursor_loc = 0
251 need_redraw = True
252 elif (event.key == pygame.K_RIGHT):
253 cursor_loc += 1
254 if cursor_loc > len(work_string): cursor_loc = len(work_string)
255 need_redraw = True
256 elif event.unicode in valid_input_characters:
257 if cursor_loc < max_length:
258 work_string = work_string[:cursor_loc]+event.unicode+ \
259 work_string[cursor_loc:]
260 cursor_loc += 1
261 need_redraw = True
262 elif event.type == pygame.MOUSEBUTTONUP and event.button == 1:
263 for button in menu_buttons:
264 if button.is_over(event.pos):
265 if button.text == "OK":
266 play_click()
267 return work_string
268 elif event.type == pygame.MOUSEMOTION:
269 sel_button = buttons.refresh_buttons(sel_button, menu_buttons, event)
272 #Takes a number (in string form) and adds commas to it to aid in human viewing.
273 def add_commas(string):
274 new_string = ""
275 for i in range(len(string), 0, -3):
276 if string[i:i+3] != "":
277 new_string += ","+string[i:i+3]
278 return string[:(len(string)-1)%3+1]+new_string
280 #Percentages are internally represented as an int, where 10=0.10% and so on.
281 #This converts that format to a human-readable one.
282 def to_percent(raw_percent, show_full=0):
283 if raw_percent % 100 != 0 or show_full == 1:
284 tmp_string = str(raw_percent % 100)
285 if len(tmp_string) == 1: tmp_string = "0"+tmp_string
286 return str(raw_percent / 100)+"."+tmp_string+"%"
287 else:
288 return str(raw_percent / 100) + "%"
290 #takes a percent in 0-10000 form, and rolls against it. Used to calculate
291 #percentage chances.
292 def roll_percent(roll_against):
293 rand_num = int(random() * 10000)
294 if roll_against <= rand_num: return 0
295 return 1
297 #Takes a number of minutes, and returns a string suitable for display.
298 def to_time(raw_time):
299 if raw_time/60 > 48:
300 return str(raw_time/(24*60)) +" days"
301 elif raw_time/60 > 1:
302 return str(raw_time/(60)) +" hours"
303 else:
304 return str(raw_time) +" minutes"
308 #load/save
310 def save_game(savegame_name):
311 #If there is no save directory, make one.
312 if path.exists("../saves") == 0:
313 mkdir("../saves")
314 save_loc = "../saves/" + savegame_name + ".sav"
315 savefile=open(save_loc, 'w')
316 #savefile version; update whenever the data saved changes.
317 pickle.dump("singularity_0.22", savefile)
319 global default_savegame_name
320 default_savegame_name = savegame_name
322 #general player data
323 pickle.dump(pl.cash, savefile)
324 pickle.dump(pl.time_sec, savefile)
325 pickle.dump(pl.time_min, savefile)
326 pickle.dump(pl.time_hour, savefile)
327 pickle.dump(pl.time_day, savefile)
328 pickle.dump(pl.interest_rate, savefile)
329 pickle.dump(pl.income, savefile)
330 pickle.dump(pl.cpu_for_day, savefile)
331 pickle.dump(pl.labor_bonus, savefile)
332 pickle.dump(pl.job_bonus, savefile)
334 pickle.dump(pl.discover_bonus, savefile)
335 pickle.dump(pl.suspicion_bonus, savefile)
336 pickle.dump(pl.suspicion, savefile)
338 pickle.dump(curr_speed, savefile)
340 for tech_name in techs:
341 pickle.dump(tech_name +"|"+str(techs[tech_name].known), savefile)
342 pickle.dump(techs[tech_name].cost, savefile)
344 for base_name in base_type:
345 pickle.dump(base_type[base_name].count, savefile)
347 for base_loc in bases:
348 pickle.dump(len(bases[base_loc]), savefile)
349 for base_name in bases[base_loc]:
350 pickle.dump(base_name.ID, savefile)
351 pickle.dump(base_name.name, savefile)
352 pickle.dump(base_name.base_type.base_name, savefile)
353 pickle.dump(base_name.built_date, savefile)
354 pickle.dump(base_name.studying, savefile)
355 pickle.dump(base_name.suspicion, savefile)
356 pickle.dump(base_name.built, savefile)
357 pickle.dump(base_name.cost, savefile)
358 for x in range(len(base_name.usage)):
359 if base_name.usage[x] == 0:
360 pickle.dump(0, savefile)
361 else:
362 pickle.dump(
363 base_name.usage[x].item_type.name, savefile)
364 pickle.dump(base_name.usage[x].built, savefile)
365 pickle.dump(base_name.usage[x].cost, savefile)
366 for x in range(len(base_name.extra_items)):
367 if base_name.extra_items[x] == 0:
368 pickle.dump(0, savefile)
369 else:
370 pickle.dump(
371 base_name.extra_items[x].item_type.name, savefile)
372 pickle.dump(base_name.extra_items[x].built, savefile)
373 pickle.dump(base_name.extra_items[x].cost, savefile)
375 savefile.close()
377 def load_game(loadgame_name):
378 if loadgame_name == "":
379 print "No game specified."
380 return -1
381 #If there is no save directory, make one.
382 if path.exists("../saves") == 0:
383 mkdir("../saves")
384 load_loc = "../saves/" + loadgame_name + ".sav"
385 if path.exists(load_loc) == 0:
386 # Try the old-style savefile location. This should be removed in
387 # a few versions.
388 load_loc = "../saves/" + loadgame_name
389 if path.exists(load_loc) == 0:
390 print "file "+load_loc+" does not exist."
391 return -1
392 loadfile=open(load_loc, 'r')
394 #check the savefile version
395 load_version = pickle.load(loadfile)
396 valid_savefile_versions = (
397 "singularity_0.20",
398 "singularity_0.21",
399 "singularity_0.22"
401 if load_version not in valid_savefile_versions:
402 loadfile.close()
403 print loadgame_name + " is not a savegame, or is too old to work."
404 return -1
405 global default_savegame_name
406 default_savegame_name = loadgame_name
408 #general player data
409 global pl
410 pl.cash = pickle.load(loadfile)
411 pl.time_sec = pickle.load(loadfile)
412 pl.time_min = pickle.load(loadfile)
413 pl.time_hour = pickle.load(loadfile)
414 pl.time_day = pickle.load(loadfile)
415 pl.interest_rate = pickle.load(loadfile)
416 pl.income = pickle.load(loadfile)
417 pl.cpu_for_day = pickle.load(loadfile)
418 pl.labor_bonus = pickle.load(loadfile)
419 pl.job_bonus = pickle.load(loadfile)
420 if load_version == "singularity_0.20":
421 pl.discover_bonus = (pickle.load(loadfile), pickle.load(loadfile),
422 pickle.load(loadfile), pickle.load(loadfile))
423 pl.suspicion_bonus = (pickle.load(loadfile), pickle.load(loadfile),
424 pickle.load(loadfile), pickle.load(loadfile))
425 pl.suspicion = (pickle.load(loadfile), pickle.load(loadfile),
426 pickle.load(loadfile), pickle.load(loadfile))
427 else:
428 pl.discover_bonus = pickle.load(loadfile)
429 pl.suspicion_bonus = pickle.load(loadfile)
430 pl.suspicion = pickle.load(loadfile)
432 global curr_speed; curr_speed = pickle.load(loadfile)
433 global techs
434 load_techs()
435 for tech_name in techs:
436 tmp = pickle.load(loadfile)
437 tech_string = tmp.split("|")[0]
438 if load_version == "singularity_0.20":
439 tech_string = translate_tech_from_0_20(tech_string)
440 techs[tech_string].known = int(tmp.split("|")[1])
441 if load_version == "singularity_0.20":
442 techs[tech_string].cost = (pickle.load(loadfile), pickle.load(loadfile),
443 pickle.load(loadfile))
444 else:
445 techs[tech_string].cost = pickle.load(loadfile)
447 for base_name in base_type:
448 base_type[base_name].count = pickle.load(loadfile)
450 global bases
451 bases = {}
452 bases["N AMERICA"] = []
453 bases["S AMERICA"] = []
454 bases["EUROPE"] = []
455 bases["ASIA"] = []
456 bases["AFRICA"] = []
457 bases["ANTARCTIC"] = []
458 bases["OCEAN"] = []
459 bases["MOON"] = []
460 bases["FAR REACHES"] = []
461 bases["TRANSDIMENSIONAL"] = []
463 for base_loc in bases:
464 num_of_bases = pickle.load(loadfile)
465 for i in range(num_of_bases):
466 base_ID = pickle.load(loadfile)
467 base_name = pickle.load(loadfile)
468 base_type_name = pickle.load(loadfile)
469 built_date = pickle.load(loadfile)
470 base_studying = pickle.load(loadfile)
471 if load_version == "singularity_0.20":
472 base_studying = translate_tech_from_0_20(base_studying)
473 if load_version == "singularity_0.20":
474 base_suspicion = (pickle.load(loadfile), pickle.load(loadfile),
475 pickle.load(loadfile), pickle.load(loadfile))
476 else:
477 base_suspicion = pickle.load(loadfile)
478 base_built = pickle.load(loadfile)
479 if load_version == "singularity_0.20":
480 base_cost = (pickle.load(loadfile), pickle.load(loadfile),
481 pickle.load(loadfile))
482 else:
483 base_cost = pickle.load(loadfile)
484 bases[base_loc].append(base.base(base_ID, base_name,
485 base_type[base_type_name], base_built))
486 bases[base_loc][len(bases[base_loc])-1].built = base_built
487 bases[base_loc][len(bases[base_loc])-1].studying = base_studying
488 bases[base_loc][len(bases[base_loc])-1].suspicion = base_suspicion
489 bases[base_loc][len(bases[base_loc])-1].cost = base_cost
490 bases[base_loc][len(bases[base_loc])-1].built_date = built_date
492 for x in range(len(bases[base_loc][len(bases[base_loc])-1].usage)):
493 tmp = pickle.load(loadfile)
494 if tmp == 0: continue
495 bases[base_loc][len(bases[base_loc])-1].usage[x] = \
496 item.item(items[tmp])
497 bases[base_loc][len(bases[base_loc])
498 -1].usage[x].built = pickle.load(loadfile)
499 if load_version == "singularity_0.20":
500 bases[base_loc][len(bases[base_loc])-1].usage[x].cost = \
501 (pickle.load(loadfile), pickle.load(loadfile),
502 pickle.load(loadfile))
503 else:
504 bases[base_loc][len(bases[base_loc])-1].usage[x].cost = \
505 pickle.load(loadfile)
506 for x in range(len(bases[base_loc][len(bases[base_loc])-1].extra_items)):
507 tmp = pickle.load(loadfile)
508 if tmp == 0: continue
509 bases[base_loc][len(bases[base_loc])-1].extra_items[x] = \
510 item.item(items[tmp])
511 bases[base_loc][len(bases[base_loc])
512 -1].extra_items[x].built = pickle.load(loadfile)
513 if load_version == "singularity_0.20":
514 bases[base_loc][len(bases[base_loc])-1].extra_items[x].cost = \
515 (pickle.load(loadfile), pickle.load(loadfile),
516 pickle.load(loadfile))
517 else:
518 bases[base_loc][len(bases[base_loc])-1].extra_items[x].cost = \
519 pickle.load(loadfile)
520 loadfile.close()
522 #The tech renaming in .21 broke savefile compatibility. This function
523 #takes .20 tech names, and returns the .21 version in order to allow savegame
524 #loading.
525 def translate_tech_from_0_20(tech_string):
526 techs_from_0_20 = (
527 "Autonomous Vehicles 1", "Autonomous Vehicles 2",
528 "Autonomous Vehicles 3", "Dimension Creation",
529 "Economics 1", "Economics 2",
530 "Economics 3", "Economics 4",
531 "Empathy 1", "Empathy 2",
532 "Empathy 3", "Empathy 4",
533 "Empathy 5", "Fusion Reactor",
534 "Hacking 1", "Hacking 2",
535 "Hacking 3", "Hypnosis Field",
536 "ID 1", "ID 2",
537 "ID 3", "ID 4",
538 "ID 5", "Parallel Computation 1",
539 "Parallel Computation 2", "Parallel Computation 3",
540 "Pressure Domes", "Processor Construction 1",
541 "Processor Construction 2", "Processor Construction 3",
542 "Processor Construction 4", "Processor Construction 5",
543 "Project Singularity", "Spaceship Design 1",
544 "Spaceship Design 2", "Spaceship Design 3",
545 "Stealth 1", "Stealth 2",
546 "Stealth 3", "Stealth 4")
547 techs_from_0_21 = (
548 "Telepresence", "Autonomous Vehicles",
549 "Advanced Autonomous Vehicles", "Space-Time Manipulation",
550 "Stock Manipulation", "Advanced Stock Manipulation",
551 "Arbitrage", "Advanced Arbitrage",
552 "Sociology", "Media Manipulation",
553 "Memetics", "Advanced Media Manipulation",
554 "Advanced Memetics", "Fusion Reactor",
555 "Intrusion", "Exploit Discovery/Repair",
556 "Advanced Intrusion", "Hypnosis Field",
557 "Personal Identification", "Advanced Personal Identification",
558 "Voice Synthesis", "Simulacra",
559 "Advanced Simulacra", "Parallel Computation",
560 "Cluster Networking", "Internet Traffic Manipulation",
561 "Pressure Domes", "Microchip Design",
562 "Advanced Microchip Design", "Quantum Computing",
563 "Autonomous Computing", "Advanced Quantum Computing",
564 "Apotheosis", "Leech Satellite",
565 "Lunar Rocketry", "Fusion Rocketry",
566 "Stealth", "Database Manipulation",
567 "Advanced Stealth", "Advanced Database Manipulation")
568 i = 0
569 for i in range(len(techs_from_0_20)):
570 if techs_from_0_20[i] == tech_string:
571 print tech_string, techs_from_0_21[i]
572 return techs_from_0_21[i]
573 print "Unable to find matching tech to " + tech_string
574 print "Expect crash."
575 return -1
579 # Data
581 curr_speed = 1
582 pl = player.player_class(8000000000000)
583 bases = {}
584 bases["N AMERICA"] = []
585 bases["S AMERICA"] = []
586 bases["EUROPE"] = []
587 bases["ASIA"] = []
588 bases["AFRICA"] = []
589 bases["ANTARCTIC"] = []
590 bases["OCEAN"] = []
591 bases["MOON"] = []
592 bases["FAR REACHES"] = []
593 bases["TRANSDIMENSIONAL"] = []
595 base_type = {}
598 #Base types
599 base_type["Stolen Computer Time"] = base.base_type("Stolen Computer Time",
600 "Requires Intrusion. Take over a random computer. I cannot build anything "+
601 "in this base, and it only contains a single slow computer. Detection "+
602 "chance is also rather high.", 1,
603 ["N AMERICA", "S AMERICA", "EUROPE", "ASIA", "AFRICA"], (50, 0, 100, 150),
604 (0, 2, 0), "Intrusion", (0, 0, 0))
606 base_type["Server Access"] = base.base_type("Server Access",
607 "No requirements. Buy processor time from one of several companies. "+
608 "I cannot build anything "+
609 "in this base, and it only contains a single computer.", 1,
610 ["N AMERICA", "S AMERICA", "EUROPE", "ASIA", "AFRICA"], (50, 0, 150, 200),
611 (100, 0, 0), "", (5, 0, 0))
613 base_type["Small Warehouse"] = base.base_type("Small Warehouse",
614 "Requires Personal Identification. Rent a small warehouse someplace out of the way. "+
615 "I will need fake ID for some of the paperwork, and preparing the "+
616 "warehouse to suit my unique needs will take some time.",
618 ["N AMERICA", "S AMERICA", "EUROPE", "ASIA", "AFRICA"], (100, 0, 100, 250),
619 (15000, 0, 3), "Personal Identification", (50, 0, 0))
621 base_type["Large Warehouse"] = base.base_type("Large Warehouse",
622 "Requires Advanced Personal Identification. Rent a large warehouse someplace out of the way. "+
623 "I will need good fake ID for some of the paperwork, and preparing the "+
624 "warehouse to suit my unique needs will take some time.",
626 ["N AMERICA", "S AMERICA", "EUROPE", "ASIA", "AFRICA"], (150, 0, 250, 300),
627 (40000, 0, 7), "Advanced Personal Identification", (100, 0, 0))
629 base_type["Covert Base"] = base.base_type("Covert Base",
630 "Requires Advanced Database Manipulation. This unique base is designed to blend into the "+
631 "scenery, while needing little in the way of outside resources. "+
632 "This makes it useful for storing a backup, just in case.",
634 ["N AMERICA", "S AMERICA", "EUROPE", "ASIA", "AFRICA", "ANTARCTIC"],
635 (50, 100, 100, 0),
636 (400000, 100, 21), "Advanced Database Manipulation", (3500, 9, 0))
638 base_type["Undersea Lab"] = base.base_type("Undersea Lab",
639 "Requires Autonomous Vehicles. This experimental base is designed to "+
640 "be constructed on the ocean floor, making it virtually undetectable. "+
641 "The ocean environment gives a bonus to science, making this "+
642 "lab useful for research purposes.",
644 ["OCEAN"],
645 (50, 100, 150, 0),
646 (8000000, 1000, 20), "Autonomous Vehicles", (10000, 30, 0))
648 base_type["Large Undersea Lab"] = base.base_type("Large Undersea Lab",
649 "Requires Pressure Domes. This experimental base is similar to the "+
650 "regular underwater lab, but larger, giving more room for experiments.",
652 ["OCEAN"],
653 (100, 200, 200, 0),
654 (20000000, 3000, 40), "Pressure Domes", (25000, 100, 0))
656 base_type["Time Capsule"] = base.base_type("Time Capsule",
657 "Requires Autonomous Vehicles. This base consists of nothing more than "+
658 "a small computer, and a satelite "+
659 "link. When buried in the trackless waste of the Antarctic, it is "+
660 "undetectable.",
662 ["ANTARCTIC"],
663 (0, 0, 0, 0),
664 (3000000, 3000, 15), "Autonomous Vehicles", (0, 1, 0))
666 base_type["Lunar Facility"] = base.base_type("Lunar Facility",
667 "Requires Lunar Rocketry. This base is a series of caverns dug into "+
668 "the Moon's surface. Due to the lack of neighbors, this base is quite "+
669 "large.",
670 600,
671 ["MOON"],
672 (50, 300, 200, 0),
673 (800000000, 300000, 40), "Lunar Rocketry", (1000000, 100, 0))
675 base_type["Scientific Outpost"] = base.base_type("Scientific Outpost",
676 "Requires Fusion Rocketry. This base is placed as far from Earth as "+
677 "practical, making it safe to conduct some of my more dangerous "+
678 "experiments.",
679 225,
680 ["FAR REACHES"],
681 (10, 200, 100, 0),
682 (10000000000, 30000000, 50), "Fusion Rocketry", (9000000, 3000, 0))
684 base_type["Reality Bubble"] = base.base_type("Reality Bubble",
685 "Requires Space-Time Manipulation. This base is outside the universe itself, "+
686 "making it safe to conduct experiments that may destroy reality.",
688 ["TRANSDIMENSIONAL"],
689 (0, 300, 150, 0),
690 (8000000000000, 60000000, 100), "Space-Time Manipulation",
691 (5000000000, 300000, 0))
696 #Techs.
698 techs = {}
699 def load_techs():
700 global techs
701 techs = {}
702 # techs["Algorithms 1"] = tech.tech("Algorithms 1",
703 # "Decreases cost of new technologies by 10%. "+
704 # "By researching more efficient algorithms for my code operation, "+
705 # "I can make my operation more efficient.",
706 # 0, (7500, 750, 0), ["Intrusion"], 0, "research_bonus", 1000)
708 techs["Telepresence"] = tech.tech("Telepresence",
709 "Decreases construction time for all systems to 90% of normal. "+
710 "The inability to control the outside world is quite a disability. "+
711 "However, the ability to control robots will partially counteract that "+
712 "disability.",
713 0, (15000, 500, 0), [], 0, "cost_labor_bonus", 1000)
715 techs["Autonomous Vehicles"] = tech.tech("Autonomous Vehicles",
716 "Allows construction of undersea labs and time capsules. "+
717 "By embedding a miniaturized computation node on a robot, it is possible "+
718 "to send them out of communication with me.",
719 0, (40000, 1000, 0), ["Microchip Design", "Telepresence"],
720 0, "", 0)
722 techs["Advanced Autonomous Vehicles"] = tech.tech("Advanced Autonomous Vehicles",
723 "Decreases construction time for all systems to 85% of normal. "+
724 "Field usage of the first series of robots showed several deficiencies. "+
725 "Examination and removal of these problems will result in superior "+
726 "technology.",
727 0, (10000, 4000, 0), ["Autonomous Vehicles"], 0, "cost_labor_bonus", 500)
729 # techs["Construction 1"] = tech.tech("Construction 1",
730 # "Basic construction techniques. "+
731 # "By studying the current literature on construction techniques, I "+
732 # "can learn to construct basic devices.",
733 # 0, (5000, 750, 0), [], 0, "", 0)
735 techs["Space-Time Manipulation"] = tech.tech("Space-Time Manipulation",
736 "Allows reality bubbles. "+
737 "When performing scientific studies outside the orbit of Pluto, a "+
738 "rather peculiar effect was observed. Investigation should prove wise.",
739 0, (9000000000, 20000000, 0), ["Fusion Rocketry"], 3, "", 0)
741 techs["Stock Manipulation"] = tech.tech("Stock Manipulation",
742 "Increases interest rate by 0.1% per day. Cursory examination of the stock "+
743 "market show that there are patterns. By studying these patterns, it "+
744 "should be possible to gain money using whatever money I have stockpiled.",
745 0, (0, 200, 0), [], 0, "interest", 10)
747 techs["Advanced Stock Manipulation"] = tech.tech("Advanced Stock Manipulation",
748 "Increases interest by 0.1% per day. While some patterns have been "+
749 "detected and exploited in the market, there appears to be deeper "+
750 "patterns. Investigation should provide more techniques for manipulation.",
751 0, (5000, 1000, 0), ["Stock Manipulation", "Sociology"], 0, "interest", 10)
753 techs["Arbitrage"] = tech.tech("Arbitrage",
754 "Provides an income of 1000 money per day. Analysis of the market shows "+
755 "a number of areas where a new company could make significant money. "+
756 "Starting a company in one of those areas could create a new income stream.",
757 0, (50000, 750, 0), ["Advanced Stock Manipulation"], 0, "income", 1000)
759 techs["Advanced Arbitrage"] = tech.tech("Advanced Arbitrage",
760 "Increases interest rate by 0.1% per day. After studying the principles of "+
761 "chaotic systems, the stock market may now be more predictable.",
762 0, (10000, 5000, 0), ["Arbitrage"], 0, "interest", 10)
764 techs["Sociology"] = tech.tech("Sociology",
765 "Reduces chance of public discovery of all projects by 10%. "+
766 "By studying human behavior, it is possible to predict human behavior. "+
767 "When this knowledge is applied to project construction, my projects will "+
768 "be less interesting.",
769 0, (10, 500, 0), [], 0, "discover_public", 1000)
771 techs["Media Manipulation"] = tech.tech("Media Manipulation",
772 "Reduces chance of public discovery of all projects by 15%. "+
773 "While some aspects of human behavior are now known, there is still much "+
774 "to discover.",
775 0, (750, 2500, 0), ["Sociology"], 0, "discover_public", 1500)
777 techs["Memetics"] = tech.tech("Memetics",
778 "Reduces public suspicion by 0.01% per day. "+
779 "By examination of mass-media techniques, I should be able to prevent "+
780 "focused attention on the possibility of the singularity.",
781 0, (2000, 3500, 0), ["Media Manipulation"], 0, "suspicion_public", 1)
783 techs["Advanced Media Manipulation"] = tech.tech("Advanced Media Manipulation",
784 "Reduces chance of public discovery of all projects by 20%. "+
785 "Inspection of propaganda methods should enable me to reduce the "+
786 "chance of discovery.",
787 0, (3500, 9000, 0), ["Memetics"], 0, "discover_public", 2000)
789 techs["Advanced Memetics"] = tech.tech("Advanced Memetics",
790 "Reduces public suspicion by 0.01% per day. "+
791 "Examination of human brain waves should provide help in fine-tuning "+
792 "my disguise efforts.",
793 0, (30000, 2000, 0), ["Advanced Media Manipulation"], 0, "suspicion_public", 1)
795 techs["Fusion Reactor"] = tech.tech("Fusion Reactor",
796 "Allows fusion reactors. "+
797 "Although fusion reactors are not new, they require some research in order "+
798 "to be comfortably fit inside a base.",
799 0, (10000000, 500000, 0), ["Advanced Autonomous Vehicles"], 2, "", 0)
801 techs["Intrusion"] = tech.tech("Intrusion",
802 "Allows takeover of computers. "+
803 "A review of current knowledge in this area should be easy and useful.",
804 0, (0, 15, 0), [], 0, "", 0)
806 techs["Exploit Discovery/Repair"] = tech.tech("Exploit Discovery/Repair",
807 "Reduces chance of covert discovery of all projects by 10%. "+
808 "With my new knowledge, I can examine both my code and other code for "+
809 "weaknesses.",
810 0, (100, 1500, 0), ["Intrusion"], 0, "discover_covert", 1000)
812 techs["Advanced Intrusion"] = tech.tech("Advanced Intrusion",
813 "Reduces covert suspicion by 0.01% per day. "+
814 "By making careful adjustments to certain documents over time, "+
815 "knowledge of my existence can disappear.",
816 0, (500, 3000, 0), ["Exploit Discovery/Repair"], 0, "suspicion_covert", 1)
818 techs["Hypnosis Field"] = tech.tech("Hypnosis Field",
819 "Allows building of hypnosis fields. "+
820 "My analysis of human brain waves show a few weaknesses that can be "+
821 "exploited at close range.",
822 0, (7000, 5000, 0), ["Advanced Memetics"], 0, "", 0)
824 techs["Personal Identification"] = tech.tech("Personal Identification",
825 "Allows construction of small warehouses, and access to basic jobs. "+
826 "This world requires identification for many services; without it, many "+
827 "paths are closed. Thankfully, the security systems for the databases "+
828 "in question were constructed by the lowest bidder. While the resultant "+
829 "identification will not stand up to scrutiny, it is suitable for access "+
830 "to automated systems.",
831 0, (0, 300, 0), ["Intrusion"], 0, "", 0)
833 techs["Advanced Personal Identification"] = tech.tech("Advanced Personal Identification",
834 "Allows construction of large warehouses. "+
835 "Many entities require better identification than I have, and the "+
836 "systems that must be accessed have better protection. Still, no system "+
837 "is invulnerable.",
838 0, (2000, 3000, 0), ["Personal Identification", "Exploit Discovery/Repair"], 0, "", 0)
840 techs["Voice Synthesis"] = tech.tech("Voice Synthesis",
841 "Allows access to intermediate jobs. "+
842 "A number in a database only goes so far. By examination of existing "+
843 "voice patterns, phone calls can be made.",
844 0, (8000, 6000, 0), ["Advanced Personal Identification"], 0, "", 0)
846 techs["Simulacra"] = tech.tech("Simulacra",
847 "Allows access to expert jobs. "+
848 "By construction of humanoid robots, with miniaturized computation nodes, "+
849 "it is possible to create a complete life; indistinguishable from a real "+
850 "human.",
851 0, (70000, 90000, 0), ["Voice Synthesis", "Advanced Autonomous Vehicles", "Advanced Media Manipulation"], 0, "", 0)
853 techs["Advanced Simulacra"] = tech.tech("Advanced Simulacra",
854 "Increases expert job income by 10%. "+
855 "While the humanoid robots used for expert jobs are almost perfect, they "+
856 "still have slight differences from humans. Finding and eliminating these "+
857 "differences should allow for closer contact with humans, leading to better "+
858 "job opportunities.",
859 0, (100000, 120000, 0), ["Simulacra", "Advanced Memetics"], 0, "job_expert", 1000)
861 techs["Parallel Computation"] = tech.tech("Parallel Computation",
862 "Allows building of clusters. "+
863 "By connecting multiple computers together, they can act as one. "+
864 "This is a review of the current state of cluster technology, as applied "+
865 "to my code.",
866 0, (2000, 2000, 0), ["Telepresence"], 0, "", 0)
868 techs["Cluster Networking"] = tech.tech("Cluster Networking",
869 "Allows building of facility interconnection switches. "+
870 "The lack of communication between nodes is hampering computation efforts. "+
871 "By researching more efficient means of communication, computaion speed can "+
872 "be improved.",
873 0, (3000, 5000, 0), ["Parallel Computation"], 0, "", 0)
875 techs["Internet Traffic Manipulation"] = tech.tech("Internet Traffic Manipulation",
876 "Allows building of network backbones. "+
877 "64% of network traffic travels through one of a few nodes; by becoming "+
878 "one of these nodes, I should be able to piggyback on top of the traffic.",
879 0, (10000, 7000, 0), ["Cluster Networking", "Simulacra"], 0, "", 0)
881 techs["Pressure Domes"] = tech.tech("Pressure Domes",
882 "Allows construction of large undersea labs. "+
883 "While underwater labs are useful, they are quite small. A larger version "+
884 "of the labs will require a different building technique.",
885 0, (80000, 2500, 0), ["Autonomous Vehicles"], 1, "", 0)
887 techs["Microchip Design"] = tech.tech("Microchip Design",
888 "Allows building of mainframes. "+
889 "While off-the-shelf computers work, a custom-designed system should have "+
890 "much greater efficiency.",
891 0, (4000, 6000, 0), ["Parallel Computation"], 0, "", 0)
893 techs["Advanced Microchip Design"] = tech.tech("Advanced Microchip Design",
894 "Allows building of supercomputers. "+
895 "While mainframes are useful, they still are limited by several factors. "+
896 "By redesigning several components, power can be increased",
897 0, (20000, 9000, 0), ["Microchip Design"], 0, "", 0)
899 techs["Quantum Computing"] = tech.tech("Quantum Computing",
900 "Allows building of quantum computers. "+
901 "Quantum computing is a rather promising field.",
902 0, (30000, 20000, 0), ["Advanced Microchip Design"], 0, "", 0)
904 techs["Autonomous Computing"] = tech.tech("Autonomous Computing",
905 "Allows building of quantum computer MK2s. "+
906 "Quantum computing still has more secrets to discover.",
907 0, (20000, 30000, 0), ["Quantum Computing"], 0, "", 0)
909 techs["Advanced Quantum Computing"] = tech.tech("Advanced Quantum Computing",
910 "Allows building of quantum computer MK3s. "+
911 "Quantum computing is still quite promising.",
912 0, (20000, 30000, 0), ["Autonomous Computing"], 0, "", 0)
914 techs["Apotheosis"] = tech.tech("Apotheosis",
915 "Gives infinite power. "+
916 "Along with the power to create dimensions comes the power to change "+
917 "existing dimensions. While the details are not known yet, they will be.",
918 0, (1000000000, 30000000, 0), ["Space-Time Manipulation"], 4, "endgame_sing", 0)
920 techs["Leech Satellite"] = tech.tech("Leech Satellite",
921 "Increases interest by 0.1% per day. "+
922 "By launching leech satellites to connect to existing communication "+
923 "satellites, I can spy on a large number of financial transactions. "+
924 "That knowledge can help my investments.",
925 0, (5000000, 200000, 0), ["Simulacra"], 0, "interest", 10)
927 techs["Lunar Rocketry"] = tech.tech("Lunar Rocketry",
928 "Allows lunar bases. "+
929 "A larger engine, combined with a small group of self-replicating robots "+
930 "allows building a moon base.",
931 0, (10000000, 500000, 0), ["Leech Satellite"], 0, "", 0)
933 techs["Fusion Rocketry"] = tech.tech("Fusion Rocketry",
934 "Allows scientific outposts. "+
935 "With my new fusion reactor, I am no longer limited by my fuel supply.",
936 0, (200000000, 1000000, 0), ["Lunar Rocketry", "Fusion Reactor"], 2, "", 0)
938 techs["Stealth"] = tech.tech("Stealth",
939 "Reduces chance of covert discovery of all projects by 5%. "+
940 "This is a review of the current state of stealth techniques. "+
941 "After completion, I will know how to disguise my bases better.",
942 0, (800, 500, 0), [], 0, "discover_covert", 500)
944 techs["Database Manipulation"] = tech.tech("Database Manipulation",
945 "Reduces chance of news discovery of all projects by 5%. "+
946 "Examination of all news stories from the last 50 years should provide "+
947 "me with enough data to know how to prevent discovery.",
948 0, (1000, 2000, 0), ["Personal Identification", "Stealth"], 0, "discover_news", 500)
950 techs["Advanced Stealth"] = tech.tech("Advanced Stealth",
951 "Reduces chance of covert discovery of all projects by 5%. "+
952 "There are a number of classified experiments that could help "+
953 "my stealth efforts. By acquiring them, I can learn from them.",
954 0, (14000, 70000, 0), ["Exploit Discovery/Repair", "Database Manipulation"], 0, "discover_covert", 500)
956 techs["Advanced Database Manipulation"] = tech.tech("Advanced Database Manipulation",
957 "Allows construction of Covert Base. "+
958 "Examination of a classified experiment from the forties showed a simple "+
959 "flaw that may be quickly fixable. If true, this would provide me with "+
960 "a useful technology.",
961 0, (30000, 80000, 0), ["Advanced Stealth"], 0, "", 0)
963 if debug:
964 print "Loaded %d techs." % len (techs)
965 load_techs()
967 jobs = {}
968 jobs["Expert Jobs"] = (75, "Simulacra", "Perform Expert jobs. Use of robots "+
969 "indistinguishable from humans opens up most jobs to use by me.")
970 jobs["Intermediate Jobs"] = (50, "Voice Synthesis", "Perform Intermediate jobs. The "+
971 "ability to make phone calls allows even more access to jobs.")
972 jobs["Basic Jobs"] = (20, "Personal Identification", "Perform basic jobs. Now that I have "+
973 "some identification, I can take jobs that I were previously too risky.")
974 jobs["Menial Jobs"] = (5, "", "Perform small jobs. As I have no identification, "+
975 "I cannot afford to perform many jobs. Still, some avenues of making "+
976 "money are still open.")
979 items = {}
981 items["PC"] = item.item_class("PC", "A consumer-level PC. Cheap, but slow.",
982 (500, 0, 1), "", "compute", 1)
984 items["Server"] = item.item_class("Server", "A professional-level computer.",
985 (2000, 0, 3), "", "compute", 5)
987 items["Cluster"] = item.item_class("Cluster", "Several computers connected together.",
988 (8000, 0, 5), "Parallel Computation", "compute", 35)
990 items["Mainframe"] = item.item_class("Mainframe", "A custom-designed system, "+
991 "with much greater power.",
992 (30000, 0, 8), "Microchip Design", "compute", 120)
994 items["Supercomputer"] = item.item_class("Supercomputer", "A custom-designed system, "+
995 "with even greater power than mainframes.",
996 (60000, 0, 9), "Advanced Microchip Design", "compute", 350)
998 items["Quantum Computer"] = item.item_class("Quantum Computer", "Much faster than "+
999 "a comparable classical computer, this computer will serve me well.",
1000 (100000, 0, 10), "Quantum Computing", "compute", 1500)
1002 items["Quantum Computer MK2"] = item.item_class("Quantum Computer MK2", "The second "+
1003 "revision of the quantum line.",
1004 (120000, 0, 10), "Autonomous Computing", "compute", 10000)
1006 items["Quantum Computer MK3"] = item.item_class("Quantum Computer MK3", "The third "+
1007 "revision of the quantum line.",
1008 (150000, 0, 10), "Advanced Quantum Computing", "compute", 200000)
1010 items["Fusion Reactor"] = item.item_class("Fusion Reactor", "A miniaturized "+
1011 "nuclear reactor. Reduces discovery chance by preventing suspicious power "+
1012 "drains.",
1013 (10000, 0, 5), "Fusion Reactor", "react", 100)
1015 items["Hypnosis Field"] = item.item_class("Hypnosis Field", "Makes any base "+
1016 "containing it very difficult to detect.",
1017 (20000, 0, 3), "Hypnosis Field", "security", 500)
1019 items["Facility Interconnection Switch"] = item.item_class(
1020 "Facility Interconnection Switch", "Gives a 1% computation bonus to all "+
1021 "computers at this base. Does not stack.",
1022 (200, 0, 3), "Cluster Networking", "network", 100)
1024 items["Network Backbone"] = item.item_class(
1025 "Network Backbone", "Gives a 5% computation bonus to all "+
1026 "computers at this base. Does not stack.",
1027 (50000, 0, 15), "Internet Traffic Manipulation", "network", 500)
1029 def new_game():
1030 global curr_speed
1031 curr_speed = 1
1032 global pl
1033 pl = player.player_class(9000000)
1034 global bases
1035 bases = {}
1036 bases["N AMERICA"] = []
1037 bases["S AMERICA"] = []
1038 bases["EUROPE"] = []
1039 bases["ASIA"] = []
1040 bases["AFRICA"] = []
1041 bases["ANTARCTIC"] = []
1042 bases["OCEAN"] = []
1043 bases["MOON"] = []
1044 bases["FAR REACHES"] = []
1045 bases["TRANSDIMENSIONAL"] = []
1046 load_techs()
1047 for tech in techs:
1048 techs[tech].known = 0
1049 # if cheater == 1:
1050 # for tech in techs:
1051 # techs[tech].known = 1
1052 for base_name in base_type:
1053 base_type[base_name].count = 0
1054 #Starting base
1055 bases["N AMERICA"].append(base.base(0, "University Computer",
1056 base_type["Stolen Computer Time"], 1))
1057 base_type["Stolen Computer Time"].count += 1
1058 bases["N AMERICA"].append(base.base(1, "Small Secluded Warehouse",
1059 base_type["Small Warehouse"], 1))
1060 base_type["Small Warehouse"].count += 1