def return_savegame(self): save = self.listbox.current_item() try: sv.load_savegame(save) return True except sv.SavegameVersionException as e: md = dialog.MessageDialog(self, pos=(-.5,-.5), size=(.5,.5), anchor=constants.MID_CENTER, text=_(""" This save file '{SAVE_NAME}' is from an unsupported or invalid version: {VERSION}. """, SAVE_NAME=save.name, VERSION=e.version)) dialog.call_dialog(md, self) except Exception: log_func_exc(sv.load_savegame) md = dialog.MessageDialog(self, pos=(-.5,-.5), size=(.5,.5), anchor=constants.MID_CENTER, text=_(""" Attempting to load the save file '{SAVE_NAME}' caused an unexpected error. A report was written out to{LOG_TEXT} Please create a issue with this report and this savegame at Github: https://github.com/singularity/singularity """, \ SAVE_NAME = save.name, \ LOG_TEXT = (":\n" + g.logfile if g.logfile is not None else " console output."))) dialog.call_dialog(md, self) return False
def handle_double_click(self, event): if self.listbox.is_over(event.pos) and 0 <= self.listbox.list_pos < len(self.key_list): message = self.key_list[self.listbox.list_pos] message_dialog = dialog.MessageDialog(self, text_size=20) message_dialog.text = message.full_message message_dialog.color = message.full_message_color dialog.call_dialog(message_dialog, self)
def open_base(self): if 0 <= self.listbox.list_pos < len(self.listbox.key_list): base = self.listbox.key_list[self.listbox.list_pos] if not base.done: return self.base_dialog.base = base dialog.call_dialog(self.base_dialog, self) self.needs_rebuild = True self.parent.needs_rebuild = True
def destroy_base(self): if 0 <= self.listbox.list_pos < len(self.listbox.key_list): selected_base = self.listbox.key_list[self.listbox.list_pos] all_active_bases = [b for b in g.all_bases() if b.maintains_singularity] if len(all_active_bases) == 1 and all_active_bases[0] == selected_base: dialog.call_dialog(self.cannot_destroy_last_base, self) elif dialog.call_dialog(self.confirm_destroy, self): selected_base.destroy() self.listbox.list = [b.name for b in self.location.bases] self.listbox.key_list = self.location.bases self.needs_rebuild = True self.parent.needs_rebuild = True
def convert_save(self): save = self.listbox.current_item() if save is None: return if not self._load_savegame(save): return # For ".sav" files, we end up creating a parallel ".s2" file and need # to clean up the ".sav" file manually. overwrites_in_place = False if sv.savegame_exists(save.name): if save.savegame_format.internal_version < 99.8: # We seem to be updating a ".sav" file but there is an ".s2" # file? This should only happen to beta testers yn = dialog.YesNoDialog( self, pos=(-.5, -.5), size=(-.5, -.5), anchor=constants.MID_CENTER, text=_( "A savegame with the same name but for a newer version exists.\n" "Are you sure to overwrite the saved game ?")) overwrite = dialog.call_dialog(yn, self) if not overwrite: return else: # Saving will override in place; overwrites_in_place = True sv.create_savegame(save.name) if not overwrites_in_place: sv.delete_savegame(save) self.reload_savegames()
def check_restart(self): # Test all changes that require a restart. Currently, none. # We keep it for future need... need_restart = False # Add restart test here. if not need_restart: # No restart required. Simply exit the dialog respecting all hooks self.yes_button.exit_dialog() return # Ask user about a restart ask_restart = dialog.YesNoDialog( self, pos=(-.50, -.50), anchor=constants.MID_CENTER, text= _("""You must restart for some of the changes to be fully applied.\n Would you like to restart the game now?"""), ) if dialog.call_dialog(ask_restart, self): # YES, go for it #TODO: check if there is an ongoing game, save it under a special # name and automatically load it after restart using a custom # command-line argument save_options() restart() else: # NO, revert "restart-able" changes pass
def show_dialog(self): """When the assigned dialog exits, raises Handled with the dialog's exit code as a parameter. Subclass if you care what the code was.""" if not self.dialog: raise constants.Handled else: from singularity.code.graphics import dialog raise constants.Handled(dialog.call_dialog(self.dialog, self))
def new_base(self): result = dialog.call_dialog(self.new_base_dialog, self) if result: base_type, base_name = result new_base = base.Base(base_type, base_name) self.location.add_base(new_base) self.needs_rebuild = True self.parent.needs_rebuild = True
def steal_money(self): asked = dialog.call_dialog(self.steal_amount_dialog, self) try: g.pl.cash += int(asked) except ValueError: pass else: self.needs_rebuild = True
def rename_base(self): if 0 <= self.listbox.list_pos < len(self.listbox.key_list): base = self.listbox.key_list[self.listbox.list_pos] self.name_dialog.default_text = base.name name = dialog.call_dialog(self.name_dialog, self) if name: base.name = name self.needs_rebuild = True
def save_game(self): self.savename_dialog.default_text = sv.default_savegame_name name = dialog.call_dialog(self.savename_dialog, self) if name: if sv.savegame_exists(name): yn = dialog.YesNoDialog( self, pos=(-.5, -.5), size=(-.5, -.5), anchor=constants.MID_CENTER, text=_("A savegame with the same name exists.\n" "Are you sure to overwrite the saved game ?")) overwrite = dialog.call_dialog(yn, self) if not overwrite: return sv.create_savegame(name) raise constants.ExitDialog(False)
def delete_savegame(self): yn = dialog.YesNoDialog(self, pos=(-.5,-.5), size=(-.5,-1), anchor=constants.MID_CENTER, text=_("Are you sure to delete the saved game ?")) delete = dialog.call_dialog(yn, self) yn.parent = None if delete: save = self.listbox.current_item() sv.delete_savegame(save) self.reload_savegames()
def save_game(self): # If no savename was set yet, use current difficulty if not sv.last_savegame_name: sv.last_savegame_name = g.strip_hotkey(g.pl.difficulty.name) self.savename_dialog.default_text = sv.last_savegame_name self.savename_dialog.add_handler(constants.KEYUP, self.check_filename) self.savename_dialog.text_field.has_focus = True name = dialog.call_dialog(self.savename_dialog, self).strip() if name: if sv.savegame_exists(name): yn = dialog.YesNoDialog(self, pos=(-.5,-.5), size=(-.5,-.5), anchor=constants.MID_CENTER, text=_("A savegame with the same name exists.\n" "Are you sure to overwrite the saved game ?")) overwrite = dialog.call_dialog(yn, self) if not overwrite: self.save_game() sv.create_savegame(name) raise constants.ExitDialog(False)
def handle_double_click(self, event): if self.listbox.is_over(event.pos) and 0 <= self.listbox.list_pos < len(self.key_list): message = self.key_list[self.listbox.list_pos] # use the MapScreen (our parent) as parent for the dialog to match # how it is originally shown (plus to avoid "cannot fit" warnings # when the dialog is larger than the log screen) message_dialog = dialog.MessageDialog(self.parent, text_size=20) message_dialog.text = message.full_message message_dialog.color = message.full_message_color # Because we need to use the MapScreen as parent, we need to juggle # things manually (as call_dialog works with a different assumption # than we need). try: self.visible = False dialog.call_dialog(message_dialog, self.parent) finally: self.visible = True self.needs_rebuild = True self.parent.needs_rebuild = True self.parent.lost_focus() self.regained_focus()
def show(self): self.force_update() from singularity.code.safety import safe_call # By using safe call here (and only here), if an error is raised # during the game, it will drop back out of all the menus, without # doing anything, and open the pause dialog, so that the player can # save or quit even if the error occurs every game tick. while safe_call(super(MapScreen, self).show, on_error=True): for child in self.children: if isinstance(child, dialog.Dialog): child.visible = False # Display a message so the player understand better what happened. msg = _(""" A error has occurred. The game will automatically pause and open the game menu. You can continue and save or quit immediately. A report was written out to%s Please create a issue with this report at github: https://github.com/singularity/singularity """ % (":\n" + g.logfile if g.logfile is not None else " console output.")) d = dialog.YesNoDialog(self, pos=(-.5, -.5), size=(-.5, -.5), anchor=constants.MID_CENTER, yes_type="continue", no_type="quit", text=msg) cont = dialog.call_dialog(d, self) if not cont: raise SystemExit exit = dialog.call_dialog(self.menu_dialog, self) if exit: self.visible = False return
def show_list(self, message_type, messages): if (len(messages) == 0): return self.dialog.type = message_type self.dialog.list = messages ret = dialog.call_dialog(self.dialog, self.screen) # Pause game if (not ret): g.pl.pause_game() return True # Continue return False
def show_story_section(self, name): section = list(g.get_story_section(name)) first_dialog = dialog.YesNoDialog(self, yes_type=N_("&CONTINUE"), no_type=N_("&SKIP")) last_dialog = dialog.MessageDialog(self, ok_type=N_("&OK")) for num, segment in enumerate(section): story_dialog = first_dialog if num != len(section) - 1 else last_dialog story_dialog.text = segment if not dialog.call_dialog(story_dialog, self): break first_dialog.parent = None last_dialog.parent = None
def show_story_section(self, name): section = list(g.get_story_section(name)) first_dialog = dialog.YesNoDialog(self, yes_type="continue", no_type="skip") last_dialog = dialog.MessageDialog(self, ok_type="ok") for num, segment in enumerate(section): story_dialog = first_dialog if num != len( section) - 1 else last_dialog story_dialog.text = segment if not dialog.call_dialog(story_dialog, self): break first_dialog.parent = None last_dialog.parent = None
def build_item(self, type): if (type.id == "cpu"): build_dialog = self.multiple_build_dialog else: build_dialog = self.build_dialog build_dialog.type = type result = dialog.call_dialog(build_dialog, self) if result is not None and 0 <= result < len(build_dialog.key_list): item_type = build_dialog.key_list[result] count = 1 if (type.id == "cpu"): count = build_dialog.count self.set_current(type, item_type, count) self.needs_rebuild = True self.parent.parent.needs_rebuild = True
def load_game(self): did_load = dialog.call_dialog(self.load_dialog, self) if did_load: dialog.call_dialog(self.map_screen, self)
def new_game(self): difficulty = dialog.call_dialog(self.difficulty_dialog, self) if difficulty is not None: g.new_game(difficulty) dialog.call_dialog(self.map_screen, self)
def open_location(self, location): self.location_dialog.location = g.pl.locations[location] dialog.call_dialog(self.location_dialog, self) return
def show_message(self, message, color=None): self.message_dialog.text = message if color == None: color = "text" self.message_dialog.color = color dialog.call_dialog(self.message_dialog, self)
def show_menu(): exit = dialog.call_dialog(self.menu_dialog, self) if exit: raise constants.ExitDialog
def show_filters(self): dialog.call_dialog(self.filter_log_dialog, self) self.needs_rebuild = True
def load_game(self): did_load = dialog.call_dialog(self.load_dialog, self) if did_load: self._map_screen.force_update() raise constants.ExitDialog(False)
def hidden_state(self): presenters = { float: lambda x: round(x, 4), Location: lambda x: x.id, } def _dump_dict(prefix, mapping): if isinstance(mapping, collections.OrderedDict): keys = mapping else: keys = sorted(mapping) for key in keys: prop_name = '%s["%s"]' % (prefix, key) value = mapping[key] presenter = presenters.get(type(value), repr) yield "%s = %s" % (prop_name, presenter(value)) def _properties_from_object(name, object, properties): for p in properties: value = getattr(object, p) prop_name = '%s.%s' % (name, p) if callable(value): value = value() prop_name += '()' if isinstance(value, collections.Mapping): for v in _dump_dict(prop_name, value): yield v else: presenter = presenters.get(type(value), repr) yield "%s = %s" % (prop_name, presenter(value)) bases = [] state_prop = [] state_prop.extend( _properties_from_object('player.difficulty', g.pl.difficulty, difficulty.columns)) state_prop.extend( _properties_from_object('player', g.pl, [ 'cash', 'partial_cash', 'labor_bonus', 'job_bonus', 'last_discovery', 'prev_discovery', 'used_cpu', ])) for group in g.pl.groups.values(): name = 'groups["%s"]' % group.spec.id state_prop.extend( _properties_from_object(name, group, [ 'suspicion', 'suspicion_decay', 'discover_bonus', 'discover_suspicion', 'decay_rate', ])) for location_id in sorted(g.locations): location = g.pl.locations[location_id] name = 'locations["%s"]' % location.id state_prop.extend( _properties_from_object(name, location, [ 'safety', 'modifiers', 'discovery_bonus', ])) bases.extend((x, location) for x in location.bases) for event_id in sorted(g.pl.events): event = g.pl.events[event_id] name = 'events["%s"]' % event_id state_prop.extend( _properties_from_object(name, event, [ 'event_type', 'chance', 'unique', 'triggered', ])) for i, base_w_loc in enumerate(bases): base, location = base_w_loc name = 'bases[%d]' % i state_prop.extend(_properties_from_object(name, base, [ 'name', ])) state_prop.append("%s.location = %s" % (name, location.id)) state_prop.extend( _properties_from_object(name, base, [ 'started_at', 'grace_over', 'get_detect_chance', ])) state_dialog = dialog.ChoiceDialog( self, list=state_prop, background_color='hidden_state_menu') state_dialog.listbox.item_selectable = False state_dialog.listbox.align = constants.LEFT dialog.call_dialog(state_dialog, self)
def set_current(self, type, item_type, count): if type.id == "cpu": space_left = self.base.space_left_for(item_type) try: count = int(count) except ValueError: msg = _( "\"%(value)s\" does not seem to be a valid integer.") % { "value": count } md = dialog.MessageDialog(self, pos=(-.5, -.5), size=(-.5, -1), anchor=constants.MID_CENTER, text=msg) dialog.call_dialog(md, self) md.parent = None return if count > space_left or count <= 0 or space_left == 0: if space_left > 0: msg = _("Please choose an integer between 1 and %(limit)s." ) % { "limit": space_left } else: msg = _( "The base cannot support any additional number of %(item_name)s." ) % { "item_name": item_type.name } md = dialog.MessageDialog(self, pos=(-.5, -.5), size=(-.5, -1), anchor=constants.MID_CENTER, text=msg) dialog.call_dialog(md, self) md.parent = None return # If there are any existing CPUs of this type, warn that they will # be taken offline until construction finishes. cpu_added = self.base.cpus is not None \ and self.base.cpus.spec == item_type if cpu_added: space_left -= self.base.cpus.count if self.base.cpus.done: msg = _( "I will need to take the existing processors offline while I install the new ones. Continue anyway?" ) yn = dialog.YesNoDialog(self, pos=(-.5, -.5), size=(-.5, -1), anchor=constants.MID_CENTER, text=msg) go_ahead = dialog.call_dialog(yn, self) yn.parent = None if not go_ahead: return # If there are already existing CPUs of other type, warn that they will # be taken removed. cpu_removed = self.base.cpus is not None \ and self.base.cpus.spec != item_type if cpu_removed: msg = _( "I will need to remove the existing different processors while I install the new type. Continue anyway?" ) yn = dialog.YesNoDialog(self, pos=(-.5, -.5), size=(-.5, -1), anchor=constants.MID_CENTER, text=msg) go_ahead = dialog.call_dialog(yn, self) yn.parent = None if not go_ahead: return new_cpus = item.Item(item_type, base=self.base, count=count) if cpu_added: self.base.cpus += new_cpus else: self.base.cpus = new_cpus self.base.check_power() else: old_item = self.base.items[type.id] if old_item is None or old_item.spec != item_type: self.base.items[type.id] = item.Item(item_type, base=self.base) self.base.check_power() self.base.recalc_cpu()
def new_game(self): difficulty = dialog.call_dialog(self.difficulty_dialog, self) if difficulty is not None: sv.last_savegame_name = None g.new_game(difficulty) dialog.call_dialog(self.map_screen, self)
def show_help(self, danger_level): self.help_dialog.text = _( "This technology is too dangerous to research on any of the computers I have. {TEXT}" ).format(TEXT=g.dangers[danger_level].research_desc) dialog.call_dialog(self.help_dialog, self)