def _do_save(self, savegame): """Actual save code. @param savegame: absolute path""" assert os.path.isabs(savegame) self.log.debug("Session: Saving to %s", savegame) try: if os.path.exists(savegame): os.unlink(savegame) self.savecounter += 1 db = DbReader(savegame) except IOError as e: # usually invalid filename headline = _("Failed to create savegame file") descr = _("There has been an error while creating your savegame file.") advice = _("This usually means that the savegame name contains unsupported special characters.") self.gui.show_error_popup(headline, descr, advice, unicode(e)) return self.save() # retry with new savegamename entered by the user # this must not happen with quicksave/autosave except ZeroDivisionError as err: # TODO: # this should say WindowsError, but that somehow now leads to a NameError if err.winerror == 5: self.gui.show_error_popup(_("Access is denied"), \ _("The savegame file is probably read-only.")) return self.save() elif err.winerror == 32: self.gui.show_error_popup(_("File used by another process"), \ _("The savegame file is currently used by another program.")) return self.save() raise try: read_savegame_template(db) db("BEGIN") self.world.save(db) #self.manager.save(db) self.view.save(db) self.ingame_gui.save(db) self.scenario_eventhandler.save(db) LastActivePlayerSettlementManager().save(db) for instance in self.selected_instances: db("INSERT INTO selected(`group`, id) VALUES(NULL, ?)", instance.worldid) for group in xrange(len(self.selection_groups)): for instance in self.selection_groups[group]: db("INSERT INTO selected(`group`, id) VALUES(?, ?)", group, instance.worldid) rng_state = json.dumps( self.random.getstate() ) SavegameManager.write_metadata(db, self.savecounter, rng_state) # make sure everything get's written now db("COMMIT") db.close() return True except: print "Save Exception" traceback.print_exc() db.close() # close db before delete os.unlink(savegame) # remove invalid savegamefile return False
def _create_map_db(self, savepath): """Returns a dbreader instance, that is connected to the main game data dbfiles.""" horizons.main.PATHS.SAVEGAME_TEMPLATE = os.path.join(util.getUHPath(), horizons.main.PATHS.SAVEGAME_TEMPLATE) db = UhDbAccessor(savepath) read_savegame_template(db) return db
def _do_save(self, savegame): """Actual save code. @param savegame: absolute path""" assert os.path.isabs(savegame) self.log.debug("Session: Saving to %s", savegame) try: if os.path.exists(savegame): os.unlink(savegame) self.savecounter += 1 db = DbReader(savegame) except IOError as e: # usually invalid filename headline = T("Failed to create savegame file") descr = T( "There has been an error while creating your savegame file.") advice = T( "This usually means that the savegame name contains unsupported special characters." ) self.ingame_gui.open_error_popup(headline, descr, advice, unicode(e)) # retry with new savegamename entered by the user # (this must not happen with quicksave/autosave) return self.save() except OSError as e: if e.errno != errno.EACCES: raise self.ingame_gui.open_error_popup( T("Access is denied"), T("The savegame file could be read-only or locked by another process." )) return self.save() try: read_savegame_template(db) db("BEGIN") self.world.save(db) self.view.save(db) self.ingame_gui.save(db) self.scenario_eventhandler.save(db) # Store RNG state rng_state = json.dumps(self.random.getstate()) SavegameManager.write_metadata(db, self.savecounter, rng_state) # Make sure everything gets written now db("COMMIT") db.close() return True except Exception: self.log.error("Save Exception:") traceback.print_exc() # remove invalid savegamefile (but close db connection before deleting) db.close() os.unlink(savegame) return False
def _do_save(self, savegame): """Actual save code. @param savegame: absolute path""" assert os.path.isabs(savegame) self.log.debug("Session: Saving to %s", savegame) try: if os.path.exists(savegame): os.unlink(savegame) self.savecounter += 1 db = DbReader(savegame) except IOError as e: # usually invalid filename headline = _("Failed to create savegame file") descr = _("There has been an error while creating your savegame file.") advice = _("This usually means that the savegame name contains unsupported special characters.") self.ingame_gui.show_error_popup(headline, descr, advice, unicode(e)) # retry with new savegamename entered by the user # (this must not happen with quicksave/autosave) return self.save() except OSError as e: if e.errno != errno.EACCES: raise self.ingame_gui.show_error_popup( _("Access is denied"), _("The savegame file could be read-only or locked by another process.") ) return self.save() try: read_savegame_template(db) db("BEGIN") self.world.save(db) self.view.save(db) self.ingame_gui.save(db) self.scenario_eventhandler.save(db) # Store RNG state rng_state = json.dumps(self.random.getstate()) SavegameManager.write_metadata(db, self.savecounter, rng_state) # Make sure everything gets written now db("COMMIT") db.close() return True except Exception: self.log.error("Save Exception:") traceback.print_exc() # remove invalid savegamefile (but close db connection before deleting) db.close() os.unlink(savegame) return False
def save_map(world, path, prefix): map_file = os.path.join(path, prefix + '.sqlite') db = DbReader(map_file) read_savegame_template(db) db('BEGIN') for island in world.islands: island_name = '%s_island_%d_%d.sqlite' % (prefix, island.origin.x, island.origin.y) island_db_path = os.path.join(path, island_name) if os.path.exists(island_db_path): os.unlink(island_db_path) # the process relies on having an empty file db('INSERT INTO island (x, y, file) VALUES(?, ?, ?)', island.origin.x, island.origin.y, 'content/islands/' + island_name) island_db = DbReader(island_db_path) island.save_map(island_db) island_db.close() db('COMMIT') db.close()
def save_map(world, path, prefix): map_file = os.path.join(path, prefix + '.sqlite') db = DbReader(map_file) read_savegame_template(db) db('BEGIN') for island in world.islands: island_name = '%s_island_%d_%d.sqlite' % (prefix, island.origin.x, island.origin.y) island_db_path = os.path.join(path, island_name) if os.path.exists(island_db_path): os.unlink( island_db_path) # the process relies on having an empty file db('INSERT INTO island (x, y, file) VALUES(?, ?, ?)', island.origin.x, island.origin.y, 'content/islands/' + island_name) island_db = DbReader(island_db_path) island.save_map(island_db) island_db.close() db('COMMIT') db.close()
def create_map(): """ Create a map with a square island (20x20) at position (20, 20) and return the path to the database file. """ # Create island. fd, islandfile = tempfile.mkstemp() os.close(fd) db = DbReader(islandfile) db("CREATE TABLE ground(x INTEGER NOT NULL, y INTEGER NOT NULL, ground_id INTEGER NOT NULL, action_id TEXT NOT NULL, rotation INTEGER NOT NULL)") db("CREATE TABLE island_properties(name TEXT PRIMARY KEY NOT NULL, value TEXT NOT NULL)") db("BEGIN TRANSACTION") tiles = [] for x, y in Rect.init_from_topleft_and_size(0, 0, 20, 20).tuple_iter(): if (0 < x < 20) and (0 < y < 20): ground = GROUND.DEFAULT_LAND else: # Add coastline at the borders. ground = GROUND.SHALLOW_WATER tiles.append([x, y] + list(ground)) db.execute_many("INSERT INTO ground VALUES(?, ?, ?, ?, ?)", tiles) db("COMMIT") # Create savegame with the island above. fd, savegame = tempfile.mkstemp() os.close(fd) db = DbReader(savegame) read_savegame_template(db) db("BEGIN TRANSACTION") db("INSERT INTO island (x, y, file) VALUES(?, ?, ?)", 20, 20, islandfile) db("COMMIT") return savegame
def generate_map(seed, map_size, water_percent, max_island_size, preferred_island_size, island_size_deviation): """ Generates a random map. @param seed: random number generator seed @param map_size: maximum map side length @param water_percent: minimum percent of map covered with water @param max_island_size: maximum island side length @param preferred_island_size: mean of island side lengths @param island_size_deviation: deviation of island side lengths @return: filename of the SQLite database containing the map """ max_island_size = min(max_island_size, map_size) rand = random.Random(_simplify_seed(seed)) min_island_size = 20 # minimum chosen island side length (the real size my be smaller) min_island_separation = 3 + map_size / 100 # minimum distance between two islands max_island_side_coefficient = 4 # maximum value of island's max(side length) / min(side length) islands = [] estimated_land = 0 max_land_amount = map_size * map_size * (100 - water_percent) / 100 trial_number = 0 while trial_number < 100: trial_number += 1 width = max(min_island_size, min(max_island_size, int(round(rand.gauss(preferred_island_size, island_size_deviation))))) side_coefficient = min(1 + abs(rand.gauss(0, 0.2)), max_island_side_coefficient) side_coefficient = side_coefficient if rand.randint(0, 1) else 1.0 / side_coefficient height = max(min_island_size, min(max_island_size, int(round(width * side_coefficient)))) size = width * height if estimated_land + size > max_land_amount: continue for _ in xrange(13): x = rand.randint(0, map_size - width) y = rand.randint(0, map_size - height) rect = Rect.init_from_topleft_and_size(x, y, width, height) blocked = False for existing_island in islands: if existing_island.distance_to_rect(rect) < min_island_separation: blocked = True break if not blocked: islands.append(rect) estimated_land += size trial_number = 0 break handle, filename = tempfile.mkstemp() os.close(handle) db = DbReader(filename) read_savegame_template(db) # move some of the islands to stretch the map to the right size if len(islands) > 1: min_top = min(rect.top for rect in islands) rect = rand.choice([rect for rect in islands if rect.top == min_top]) islands[islands.index(rect)] = Rect.init_from_borders(rect.left, rect.top - min_top, rect.right, rect.bottom - min_top) max_bottom = max(rect.bottom for rect in islands) rect = rand.choice([rect for rect in islands if rect.bottom == max_bottom]) shift = map_size - max_bottom - 1 islands[islands.index(rect)] = Rect.init_from_borders(rect.left, rect.top + shift, rect.right, rect.bottom + shift) min_left = min(rect.left for rect in islands) rect = rand.choice([rect for rect in islands if rect.left == min_left]) islands[islands.index(rect)] = Rect.init_from_borders(rect.left - min_left, rect.top, rect.right - min_left, rect.bottom) max_right = max(rect.right for rect in islands) rect = rand.choice([rect for rect in islands if rect.right == max_right]) shift = map_size - max_right - 1 islands[islands.index(rect)] = Rect.init_from_borders(rect.left + shift, rect.top, rect.right + shift, rect.bottom) for rect in islands: island_seed = rand.randint(-sys.maxint, sys.maxint) island_params = {'creation_method': 2, 'seed': island_seed, 'width': rect.width, 'height': rect.height} island_string = string.Template(_random_island_id_template).safe_substitute(island_params) db("INSERT INTO island (x, y, file) VALUES(?, ?, ?)", rect.left, rect.top, island_string) return filename
def _do_save(self, savegame): """Actual save code. @param savegame: absolute path""" assert os.path.isabs(savegame) self.log.debug("Session: Saving to %s", savegame) try: if os.path.exists(savegame): os.unlink(savegame) self.savecounter += 1 db = DbReader(savegame) except IOError as e: # usually invalid filename headline = _("Failed to create savegame file") descr = _( "There has been an error while creating your savegame file.") advice = _( "This usually means that the savegame name contains unsupported special characters." ) self.gui.show_error_popup(headline, descr, advice, unicode(e)) return self.save( ) # retry with new savegamename entered by the user # this must not happen with quicksave/autosave except OSError as e: if e.errno == errno.EACCES: self.gui.show_error_popup( _("Access is denied"), _("The savegame file could be read-only or locked by another process." )) return self.save() raise try: read_savegame_template(db) db("BEGIN") self.world.save(db) #self.manager.save(db) self.view.save(db) self.ingame_gui.save(db) self.scenario_eventhandler.save(db) LastActivePlayerSettlementManager().save(db) for instance in self.selected_instances: db("INSERT INTO selected(`group`, id) VALUES(NULL, ?)", instance.worldid) for group in xrange(len(self.selection_groups)): for instance in self.selection_groups[group]: db("INSERT INTO selected(`group`, id) VALUES(?, ?)", group, instance.worldid) rng_state = json.dumps(self.random.getstate()) SavegameManager.write_metadata(db, self.savecounter, rng_state) # make sure everything gets written now db("COMMIT") db.close() return True except: print "Save Exception" traceback.print_exc() db.close() # close db before delete os.unlink(savegame) # remove invalid savegamefile return False
def _do_save(self, savegame): """Actual save code. @param savegame: absolute path""" assert os.path.isabs(savegame) self.log.debug("Session: Saving to %s", savegame) try: if os.path.exists(savegame): os.unlink(savegame) self.savecounter += 1 db = DbReader(savegame) except IOError as e: # usually invalid filename headline = _("Failed to create savegame file") descr = _("There has been an error while creating your savegame file.") advice = _("This usually means that the savegame name contains unsupported special characters.") self.ingame_gui.show_error_popup(headline, descr, advice, unicode(e)) # retry with new savegamename entered by the user # (this must not happen with quicksave/autosave) return self.save() except OSError as e: if e.errno != errno.EACCES: raise self.ingame_gui.show_error_popup( _("Access is denied"), _("The savegame file could be read-only or locked by another process.") ) return self.save() try: read_savegame_template(db) db("BEGIN") self.world.save(db) self.view.save(db) self.ingame_gui.save(db) self.scenario_eventhandler.save(db) # Store instances that are selected right now. for instance in self.selected_instances: db("INSERT INTO selected (`group`, id) VALUES (NULL, ?)", instance.worldid) # If a single instance is selected, also store the currently displayed tab. # (Else, upon restoring, we display a multi-selection tab.) tabname = None if len(self.selected_instances) == 1: tabclass = self.ingame_gui.get_cur_menu().current_tab tabname = tabclass.__class__.__name__ db("INSERT INTO metadata (name, value) VALUES (?, ?)", "selected_tab", tabname) # Store user defined unit selection groups (Ctrl+number) for (number, group) in enumerate(self.selection_groups): for instance in group: db("INSERT INTO selected (`group`, id) VALUES (?, ?)", number, instance.worldid) # Store RNG state rng_state = json.dumps(self.random.getstate()) SavegameManager.write_metadata(db, self.savecounter, rng_state) # Make sure everything gets written now db("COMMIT") db.close() return True except Exception: self.log.error("Save Exception:") traceback.print_exc() # remove invalid savegamefile (but close db connection before deleting) db.close() os.unlink(savegame) return False