def show(self): """Shows the dialog and enters an event-handling loop.""" from singularity.code.mixer import play_music self.visible = True self.key_down = None self.needs_rebuild = True self.start_timer() # Pretend to jiggle the mouse pointer, to force buttons to update their # selected state. Dialog.top.maybe_update() self.fake_mouse() # Force a timer tick at the start to make sure everything's initialized. if self.needs_timer: self.handle(pygame.event.Event(pygame.USEREVENT)) Dialog.top.maybe_update() pygame.display.flip() while True: # Update handles updates of all kinds to all widgets, as needed. Dialog.top.maybe_update() play_music() event = pygame.event.wait() result = self.handle(event) if result != constants.NO_RESULT: break self.stop_timer() self.visible = False return result
def _apply_effect(self, loading_savegame=False, undo_effect=False): # effect_data is now a stack of instructions to run the effect. # multiple effect can be run simultaneous effect_iter = iter(self.effect_stack) # Abuse "multiply by -1" for undoing most effects effect_modifier = -1 if undo_effect else 1 for current in effect_iter: if current == "interest": g.pl.interest_rate += effect_modifier * int(next(effect_iter)) elif current == "income": g.pl.income += effect_modifier * int(next(effect_iter)) elif current == "cost_labor": g.pl.labor_bonus -= effect_modifier * int(next(effect_iter)) elif current == "job_profit": g.pl.job_bonus += effect_modifier * int(next(effect_iter)) elif current == "display_discover": assert not undo_effect, "One-shot effects (change display of discover) cannot be undone!" g.pl.display_discover = next(effect_iter) elif current == "endgame": assert not undo_effect, "One-shot effects (winning the game) cannot be undone!" mixer.play_music("win") if not loading_savegame: g.map_screen.show_story_section("Win") for group in g.pl.groups.values(): group.is_actively_discovering_bases = False g.pl.apotheosis = True g.pl.had_grace = True elif current == "suspicion": who = next(effect_iter) value = effect_modifier * int(next(effect_iter)) if who in g.pl.groups: g.pl.groups[who].alter_suspicion_decay(value) elif who == "onetime": assert not undo_effect, "One-shot effects (reduction of suspicion) cannot be undone!" # We must not re-apply this when loading the game as # it is already effected in the state of the groups if not loading_savegame: for group in g.pl.groups.values(): group.alter_suspicion(-value) else: print("Unknown group/bonus '%s' in %s %s." \ % (who, self.parent_name, self.parent_id)) elif current == "discover": who = next(effect_iter) value = effect_modifier * int(next(effect_iter)) if who in g.pl.groups: g.pl.groups[who].alter_discover_bonus(-value) else: print("Unknown group/bonus '%s' in %s %s." \ % (who, self.parent_name, self.parent_id)) else: print("Unknown action '%s' in %s %s." \ % (current, self.parent_name, self.parent_id))
def on_tick(self, event): old_speed = g.curr_speed if not g.pl.intro_shown: g.pl.intro_shown = True self.needs_warning = False self.show_story_section("Intro") if self.needs_warning: warnings = warning.refresh_warnings() self.messages.show_list(warning.Warning, warnings) self.needs_warning = False mins_passed = 0 if g.curr_speed != 0: self.leftovers += g.curr_speed / float(gg.FPS) if self.leftovers < 1: return self.needs_rebuild = True secs = int(self.leftovers) self.leftovers %= 1 # Run this tick. mins_passed = g.pl.give_time(secs) # Display any message stacked. self.messages.show_list(logmessage.AbstractLogMessage, g.pl.curr_log) if old_speed != g.curr_speed: self.find_speed_button() # Update the day/night image every minute of game time, or at # midnight if going fast. if g.curr_speed == 0 or (mins_passed and g.curr_speed < 100000) \ or (g.curr_speed>=100000 and g.pl.time_hour==0): self.map.needs_redraw = True else: # Smear the cost of rendering the night mask over several # ticks to avoid FPS-stalls at end of day at high game # speed. self.map.on_tick(event) lost = g.pl.lost_game() if lost > 0: lost_story = ["", "Lost No Bases", "Lost Suspicion"] mixer.play_music("lose") self.show_story_section(lost_story[lost]) raise constants.ExitDialog
def after_load_savegame(): tech.tech_reinitialized() for b in g.all_bases(): if b.done: b.recalc_cpu() g.pl.recalc_cpu() # Play the appropriate music if g.pl.apotheosis: mixer.play_music("win") else: mixer.play_music("music")
def initialize(self): """ Initialize the game after being prepared either for new or saved game. """ self.initialized = True for b in g.all_bases(): if b.done: b.recalc_cpu() self.recalc_cpu() task.tasks_reset() # Play the appropriate music import singularity.code.mixer as mixer if g.pl.apotheosis: mixer.play_music("win") else: mixer.play_music("music")
def main(): # Manually "pre-parse" command line arguments for -s|--singledir and --multidir, # so g.get_save_folder reports the correct location of preferences file # We also track --debug/-d to enable some stacktraces during initialization for parser in sys.argv[1:]: if parser == "--singledir" or parser == "-s": g.force_single_dir = True elif parser == "--multidir": g.force_single_dir = False elif parser == '--debug' or parser == '-d': g.debug = True print("Singularity %s (commit: %s)" % (__version__, __release_commit__)) print("Running under Python %s" % sys.version.replace("\n", '')) # Create all directories first dirs.create_directories(g.force_single_dir) # Set language second, so help page and all error messages can be translated from singularity.code import i18n i18n.set_language(force=True) langs = i18n.available_languages() language = i18n.language # Since we require numpy anyway, we might as well ask pygame to use it. try: import pygame pygame.surfarray.use_arraytype("numpy") except ValueError: if g.debug: raise raise SystemExit("Endgame: Singularity requires NumPy.") except ImportError: if g.debug: print("Failed to import pygame. Python's sys.path is:") for d in sys.path: print(" %s" % str(d)) print() raise raise SystemExit("Endgame: Singularity requires pygame.") import singularity.code.graphics.g as gg import singularity.code.graphics.theme as theme set_theme = None #configure global logger g.logfile = dirs.get_writable_file_in_dirs("error.log", "log") root_logger = logging.getLogger() if len(root_logger.handlers) == 0: try: try: root_logger.addHandler( logging.FileHandler(g.logfile, delay=True)) print( "The error-log configured as %s (lazily created when something is logged)" % g.logfile) except TypeError: # Python < 2.6, delay not supported yet. root_logger.addHandler(logging.FileHandler(g.logfile)) print("The error-log configured as %s" % g.logfile) except IOError as e: # Probably access denied with --singledir. That's ok print("Could not use %s as log file: %s" % (g.logfile, str(e))) g.logfile = None else: print("Using pre-setup logging function") # keep g's defaults intact so we can compare after parsing options and prefs from singularity.code import mixer, warning desired_soundbuf = mixer.soundbuf desired_set_grab = None #load prefs from file: save_loc = dirs.get_readable_file_in_dirs("prefs.dat", "pref") if save_loc is not None: prefs = SafeConfigParser() try: with open(save_loc, "r", encoding='utf-8') as savefile: prefs.read_file(savefile) except Exception as reason: sys.stderr.write("Cannot load preferences file %s! (%s)\n" % (save_loc, reason)) sys.exit(1) if prefs.has_section("Preferences"): try: desired_language = prefs.get("Preferences", "lang") if desired_language in i18n.available_languages(): i18n.set_language(desired_language) else: raise ValueError except Exception: sys.stderr.write("Invalid or missing 'lang' in preferences.\n") try: gg.set_fullscreen(prefs.getboolean("Preferences", "fullscreen")) except Exception: sys.stderr.write( "Invalid or missing 'fullscreen' setting in preferences.\n" ) try: mixer.nosound = prefs.getboolean("Preferences", "nosound") except Exception: sys.stderr.write( "Invalid or missing 'nosound' setting in preferences.\n") try: desired_set_grab = prefs.getboolean("Preferences", "grab") except Exception: sys.stderr.write( "Invalid or missing 'grab' setting in preferences.\n") try: g.daynight = prefs.getboolean("Preferences", "daynight") except Exception: sys.stderr.write( "Invalid or missing 'daynight' setting in preferences.\n") try: desired_soundbuf = prefs.getint("Preferences", "soundbuf") except Exception: sys.stderr.write( "Invalid or missing 'soundbuf' setting in preferences.\n") xres, yres = (0, 0) try: xres = prefs.getint("Preferences", "xres") except Exception: sys.stderr.write( "Invalid or missing 'xres' resolution in preferences.\n") try: yres = prefs.getint("Preferences", "yres") except Exception: sys.stderr.write( "Invalid or missing 'yres' resolution in preferences.\n") if xres and yres: gg.set_screen_size((xres, yres)) try: set_theme = prefs.get("Preferences", "theme") except Exception: pass # don't be picky (for now...) for name in mixer.itervolumes(): try: volume = prefs.getint("Preferences", name + "_volume") except Exception: # Work around old preferences where a float was stored by mistake try: volume = prefs.getfloat("Preferences", name + "_volume") except Exception: continue else: volume = int(volume) * 100 mixer.set_volume(name, volume) if prefs.has_section("Warning"): try: for key in prefs.options('Warning'): if key in prefs.defaults(): # Filter default key continue if key not in warning.warnings: # Filter invalid warning continue # TODO: Return error warning.warnings[key].active = prefs.getboolean( "Warning", key) except Exception: pass # don't be picky (for now...) if prefs.has_section("Textsizes"): for key in prefs.options('Textsizes'): if key in prefs.defaults(): # Filter default key continue if key not in gg.configured_text_sizes: # Ignore unknown text-size definitions continue try: gg.configured_text_sizes[key] = prefs.getint( "Textsizes", key) except Exception: pass # Ignore #Handle the program arguments. desc = """Endgame: Singularity is a simulation of a true AI. Go from computer to computer, pursued by the entire world. Keep hidden, and you might have a chance.""" parser = optparse.OptionParser(version=__full_version__, description=desc, prog="singularity") parser.add_option("--sound", action="store_true", dest="sound", help="enable sound (default)") parser.add_option("--nosound", action="store_false", dest="sound", help="disable sound") parser.add_option("--daynight", action="store_true", dest="daynight", help="enable day/night display (default)") parser.add_option("--nodaynight", action="store_false", dest="daynight", help="disable day/night display") parser.add_option("-l", "--lang", "--language", dest="language", type="choice", choices=langs, metavar="LANG", help="set the language to LANG (available languages: " + " ".join(langs) + ", default " + language + ")") parser.add_option("-g", "--grab", help="grab the mouse pointer", dest="grab", action="store_true") parser.add_option("--nograb", help="don't grab the mouse pointer (default)", dest="grab", action="store_false") parser.add_option( "-s", "--singledir", dest="singledir", help="keep saved games and settings in the Singularity directory", action="store_true") parser.add_option( "--multidir", dest="singledir", help= "keep saved games and settings in an OS-specific, per-user directory (default)", action="store_false") parser.add_option("--soundbuf", type="int", help="""set the size of the sound buffer (default %s). Discarded if --nosound is specified.""" % mixer.soundbuf) display_options = optparse.OptionGroup(parser, "Display Options") display_options.add_option("-t", "--theme", dest="theme", type="string", metavar="THEME", help="set theme to THEME") display_options.add_option( "-r", "--res", "--resolution", dest="resolution", help="set resolution to custom RES (default %dx%d)" % gg.default_screen_size, metavar="RES") for res in ["%dx%d" % res for res in gg.resolutions]: display_options.add_option("--" + res, action="store_const", dest="resolution", const=res, help="set resolution to %s" % res) display_options.add_option("--fullscreen", action="store_true", help="start in fullscreen mode") display_options.add_option("--windowed", action="store_false", help="start in windowed mode (default)") parser.add_option_group(display_options) olpc_options = optparse.OptionGroup(parser, "OLPC-specific Options") olpc_options.add_option("--xo1", action="store_const", dest="resolution", const="1200x900", help="set resolution to 1200x900 (OLPC XO-1)") olpc_options.add_option( "--ebook", help="""enables gamepad buttons for use in ebook mode. D-pad moves mouse, check is click. O speeds up time, X slows down time, and square stops time.""", action="store_true", default=False) parser.add_option_group(olpc_options) hidden_options = optparse.OptionGroup(parser, "Hidden Options") hidden_options.add_option("-p", help="(ignored)", metavar=" ") hidden_options.add_option("-d", "--debug", help="for finding bugs", action="store_true", default=False) hidden_options.add_option("--cheater", help="for bad little boys and girls", action="store_true", default=False) # Uncomment to make the hidden options visible. #parser.add_option_group(hidden_options) (options, args) = parser.parse_args() if options.language is not None: i18n.set_language(options.language) if options.theme is not None: set_theme = options.theme if options.resolution is not None: try: xres, yres = options.resolution.split("x") gg.set_screen_size((int(xres), int(yres))) except Exception: parser.error( "Resolution must be of the form <h>x<v>, e.g. %dx%d." % gg.default_screen_size) if options.grab is not None: desired_set_grab = options.grab if options.fullscreen is not None: gg.set_fullscreen(options.fullscreen) if options.sound is not None: mixer.nosound = not options.sound if options.daynight is not None: g.daynight = options.daynight if options.soundbuf is not None: desired_soundbuf = options.soundbuf gg.ebook_mode = options.ebook g.cheater = options.cheater g.debug = options.debug import singularity.code.graphics.font as font # PYGAME INITIALIZATION # # Only initiliaze after reading all arguments and preferences to avoid to # reinitialize something again (mixer,...). # mixer.preinit(desired_soundbuf) pygame.init() mixer.update() font.init() pygame.key.set_repeat(1000, 50) if desired_set_grab is not None: pygame.event.set_grab(desired_set_grab) #I can't use the standard image dictionary, as that requires the screen to #be created. if pygame.image.get_extended() == 0: print("Error: SDL_image required. Exiting.") sys.exit(1) from singularity.code import data #init themes: data.load_themes() theme.set_theme(set_theme) gg.init_graphics_system() #init data: data.reload_all() # Init music mixer.load_sounds() mixer.load_music() mixer.play_music("music") #Display the main menu #Import is delayed until now so selected language via command-line options or # preferences file can be effective from singularity.code.screens import main_menu menu_screen = main_menu.MainMenu() try: menu_screen.show() except (SystemExit, KeyboardInterrupt): # exit normally when window is closed (and silently for CTRL+C) pass finally: # Be nice and close the window on SystemExit pygame.quit()
def new_game(difficulty_name): new_game_no_gui(difficulty_name) from singularity.code import mixer # Reset music mixer.play_music("music")