def load_raw_map(self, savegame_db, preview=False): self.map_name = savegame_db.map_name # Load islands. for (islandid,) in savegame_db("SELECT DISTINCT island_id + 1001 FROM ground"): island = Island(savegame_db, islandid, self.session, preview=preview) self.islands.append(island) # Calculate map dimensions. self.min_x, self.min_y, self.max_x, self.max_y = 0, 0, 0, 0 for island in self.islands: self.min_x = min(island.position.left, self.min_x) self.min_y = min(island.position.top, self.min_y) self.max_x = max(island.position.right, self.max_x) self.max_y = max(island.position.bottom, self.max_y) self.min_x -= savegame_db.map_padding self.min_y -= savegame_db.map_padding self.max_x += savegame_db.map_padding self.max_y += savegame_db.map_padding self.map_dimensions = Rect.init_from_borders(self.min_x, self.min_y, self.max_x, self.max_y) # Add water. self.log.debug("Filling world with water...") self.ground_map = {} # big sea water tile class if not preview: default_grounds = Entities.grounds[self.properties.get('default_ground', '%d-straight' % GROUND.WATER[0])] fake_tile_class = Entities.grounds['-1-special'] fake_tile_size = 10 for x in xrange(self.min_x-MAP.BORDER, self.max_x+MAP.BORDER, fake_tile_size): for y in xrange(self.min_y-MAP.BORDER, self.max_y+MAP.BORDER, fake_tile_size): fake_tile_x = x - 1 fake_tile_y = y + fake_tile_size - 1 if not preview: # we don't need no references, we don't need no mem control default_grounds(self.session, fake_tile_x, fake_tile_y) for x_offset in xrange(fake_tile_size): if self.min_x <= x + x_offset < self.max_x: for y_offset in xrange(fake_tile_size): if self.min_y <= y + y_offset < self.max_y: self.ground_map[(x+x_offset, y+y_offset)] = fake_tile_class(self.session, fake_tile_x, fake_tile_y) self.fake_tile_map = copy.copy(self.ground_map) # Remove parts that are occupied by islands, create the island map and the full map. self.island_map = {} self.full_map = copy.copy(self.ground_map) for island in self.islands: for coords in island.ground_map: if coords in self.ground_map: self.full_map[coords] = island.ground_map[coords] del self.ground_map[coords] self.island_map[coords] = island
def _init(self, savegame_db): """ @param savegame_db: Dbreader with loaded savegame database """ #load properties self.properties = {} for (name, value) in savegame_db("SELECT name, value FROM map_properties"): self.properties[name] = value # create playerlist self.players = [] self.player = None # player sitting in front of this machine self.trader = None self.pirate = None # load player human_players = [] for player_worldid, client_id in savegame_db( "SELECT rowid, client_id FROM player WHERE is_trader = 0"): player = None # check if player is an ai ai_data = self.session.db( "SELECT class_package, class_name FROM ai WHERE id = ?", client_id) if len(ai_data) > 0: class_package, class_name = ai_data[0] # import ai class and call load on it module = __import__('horizons.ai.' + class_package, fromlist=[class_name]) ai_class = getattr(module, class_name) player = ai_class.load(self.session, savegame_db, player_worldid) else: # no ai player = HumanPlayer.load(self.session, savegame_db, player_worldid) self.players.append(player) if client_id == horizons.main.fife.get_uh_setting("ClientID"): self.player = player elif client_id is not None and len(ai_data) == 0: # possible human player candidate with different client id human_players.append(player) if self.player is None: # we have no human player. # check if there is only one player with an id (i.e. human player) # this would be the case if the savegame originates from a different installation. # if there's more than one of this kind, we can't be sure what to select. # TODO: create interface for selecting player, if we want this if (len(human_players) == 1): # exactly one player, we can quite safely use this one self.player = human_players[0] if self.player is None and self.session.is_game_loaded(): self.log.warning( 'WARNING: Cannot autoselect a player because there are no \ or multiple candidates.') # load islands self.islands = [] for (islandid, ) in savegame_db("SELECT rowid + 1000 FROM island"): island = Island(savegame_db, islandid, self.session) self.islands.append(island) #calculate map dimensions self.min_x, self.min_y, self.max_x, self.max_y = None, None, None, None for i in self.islands: self.min_x = i.rect.left if self.min_x is None or i.rect.left < self.min_x else self.min_x self.min_y = i.rect.top if self.min_y is None or i.rect.top < self.min_y else self.min_y self.max_x = i.rect.right if self.max_x is None or i.rect.right > self.max_x else self.max_x self.max_y = i.rect.bottom if self.max_y is None or i.rect.bottom > self.max_y else self.max_y self.min_x -= 10 self.min_y -= 10 self.max_x += 10 self.max_y += 10 self.map_dimensions = Rect.init_from_borders(self.min_x, self.min_y, self.max_x, self.max_y) #add water self.log.debug("Filling world with water...") self.ground_map = {} default_grounds = Entities.grounds[int( self.properties.get('default_ground', GROUND.WATER))] # extra world size that is added so that he player can't see the "black void" border = 30 for x in xrange(self.min_x - border, self.max_x + border, 10): for y in xrange(self.min_y - border, self.max_y + border, 10): ground = default_grounds(self.session, x, y) for x_offset in xrange(0, 10): if x + x_offset < self.max_x and x + x_offset >= self.min_x: for y_offset in xrange(0, 10): if y + y_offset < self.max_y and y + y_offset >= self.min_y: self.ground_map[(x + x_offset, y + y_offset)] = ground # "unfill" parts that are occupied by island # TODO: check if constructing a list of water coords is faster than calling the Ground() so many times for island in self.islands: for coord in island.ground_map: if coord in self.ground_map: del self.ground_map[coord] # load world buildings (e.g. fish) for (building_worldid, building_typeid) in \ savegame_db("SELECT rowid, type FROM building WHERE location = ?", self.worldid): load_building(self.session, savegame_db, building_typeid, building_worldid) self.water = list(self.ground_map) # assemble list of water and coastline for ship, that can drive through shallow water # NOTE: this is rather a temporary fix to make the fisher be able to move # since there are tile between coastline and deep sea, all non-constructible tiles # are added to this list as well, which will contain a few too many self.water_and_coastline = self.water[:] for island in self.islands: for coord, tile in island.ground_map.iteritems(): if 'coastline' in tile.classes or 'constructible' not in tile.classes: self.water_and_coastline.append(coord) # create ship position list. entries: ship_map[(x, y)] = ship self.ship_map = {} # create shiplist, which is currently used for saving ships # and having at least one reference to them self.ships = [] if self.session.is_game_loaded(): # for now, we have one trader in every game, so this is safe: trader_id = savegame_db( "SELECT rowid FROM player WHERE is_trader = 1")[0][0] self.trader = Trader.load(self.session, savegame_db, trader_id) # load all units (we do it here cause all buildings are loaded by now) for (worldid, typeid ) in savegame_db("SELECT rowid, type FROM unit ORDER BY rowid"): Entities.units[typeid].load(self.session, savegame_db, worldid) if self.session.is_game_loaded(): # let trader command it's ships. we have to do this here cause ships have to be # initialised for this, and trader has to exist before ships are loaded. self.trader.load_ship_states(savegame_db) self.inited = True """TUTORIAL: