Exemple #1
0
	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
Exemple #2
0
    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: