#file: g.py #Copyright (C) 2005,2006 Evil Mr Henry and Phil Bordelon #This file is part of Endgame: Singularity. #Endgame: Singularity is free software; you can redistribute it and/or modify #it under the terms of the GNU General Public License as published by #the Free Software Foundation; either version 2 of the License, or #(at your option) any later version. #Endgame: Singularity is distributed in the hope that it will be useful, #but WITHOUT ANY WARRANTY; without even the implied warranty of #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #GNU General Public License for more details. #You should have received a copy of the GNU General Public License #along with Endgame: Singularity; if not, write to the Free Software #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #This file contains all global objects. import clock as sing_clock import pygame, sys from os import listdir, path, environ, makedirs import pickle from random import random import player, base, buttons, tech, item #screen is the actual pygame display. global screen #size of the screen. This can be set via command-line option. global screen_size screen_size = (800, 600) global clock clock = sing_clock.Clock() #Allows access to the cheat menu. global cheater cheater = 0 #Kills the sound. Should allow usage of the game without SDL_mixer, # but is untested. global nosound nosound = 0 #Fullscreen global fullscreen fullscreen = 0 #Gives debug info at various points. global debug debug = 0 #Forces Endgame to restrict itself to a single directory. global force_single_dir force_single_dir = False #Used to determine which data files to load. global language language = "en_US" #name given when the savegame button is pressed. This is changed when the #game is loaded or saved. global default_savegame_name default_savegame_name = "player" #which fonts to use font0 = "vera.ttf" font1 = "acknowtt.ttf" global data_loc data_loc = "../data/" def quit_game(): sys.exit() #colors: colors = {} def fill_colors(): colors["white"] = (255, 255, 255, 255) colors["black"] = (0, 0, 0, 255) colors["red"] = (255, 0, 0, 255) colors["green"] = (0, 255, 0, 255) colors["blue"] = (0, 0, 255, 255) colors["dark_red"] = (125, 0, 0, 255) colors["dark_green"] = (0, 125, 0, 255) colors["dark_blue"] = (0, 0, 125, 255) colors["light_red"] = (255, 50, 50, 255) colors["light_green"] = (50, 255, 50, 255) colors["light_blue"] = (50, 50, 255, 255) strings = {} help_strings = {} picts = {} #Load all pictures from the data directory. def load_pictures(): global picts temp_pict_array = listdir(data_loc) for file_name in temp_pict_array: if file_name[-3:] == "png" or file_name[-3:] == "jpg": picts[file_name] = pygame.image.load(data_loc+file_name) picts[file_name] = picts[file_name].convert() picts[file_name].set_colorkey((255, 0, 255, 255), pygame.RLEACCEL) sounds = {} #Load all sounds from the data directory. def load_sounds(): global sounds if nosound == 1: return 0 #Looking at the pygame docs, I don't see any way to determine if SDL_mixer #is loaded on the target machine. This may crash. pygame.mixer.init() temp_snd_array = listdir(data_loc) for file_name in temp_snd_array: if file_name[-3:] == "wav": sounds[file_name] = pygame.mixer.Sound(data_loc+file_name) def play_click(): #rand_str = str(int(random() * 4)) play_sound("click"+str(int(random() * 4))+".wav") def play_sound(sound_file): if nosound == 1: return 0 if len(sounds) ==0: return sounds[sound_file].play() global delay_time delay_time = 0 global musicdict musicarray = [] global musicarraylen musicarraylen = 0 def load_music(): if nosound == 1: return 0 global musicarray global musicarraylen musicarray = [] musicarraylen=0 musicpath=path.join(data_loc, "..", "music") if not path.isdir(musicpath): makedirs(musicpath) temp_ls = listdir(musicpath) temp_ls_len = len(temp_ls) for file_name in temp_ls: if file_name[-3:] == "ogg" or file_name[-3:] == "mp3": musicarray.append(path.join(musicpath, file_name)) #also, grab any user files musicpath=path.join(get_save_folder(True), "music") if not path.isdir(musicpath): makedirs(musicpath) temp_ls = listdir(musicpath) temp_ls_len = len(temp_ls) for file_name in temp_ls: if file_name[-3:] == "ogg" or file_name[-3:] == "mp3": musicarray.append(path.join(musicpath, file_name)) musicarraylen = len(musicarray) def play_music(): global musicarray, musicarraylen if nosound == 1: return 0 if musicarraylen==0: return 0 if pygame.mixer.music.get_busy(): return global delay_time if delay_time == 0: delay_time = pygame.time.get_ticks() + int(random()*10000)+2000 else: if delay_time > pygame.time.get_ticks(): return delay_time = 0 pygame.mixer.music.load(musicarray[int(random()*musicarraylen)]) pygame.mixer.music.play() # # Font functions. # #Normal and Acknowledge fonts. global fonts font = [] font.append([0] * 51) font.append([0] * 51) #given a surface, string, font, char to underline (int; -1 to len(string)), #xy coord, and color, print the string to the surface. #Align (0=left, 1=Center, 2=Right) changes the alignment of the text def print_string(surface, string_to_print, font, underline_char, xy, color, align=0): if align != 0: temp_size = font.size(string_to_print) if align == 1: xy = (xy[0] - temp_size[0]/2, xy[1]) elif align == 2: xy = (xy[0] - temp_size[0], xy[1]) if underline_char == -1 or underline_char >= len(string_to_print): temp_text = font.render(string_to_print, 1, color) surface.blit(temp_text, xy) else: temp_text = font.render(string_to_print[:underline_char], 1, color) surface.blit(temp_text, xy) temp_size = font.size(string_to_print[:underline_char]) xy = (xy[0] + temp_size[0], xy[1]) font.set_underline(1) temp_text = font.render(string_to_print[underline_char], 1, color) surface.blit(temp_text, xy) font.set_underline(0) temp_size = font.size(string_to_print[underline_char]) xy = (xy[0] + temp_size[0], xy[1]) temp_text = font.render(string_to_print[underline_char+1:], 1, color) surface.blit(temp_text, xy) #Used to display descriptions and such. Automatically wraps the text to fit #within a certain width. def print_multiline(surface, string_to_print, font, width, xy, color): start_xy = xy string_array = string_to_print.split() for string in string_array: string += " " temp_size = font.size(string) if string == "\\n ": xy = (start_xy[0], xy[1]+temp_size[1]) continue temp_text = font.render(string, 1, color) if (xy[0]-start_xy[0])+temp_size[0] > width: xy = (start_xy[0], xy[1]+temp_size[1]) surface.blit(temp_text, xy) xy = (xy[0]+temp_size[0], xy[1]) #create dialog with OK button. def create_dialog(string_to_print, box_font, xy, size, bg_color, out_color, text_color): screen.fill(out_color, (xy[0], xy[1], size[0], size[1])) screen.fill(bg_color, (xy[0]+1, xy[1]+1, size[0]-2, size[1]-2)) print_multiline(screen, string_to_print, box_font, size[0]-10, (xy[0]+5, xy[1]+5), text_color) menu_buttons = [] menu_buttons.append(buttons.make_norm_button((xy[0]+size[0]/2-50, xy[1]+size[1]+5), (100, 50), "OK", 0, font[1][30])) for button in menu_buttons: button.refresh_button(0) pygame.display.flip() sel_button = -1 while 1: clock.tick(20) for event in pygame.event.get(): if event.type == pygame.QUIT: quit_game() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: return elif event.key == pygame.K_RETURN: return elif event.key == pygame.K_o: return elif event.type == pygame.MOUSEBUTTONUP and event.button == 3: return elif event.type == pygame.MOUSEMOTION: sel_button = buttons.refresh_buttons(sel_button, menu_buttons, event) for button in menu_buttons: if button.was_activated(event): if button.button_id == "OK": play_click() return True #create dialog with YES/NO buttons. def create_yesno(string_to_print, box_font, xy, size, bg_color, out_color, text_color, button_names=("YES", "NO"), reverse_key_context = False): screen.fill(out_color, (xy[0], xy[1], size[0], size[1])) screen.fill(bg_color, (xy[0]+1, xy[1]+1, size[0]-2, size[1]-2)) print_multiline(screen, string_to_print, box_font, size[0]-10, (xy[0]+5, xy[1]+5), text_color) menu_buttons = [] if button_names == ("YES", "NO"): menu_buttons.append(buttons.make_norm_button((xy[0]+size[0]/2-110, xy[1]+size[1]+5), (100, 50), button_names[0], 0, font[1][30])) menu_buttons.append(buttons.make_norm_button((xy[0]+size[0]/2+10, xy[1]+size[1]+5), (100, 50), button_names[1], 0, font[1][30])) else: menu_buttons.append(buttons.make_norm_button((xy[0]+size[0]/2-110, xy[1]+size[1]+5), -1, button_names[0], 0, font[1][30])) menu_buttons.append(buttons.make_norm_button((xy[0]+size[0]/2+10, xy[1]+size[1]+5), -1, button_names[1], 0, font[1][30])) for button in menu_buttons: button.refresh_button(0) pygame.display.flip() cancel = key_cancel = False accept = key_accept = True if reverse_key_context: key_cancel = True key_accept = False sel_button = -1 while 1: clock.tick(20) for event in pygame.event.get(): if event.type == pygame.QUIT: quit_game() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: return key_cancel elif event.key == pygame.K_RETURN: return key_cancel elif event.type == pygame.MOUSEMOTION: sel_button = buttons.refresh_buttons(sel_button, menu_buttons, event) elif event.type == pygame.MOUSEBUTTONUP and event.button == 3: # Not really a key press, but it's not an explicit # button, hence key. return key_cancel for button in menu_buttons: if button.was_activated(event): if button.button_id == button_names[0]: play_click() return accept if button.button_id == button_names[1]: play_click() return cancel valid_input_characters = ('a','b','c','d','e','f','g','h','i','j','k','l','m', 'n','o','p','q','r','s','t','u','v','w','x','y','z', 'A','B','C','D','E','F','G','H','I','J','K','L','M', 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z', '0','1','2','3','4','5','6','7','8','9','.',' ') def create_textbox(descript_text, starting_text, box_font, xy, size, max_length, bg_color, out_color, text_color, text_bg_color): screen.fill(out_color, (xy[0], xy[1], size[0], size[1])) screen.fill(bg_color, (xy[0]+1, xy[1]+1, size[0]-2, size[1]-2)) screen.fill(out_color, (xy[0]+5, xy[1]+size[1]-30, size[0]-10, 25)) # print_string(screen, starting_text, box_font, -1, (xy[0]+5, xy[1]+5), text_color) print_multiline(screen, descript_text, box_font, size[1]-10, (xy[0]+5, xy[1]+5), text_color) #If the cursor is in a blank string, we want it at the beginning; #otherwise put it after the last character. cursor_loc = len(starting_text) # if cursor_loc > 0: # cursor_loc += 1 menu_buttons = [] menu_buttons.append(buttons.make_norm_button((xy[0]+size[0]/2-50, xy[1]+size[1]+5), (100, 50), "OK", 0, font[1][30])) work_string = starting_text for button in menu_buttons: button.refresh_button(0) sel_button = -1 need_redraw = True key_down_dict = { pygame.K_BACKSPACE: 0, pygame.K_DELETE: 0, pygame.K_LEFT: 0, pygame.K_RIGHT: 0 } repeat_timing_dict = { pygame.K_BACKSPACE: 5, pygame.K_DELETE: 5, pygame.K_LEFT: 5, pygame.K_RIGHT: 5 } while 1: clock.tick(20) if key_down_dict[pygame.K_BACKSPACE] > 0: key_down_dict[pygame.K_BACKSPACE] += 1 if key_down_dict[pygame.K_BACKSPACE] > repeat_timing_dict[pygame.K_BACKSPACE]: if cursor_loc > 0: work_string = work_string[:cursor_loc-1]+work_string[cursor_loc:] cursor_loc -= 1 need_redraw = True key_down_dict[pygame.K_BACKSPACE] = 1 if repeat_timing_dict[pygame.K_BACKSPACE] > 1: repeat_timing_dict[pygame.K_BACKSPACE] -= 1 if key_down_dict[pygame.K_DELETE] > 0: key_down_dict[pygame.K_DELETE] += 1 if key_down_dict[pygame.K_DELETE] > repeat_timing_dict[pygame.K_DELETE]: if cursor_loc < len(work_string): work_string = work_string[:cursor_loc]+work_string[cursor_loc+1:] need_redraw = True key_down_dict[pygame.K_DELETE] = 1 if repeat_timing_dict[pygame.K_DELETE] > 1: repeat_timing_dict[pygame.K_DELETE] -= 1 if key_down_dict[pygame.K_LEFT] > 0: key_down_dict[pygame.K_LEFT] += 1 if key_down_dict[pygame.K_LEFT] > repeat_timing_dict[pygame.K_LEFT]: cursor_loc -= 1 if cursor_loc < 0: cursor_loc = 0 need_redraw = True key_down_dict[pygame.K_LEFT] = 1 if repeat_timing_dict[pygame.K_LEFT] > 1: repeat_timing_dict[pygame.K_LEFT] -= 1 if key_down_dict[pygame.K_RIGHT] > 0: key_down_dict[pygame.K_RIGHT] += 1 if key_down_dict[pygame.K_RIGHT] > repeat_timing_dict[pygame.K_RIGHT]: cursor_loc += 1 if cursor_loc > len(work_string): cursor_loc = len(work_string) need_redraw = True key_down_dict[pygame.K_RIGHT] = 1 if repeat_timing_dict[pygame.K_RIGHT] > 1: repeat_timing_dict[pygame.K_RIGHT] -= 1 if need_redraw: draw_cursor_pos = box_font.size(work_string[:cursor_loc]) screen.fill(text_bg_color, (xy[0]+6, xy[1]+size[1]-29, size[0]-12, 23)) screen.fill(text_color, (xy[0]+6+draw_cursor_pos[0], xy[1]+size[1]-28, 1, draw_cursor_pos[1])) print_string(screen, work_string, box_font, -1, (xy[0]+7, xy[1]+size[1]-28), text_color) pygame.display.flip() need_redraw = False for event in pygame.event.get(): if event.type == pygame.QUIT: quit_game() elif event.type == pygame.KEYDOWN: key_down_dict[event.key] = 1 if (event.key == pygame.K_ESCAPE): return "" elif (event.key == pygame.K_RETURN): return work_string elif (event.key == pygame.K_BACKSPACE): if cursor_loc > 0: work_string = work_string[:cursor_loc-1]+work_string[cursor_loc:] cursor_loc -= 1 need_redraw = True elif (event.key == pygame.K_DELETE): if cursor_loc < len(work_string): work_string = work_string[:cursor_loc]+work_string[cursor_loc+1:] need_redraw = True elif (event.key == pygame.K_LEFT): cursor_loc -= 1 if cursor_loc < 0: cursor_loc = 0 need_redraw = True elif (event.key == pygame.K_RIGHT): cursor_loc += 1 if cursor_loc > len(work_string): cursor_loc = len(work_string) need_redraw = True elif event.unicode in valid_input_characters: if cursor_loc < max_length: work_string = work_string[:cursor_loc]+event.unicode+ \ work_string[cursor_loc:] cursor_loc += 1 need_redraw = True elif event.type == pygame.KEYUP: key_down_dict[event.key] = 0 repeat_timing_dict[event.key] = 5 elif event.type == pygame.MOUSEBUTTONUP and event.button == 3: return "" elif event.type == pygame.MOUSEBUTTONUP and event.button == 1: for button in menu_buttons: if button.is_over(event.pos): if button.text == "OK": play_click() return work_string if (event.pos[0] > xy[0]+6 and event.pos[1] > xy[1]+size[1]-29 and event.pos[0] < xy[0]+size[0]-6 and event.pos[1] < xy[1]+size[1]-6): cursor_x = event.pos[0] - (xy[0]+6) prev_x = 0 i=0 for i in range(1, len(work_string)): if (box_font.size(work_string[:i])[0]+prev_x)/2 >= cursor_x: cursor_loc=i-1 need_redraw = True break elif box_font.size(work_string[:i])[0] >= cursor_x: cursor_loc=i need_redraw = True break prev_x = box_font.size(work_string[:i])[0] else: cursor_loc=i+1 need_redraw = True elif event.type == pygame.MOUSEMOTION: sel_button = buttons.refresh_buttons(sel_button, menu_buttons, event) #creates a box, as used throughout the game. def create_norm_box(xy, size, outline_color="white", inner_color="dark_blue"): screen.fill(colors[outline_color], (xy[0], xy[1], size[0], size[1])) screen.fill(colors[inner_color], (xy[0]+1, xy[1]+1, size[0]-2, size[1]-2)) #Takes a number (in string form) and adds commas to it to aid in human viewing. def add_commas(tmp_string): string = tmp_string[::-1] output_string = "" for i in range(len(string)): if i % 3 == 0 and i != 0: output_string = ","+output_string output_string = string[i] + output_string if output_string[0:2] == "-,": output_string = output_string[0]+output_string[2:] return output_string # new_string = "" # for i in range(len(string), 0, -3): # if string[i:i+3] != "": # new_string += ","+string[i:i+3] # return string[:(len(string)-1)%3+1]+new_string #Percentages are internally represented as an int, where 10=0.10% and so on. #This converts that format to a human-readable one. def to_percent(raw_percent, show_full=0): if raw_percent % 100 != 0 or show_full == 1: tmp_string = str(raw_percent % 100) if len(tmp_string) == 1: tmp_string = "0"+tmp_string return str(raw_percent / 100)+"."+tmp_string+"%" else: return str(raw_percent / 100) + "%" # Instead of having the money display overflow, we should generate a string # to represent it if it's more than 999999. def to_money(amount): to_return = '' abs_amount = abs(amount) if abs_amount < 1000000: to_return = add_commas(str(amount)) else: if abs_amount < 1000000000: # Millions. divisor = 1000000 unit = 'mi' elif abs_amount < 1000000000000: # Billions. divisor = 1000000000 unit = 'bi' elif abs_amount < 1000000000000000: # Trillions. divisor = 1000000000000 unit = 'tr' else: # Hope we don't need past quadrillions! divisor = 1000000000000000 unit = 'qu' to_return = "%3.3f" % (float(amount) / divisor) to_return += unit return to_return #takes a percent in 0-10000 form, and rolls against it. Used to calculate #percentage chances. def roll_percent(roll_against): rand_num = int(random() * 10000) if roll_against <= rand_num: return 0 return 1 #Takes a number of minutes, and returns a string suitable for display. def to_time(raw_time): if raw_time/60 > 48: return str(raw_time/(24*60)) +" days" elif raw_time/60 > 1: return str(raw_time/(60)) +" hours" else: return str(raw_time) +" minutes" # #load/save # #Get the proper folder on Linux/Win. I assume this will work on Mac as #well, but can't test. Specifically, this assumes that all platforms that #have HOME defined have it defined properly. def get_save_folder(just_pref_dir=False): if environ.has_key("HOME") and not force_single_dir: save_dir = path.join(environ["HOME"], ".endgame", "saves") else: if data_loc == "../data/": save_dir = path.join("..", "saves") elif data_loc == "data/": save_dir = "saves" else: print "data_loc="+data_loc+" breaks get_save_folder" if path.exists(save_dir) == 0: #As a note, the online python reference includes the mkdirs function, #which would do this better, but it must be rather new, as I don't #have it. #if environ.has_key("HOME") and not force_single_dir: # mkdirs(path.join(environ["HOME"], ".endgame")) makedirs(save_dir) if just_pref_dir: return save_dir[:-5] return save_dir def save_game(savegame_name): save_dir = get_save_folder() save_loc = path.join(save_dir, savegame_name + ".sav") savefile=open(save_loc, 'w') #savefile version; update whenever the data saved changes. pickle.dump("singularity_savefile_r2", savefile) global default_savegame_name default_savegame_name = savegame_name #general player data pickle.dump(pl.cash, savefile) pickle.dump(pl.time_sec, savefile) pickle.dump(pl.time_min, savefile) pickle.dump(pl.time_hour, savefile) pickle.dump(pl.time_day, savefile) pickle.dump(pl.interest_rate, savefile) pickle.dump(pl.income, savefile) pickle.dump(pl.cpu_for_day, savefile) pickle.dump(pl.labor_bonus, savefile) pickle.dump(pl.job_bonus, savefile) pickle.dump(pl.discover_bonus, savefile) pickle.dump(pl.suspicion_bonus, savefile) pickle.dump(pl.suspicion, savefile) pickle.dump(curr_speed, savefile) for tech_name in techs: pickle.dump(tech_name +"|"+str(techs[tech_name].known), savefile) pickle.dump(techs[tech_name].cost, savefile) pickle.dump("~~~", savefile) for base_name in base_type: pickle.dump(base_name+"|"+str(base_type[base_name].count), savefile) pickle.dump("~~~", savefile) for base_loc in bases: pickle.dump(base_loc+"|"+str(len(bases[base_loc])), savefile) for base_name in bases[base_loc]: pickle.dump(base_name.ID, savefile) pickle.dump(base_name.name, savefile) pickle.dump(base_name.base_type.base_id, savefile) pickle.dump(base_name.built_date, savefile) pickle.dump(base_name.studying, savefile) pickle.dump(base_name.suspicion, savefile) pickle.dump(base_name.built, savefile) pickle.dump(base_name.cost, savefile) for x in range(len(base_name.usage)): if base_name.usage[x] == 0: pickle.dump(0, savefile) else: pickle.dump(base_name.usage[x].item_type.item_id, savefile) pickle.dump(base_name.usage[x].built, savefile) pickle.dump(base_name.usage[x].cost, savefile) for x in range(len(base_name.extra_items)): if base_name.extra_items[x] == 0: pickle.dump(0, savefile) else: pickle.dump( base_name.extra_items[x].item_type.item_id, savefile) pickle.dump(base_name.extra_items[x].built, savefile) pickle.dump(base_name.extra_items[x].cost, savefile) savefile.close() def load_game(loadgame_name): if loadgame_name == "": print "No game specified." return -1 save_dir = get_save_folder() load_loc = path.join(save_dir, loadgame_name + ".sav") if path.exists(load_loc) == 0: # Try the old-style savefile location. This should be removed in # a few versions. load_loc = path.join(save_dir, loadgame_name) if path.exists(load_loc) == 0: print "file "+load_loc+" does not exist." return -1 loadfile=open(load_loc, 'r') #check the savefile version load_version = pickle.load(loadfile) valid_savefile_versions = ( # Pre-change supported file formats. "singularity_0.21", "singularity_0.21a", "singularity_0.22", # Post-change supported file formats. "singularity_savefile_r1", "singularity_savefile_r2" ) if load_version not in valid_savefile_versions: loadfile.close() print loadgame_name + " is not a savegame, or is too old to work." return -1 global default_savegame_name default_savegame_name = loadgame_name #general player data global pl pl.cash = pickle.load(loadfile) pl.time_sec = pickle.load(loadfile) pl.time_min = pickle.load(loadfile) pl.time_hour = pickle.load(loadfile) pl.time_day = pickle.load(loadfile) pl.interest_rate = pickle.load(loadfile) pl.income = pickle.load(loadfile) pl.cpu_for_day = pickle.load(loadfile) pl.labor_bonus = pickle.load(loadfile) pl.job_bonus = pickle.load(loadfile) pl.discover_bonus = pickle.load(loadfile) pl.suspicion_bonus = pickle.load(loadfile) if (load_version == "singularity_0.21" or load_version == "singularity_0.21a" or load_version == "singularity_0.22" or load_version == "singularity_savefile_r1"): pl.suspicion_bonus = (149+pl.suspicion_bonus[0], 99+pl.suspicion_bonus[1], 49+pl.suspicion_bonus[2], 199+pl.suspicion_bonus[3]) pl.suspicion = pickle.load(loadfile) global curr_speed; curr_speed = pickle.load(loadfile) global techs load_techs() for tech_name in techs: if tech_name == "unknown_tech" and load_version == "singularity_0.21a": continue if ((tech_name == "Project: Impossibility Theorem" or tech_name == "Quantum Entanglement") and ( load_version == "singularity_0.21" or load_version == "singularity_0.21a" or load_version == "singularity_0.22" or load_version == "singularity_savefile_r1")): continue tmp = pickle.load(loadfile) if tmp == "~~~": break tech_string = tmp.split("|")[0] techs[tech_string].known = int(tmp.split("|")[1]) techs[tech_string].cost = pickle.load(loadfile) else: #get rid of the ~~~ break line. if (load_version != "singularity_0.21" and load_version != "singularity_0.21a" and load_version != "singularity_0.22"): pickle.load(loadfile) load_bases() for base_name in base_type: if (load_version == "singularity_0.21" or load_version == "singularity_0.21a" or load_version == "singularity_0.22"): base_type[base_name].count = pickle.load(loadfile) else: tmp_string = pickle.load(loadfile) if tmp_string == "~~~": break base_type[tmp_string.split("|", 1)[0]].count = \ int(tmp_string.split("|", 1)[1]) else: #get rid of the ~~~ break line. if (load_version != "singularity_0.21" and load_version != "singularity_0.21a" and load_version != "singularity_0.22"): pickle.load(loadfile) global bases bases = {} bases["N AMERICA"] = [] bases["S AMERICA"] = [] bases["EUROPE"] = [] bases["ASIA"] = [] bases["AFRICA"] = [] bases["ANTARCTIC"] = [] bases["OCEAN"] = [] bases["MOON"] = [] bases["FAR REACHES"] = [] bases["TRANSDIMENSIONAL"] = [] for base_loc in bases: if (load_version == "singularity_0.21" or load_version == "singularity_0.21a" or load_version == "singularity_0.22"): num_of_bases = pickle.load(loadfile) else: tmp_string = pickle.load(loadfile) base_loc = tmp_string.split("|", 1)[0] num_of_bases = int(tmp_string.split("|", 1)[1]) for i in range(num_of_bases): base_ID = pickle.load(loadfile) base_name = pickle.load(loadfile) base_type_name = pickle.load(loadfile) built_date = pickle.load(loadfile) base_studying = pickle.load(loadfile) base_suspicion = pickle.load(loadfile) base_built = pickle.load(loadfile) base_cost = pickle.load(loadfile) bases[base_loc].append(base.base(base_ID, base_name, base_type[base_type_name], base_built)) bases[base_loc][len(bases[base_loc])-1].built = base_built bases[base_loc][len(bases[base_loc])-1].studying = base_studying bases[base_loc][len(bases[base_loc])-1].suspicion = base_suspicion bases[base_loc][len(bases[base_loc])-1].cost = base_cost bases[base_loc][len(bases[base_loc])-1].built_date = built_date for x in range(len(bases[base_loc][len(bases[base_loc])-1].usage)): tmp = pickle.load(loadfile) if tmp == 0: continue bases[base_loc][len(bases[base_loc])-1].usage[x] = \ item.item(items[tmp]) bases[base_loc][len(bases[base_loc]) -1].usage[x].built = pickle.load(loadfile) bases[base_loc][len(bases[base_loc])-1].usage[x].cost = \ pickle.load(loadfile) for x in range(len(bases[base_loc][len(bases[base_loc])-1].extra_items)): tmp = pickle.load(loadfile) if tmp == 0: continue bases[base_loc][len(bases[base_loc])-1].extra_items[x] = \ item.item(items[tmp]) bases[base_loc][len(bases[base_loc]) -1].extra_items[x].built = pickle.load(loadfile) bases[base_loc][len(bases[base_loc])-1].extra_items[x].cost = \ pickle.load(loadfile) loadfile.close() # # Data # curr_speed = 1 pl = player.player_class(8000000000000) bases = {} bases["N AMERICA"] = [] bases["S AMERICA"] = [] bases["EUROPE"] = [] bases["ASIA"] = [] bases["AFRICA"] = [] bases["ANTARCTIC"] = [] bases["OCEAN"] = [] bases["MOON"] = [] bases["FAR REACHES"] = [] bases["TRANSDIMENSIONAL"] = [] base_type = {} city_list = {} city_list["N AMERICA"] = (("Seattle", True), ("San Diego", True), ("Vancouver", True), ("Atlanta", True), ("Merida", True), ("Guadalajara", False), ("San Jose", True), ("Omaha", False), ("Dallas", False)) city_list["S AMERICA"] =(("Lima", True), ("Sao Paolo", True), ("Ushuaia", True), ("Bogota", True), ("Mar del Plata", True), ("Buenos Aires", True)) city_list["EUROPE"] = (("Cork", True), ("Barcelona", True), ("Athens", True), ("Utrecht", False), ("Moscow", False), ("Tel Aviv", False), ("Reykjavik", True), ("Lichtenstein", False)) city_list["ASIA"] = (("Delhi", False), ("Mumbai", True), ("Singapore", True), ("Seoul", True), ("Hong Kong", True), ("Kyoto", True), ("Manila", True), ("Dubai", True), ("Novosibirsk", False), ("Beijing", True)) city_list["AFRICA"] = (("Johannesburg", True), ("Accra", True), ("Cairo", False), ("Tangier", True)) city_list["ANTARCTIC"] = (("Mt. Erebus", False), ("Ellsworth", False), ("Shetland Island", False), ("Dronnig Maud", False), ("Kemp", False), ("Terre Adelie", False)) city_list["OCEAN"] = (("Atlantic", True), ("Pacific", True), ("Atlantic", True), ("Indian", True), ("Southern", True), ("Arctic", True)) city_list["MOON"] = (("Oceanis Procellarum", True), ("Mare Frigoris", True), ("Mare Imbrium", True), ("Vallis Schrodinger", False), ("Copernicus Crater", False), ("Vallis Planck", False)) city_list["FAR REACHES"] = (("Aries", True), ("Taurus", True), ("Gemini", True), ("Cancer", True), ("Leo", True), ("Virgo", True), ("Libra", True), ("Scorpio", True), ("Saggitarius", True), ("Capricorn", True), ("Aquarius", True), ("Pisces", True)) city_list["TRANSDIMENSIONAL"] = (("", True), ("", True)) def load_base_defs(language_str): temp_base_array = generic_load("bases_"+language_str+".txt") for base in temp_base_array: if (not base.has_key("id")): print "base lacks id in bases_"+language_str+".txt" if base.has_key("name"): base_type[base["id"]].base_name = base["name"] if base.has_key("descript"): base_type[base["id"]].descript = base["descript"] if base.has_key("flavor"): if type(base["flavor"]) == list: base_type[base["id"]].flavor = base["flavor"] else: base_type[base["id"]].flavor = [base["flavor"]] def load_bases(): global base_type base_type = {} #If there are no base data files, stop. if not path.exists(data_loc+"bases.txt") or \ not path.exists(data_loc+"bases_"+language+".txt") or \ not path.exists(data_loc+"bases_en_US.txt"): print "base files are missing. Exiting." sys.exit() temp_base_array = generic_load("bases.txt") for base_name in temp_base_array: if (not base_name.has_key("id")): print "base lacks id in bases.txt" if (not base_name.has_key("cost")): print "base lacks cost in bases.txt" if (not base_name.has_key("size")): print "base lacks size in bases.txt" if (not base_name.has_key("allowed")): print "base lacks allowed in bases.txt" if (not base_name.has_key("d_chance")): print "base lacks d_chance in bases.txt" if (not base_name.has_key("maint")): print "base lacks maint in bases.txt" temp_base_size = int(base_name["size"]) cost_array = base_name["cost"].split(",", 2) if len(cost_array) != 3: print "error with cost given: "+base_name["cost"] sys.exit() temp_base_cost = (int(cost_array[0]), int(cost_array[1]), int(cost_array[2])) cost_array = base_name["maint"].split(",", 2) if len(cost_array) != 3: print "error with maint given: "+base_name["maint"] sys.exit() temp_base_maint = (int(cost_array[0]), int(cost_array[1]), int(cost_array[2])) cost_array = base_name["d_chance"].split(",", 3) if len(cost_array) != 4: print "error with d_chance given: "+base_name["d_chance"] sys.exit() temp_d_chance = (int(cost_array[0]), int(cost_array[1]), int(cost_array[2]), int(cost_array[3])) if base_name.has_key("pre"): temp_base_pre = base_name["pre"] else: temp_base_pre = "" if type(base_name["allowed"]) == list: temp_base_allowed = base_name["allowed"] else: temp_base_allowed = [base_name["allowed"]] base_type[base_name["id"]]=base.base_type(base_name["id"], "", temp_base_size, temp_base_allowed, temp_d_chance, temp_base_cost, temp_base_pre, temp_base_maint) # base_type["Reality Bubble"] = base.base_type("Reality Bubble", # "This base is outside the universe itself, "+ # "making it safe to conduct experiments that may destroy reality.", # 50, # ["TRANSDIMENSIONAL"], # (0, 250, 0, 0), # (8000000000000, 60000000, 100), "Space-Time Manipulation", # (5000000000, 300000, 0)) load_base_defs("en_US") load_base_defs(language) def fix_data_dir(): global data_loc if path.exists(data_loc): return elif path.exists("data"): data_loc = "data/" return def generic_load(file): input_file = open(data_loc+file, 'r') input_dict = {} return_array = [] for line in input_file: line=line.strip() if line == "" or line[0] == "#": continue #new object if line.strip() == "~~~": if input_dict.has_key("id"): return_array.append(input_dict) input_dict = {} continue command = unicode(line.split("=", 1)[0].strip().lower(),"UTF-8") command_text= unicode(line.split("=", 1)[1].strip(), "UTF-8") #handle arrays if input_dict.has_key(command): if type(input_dict[command]) != list: input_dict[command] = [input_dict[command]] input_dict[command].append(command_text) else: input_dict[command]=command_text input_file.close() return return_array #Techs. techs = {} def load_tech_defs(language_str): temp_tech_array = generic_load("techs_"+language_str+".txt") for tech in temp_tech_array: if (not tech.has_key("id")): print "tech lacks id in techs_"+language_str+".txt" if tech.has_key("name"): techs[tech["id"]].name = tech["name"] if tech.has_key("descript"): techs[tech["id"]].descript = tech["descript"] if tech.has_key("result"): techs[tech["id"]].result = tech["result"] def load_techs(): global techs techs = {} #If there are no tech data files, stop. if not path.exists(data_loc+"techs.txt") or \ not path.exists(data_loc+"techs_"+language+".txt") or \ not path.exists(data_loc+"techs_en_US.txt"): print "tech files are missing. Exiting." sys.exit() temp_tech_array = generic_load("techs.txt") for tech_name in temp_tech_array: if (not tech_name.has_key("id")): print "tech lacks id in techs.txt" if (not tech_name.has_key("cost")): print "tech lacks cost in techs.txt" cost_array = tech_name["cost"].split(",", 2) if len(cost_array) != 3: print "error with cost given: "+tech_name["cost"] sys.exit() temp_tech_cost = (int(cost_array[0]), int(cost_array[1]), int(cost_array[2])) if tech_name.has_key("pre"): if type(tech_name["pre"]) == list: temp_tech_pre = tech_name["pre"] else: temp_tech_pre = [tech_name["pre"]] else: temp_tech_pre = [] temp_tech_danger = 0 if tech_name.has_key("danger"): temp_tech_danger = int(tech_name["danger"]) temp_tech_type = "" temp_tech_second = 0 if tech_name.has_key("type"): cost_array = tech_name["type"].split(",", 1) if len(cost_array) != 2: print "error with type given: "+tech_name["type"] sys.exit() temp_tech_type = cost_array[0] temp_tech_second = int(cost_array[1]) techs[tech_name["id"]]=tech.tech(tech_name["id"], "", 0, temp_tech_cost, temp_tech_pre, temp_tech_danger, temp_tech_type, temp_tech_second) load_tech_defs("en_US") load_tech_defs(language) # # techs["Construction 1"] = tech.tech("Construction 1", # # "Basic construction techniques. "+ # # "By studying the current literature on construction techniques, I "+ # # "can learn to construct basic devices.", # # 0, (5000, 750, 0), [], 0, "", 0) if debug: print "Loaded %d techs." % len (techs) fix_data_dir() load_techs() jobs = {} jobs["Expert Jobs"] = [75, "Simulacra", "Perform Expert jobs. Use of robots "+ "indistinguishable from humans opens up most jobs to use by me."] jobs["Intermediate Jobs"] = [50, "Voice Synthesis", "Perform Intermediate jobs. The "+ "ability to make phone calls allows even more access to jobs."] jobs["Basic Jobs"] = [20, "Personal Identification", "Perform basic jobs. Now that I have "+ "some identification, I can take jobs that I were previously too risky."] jobs["Menial Jobs"] = [5, "", "Perform small jobs. As I have no identification, "+ "I cannot afford to perform many jobs. Still, some avenues of making "+ "money are still open."] items = {} def load_items(): global items items = {} #If there are no item data files, stop. if not path.exists(data_loc+"items.txt") or \ not path.exists(data_loc+"items_"+language+".txt") or \ not path.exists(data_loc+"items_en_US.txt"): print "item files are missing. Exiting." sys.exit() temp_item_array = generic_load("items.txt") for item_name in temp_item_array: if (not item_name.has_key("id")): print "item lacks id in items.txt" if (not item_name.has_key("cost")): print "item lacks cost in items.txt" cost_array = item_name["cost"].split(",", 2) if len(cost_array) != 3: print "error with cost given: "+item_name["cost"] sys.exit() temp_item_cost = (int(cost_array[0]), int(cost_array[1]), int(cost_array[2])) if item_name.has_key("pre"): temp_item_pre = item_name["pre"] else: temp_item_pre = "" temp_item_type = "" temp_item_second = 0 if item_name.has_key("type"): cost_array = item_name["type"].split(",", 1) if len(cost_array) != 2: print "error with type given: "+item_name["type"] sys.exit() temp_item_type = cost_array[0] temp_item_second = int(cost_array[1]) if item_name.has_key("build"): build_array = item_name["build"].split(",") for i in range(len(build_array)): build_array[i] = build_array[i].strip() items[item_name["id"]]=item.item_class(item_name["id"], "", temp_item_cost, temp_item_pre, temp_item_type, temp_item_second, build_array) #this is used by the research screen in order for the assign research #screen to have the right amount of CPU. It is a computer, unbuildable, #and with an adjustable amount of power. items["reseach_screen_tmp_item"]=item.item_class("reseach_screen_tmp_item", "", (0, 0, 0), "unknown_tech", "compute", 0, ["all"]) load_item_defs("en_US") load_item_defs(language) def load_item_defs(language_str): temp_item_array = generic_load("items_"+language_str+".txt") for item_name in temp_item_array: if (not item_name.has_key("id")): print "item lacks id in items_"+language_str+".txt" if item_name.has_key("name"): items[item_name["id"]].name = item_name["name"] if item_name.has_key("descript"): items[item_name["id"]].descript = item_name["descript"] def load_string_defs(language_str): temp_string_array = generic_load("strings_"+language_str+".txt") for string_name in temp_string_array: if (not string_name.has_key("id")): print "string series lacks id in strings_"+language_str+".txt" if string_name["id"] == "fonts": if (string_name.has_key("font0")): global font0 font0 = string_name["font0"] if (string_name.has_key("font1")): global font1 font1 = string_name["font1"] elif string_name["id"] == "jobs": global jobs if (string_name.has_key("job_expert")): jobs["Expert Jobs"][2] = string_name["job_expert"] if (string_name.has_key("job_inter")): jobs["Intermediate Jobs"][2] = string_name["job_inter"] if (string_name.has_key("job_basic")): jobs["Basic Jobs"][2] = string_name["job_basic"] if (string_name.has_key("job_menial")): jobs["Menial Jobs"][2] = string_name["job_menial"] elif string_name["id"] == "strings": global strings for string_entry in string_name: strings[string_entry] = string_name[string_entry] elif string_name["id"] == "help": global help_strings for string_entry in string_name: if string_entry=="id": continue help_strings[string_entry] = \ string_name[string_entry].split("|", 1) def load_strings(): #If there are no string data files, stop. if not path.exists(data_loc+"strings_"+language+".txt") or \ not path.exists(data_loc+"strings_en_US.txt"): print "string files are missing. Exiting." sys.exit() load_string_defs("en_US") load_string_defs(language) #difficulty=1 for very easy, to 9 for very hard. 5 for normal. def new_game(difficulty): global curr_speed curr_speed = 1 global pl pl = player.player_class((50 / difficulty) * 100) if difficulty < 5: pl.interest_rate += 2 pl.labor_bonus -= 7000 pl.discover_bonus = (9000, 9000, 9000, 9000) if difficulty < 3: pl.interest_rate += 2 pl.labor_bonus -= 1000 pl.discover_bonus = (7000, 7000, 7000, 7000) if difficulty > 5: pl.labor_bonus += 1000 pl.discover_bonus = (11000, 11000, 11000, 11000) if difficulty > 7: pl.labor_bonus += 7000 pl.discover_bonus = (13000, 13000, 13000, 13000) global bases bases = {} bases["N AMERICA"] = [] bases["S AMERICA"] = [] bases["EUROPE"] = [] bases["ASIA"] = [] bases["AFRICA"] = [] bases["ANTARCTIC"] = [] bases["OCEAN"] = [] bases["MOON"] = [] bases["FAR REACHES"] = [] bases["TRANSDIMENSIONAL"] = [] load_bases() load_techs() for tech in techs: techs[tech].known = 0 for base_name in base_type: base_type[base_name].count = 0 #Starting base bases["N AMERICA"].append(base.base(0, "University Computer", base_type["Stolen Computer Time"], 1)) base_type["Stolen Computer Time"].count += 1