示例#1
0
    def _load_players(self, savegame_db, force_player_id):
        human_players = []
        for player_worldid, client_id in savegame_db(
                "SELECT rowid, client_id FROM player WHERE is_trader = 0 and is_pirate = 0 ORDER BY rowid"
        ):
            player = None
            # check if player is an ai
            ai_data = self.session.db(
                "SELECT class_package, class_name FROM ai WHERE client_id = ?",
                client_id)
            if ai_data:
                class_package, class_name = ai_data[0]
                # import ai class and call load on it
                module = importlib.import_module('horizons.ai.' +
                                                 class_package)
                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.globals.fife.get_uh_setting("ClientID"):
                self.player = player
            elif client_id is not None and not ai_data:
                # possible human player candidate with different client id
                human_players.append(player)
        self.owner_highlight_active = False
        self.health_visible_for_all_health_instances = False

        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]
            elif not human_players and self.players:
                # the first player should be the human-ai hybrid
                self.player = self.players[0]

        # set the human player to the forced value (debug option)
        self.set_forced_player(force_player_id)

        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.')
示例#2
0
    def setup_player(self, id, name, color, local):
        """Sets up a new Player instance and adds him to the active world.
		Only used for new games. Loading old players is done in _init().
		@param local: bool, whether the player is the one sitting on front of this machine."""
        inv = self.session.db.get_player_start_res()
        player = None
        if local:
            player = HumanPlayer(self.session, id, name, color, inventory=inv)
            self.player = player
            self.player.inventory.add_change_listener(self.session.ingame_gui.update_gold, \
                                                      call_listener_now=True)
        else:
            player = Player(self.session, id, name, color, inventory=inv)
        self.players.append(player)
示例#3
0
	def setup_player(self, id, name, color, clientid, local, is_ai, difficulty_level):
		"""Sets up a new Player instance and adds her to the active world.
		Only used for new games. Loading old players is done in _init().
		@param local: bool, whether the player is the one sitting on front of this machine."""
		inv = self.session.db.get_player_start_res()
		player = None
		if is_ai: # a human controlled AI player
			player = AIPlayer(self.session, id, name, color, clientid, difficulty_level)
		else:
			player = HumanPlayer(self.session, id, name, color, clientid, difficulty_level)
		player.initialize(inv)  # Componentholder init
		if local:
			self.player = player
		self.players.append(player)
示例#4
0
    def setup_player(self, id, name, color, local):
        """Sets up a new Player instance and adds him to the active world.
		@param local: bool, whether the player is the one sitting on front of this machine."""
        inv = self.session.db.get_player_start_res()
        player = None
        if local:
            player = HumanPlayer(self.session, id, name, color, inventory=inv)
            self.player = player
            self.session.ingame_gui.resbar.update_gold()
            self.player.inventory.add_change_listener(
                self.session.ingame_gui.resbar.update_gold)
        else:
            player = Player(self.session, id, name, color, inventory=inv)
        self.players.append(player)
示例#5
0
    def _load_players(self, savegame_db, force_player_id):
        human_players = []
        for player_worldid, client_id in savegame_db(
            "SELECT rowid, client_id FROM player WHERE is_trader = 0 and is_pirate = 0 ORDER BY rowid"
        ):
            player = None
            # check if player is an ai
            ai_data = self.session.db("SELECT class_package, class_name FROM ai WHERE client_id = ?", client_id)
            if ai_data:
                class_package, class_name = ai_data[0]
                # import ai class and call load on it
                module = __import__("horizons.ai." + class_package, fromlist=[str(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 not ai_data:
                # possible human player candidate with different client id
                human_players.append(player)
        self.owner_highlight_active = False
        self.health_visible_for_all_health_instances = False

        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]
            elif not human_players and self.players:
                # the first player should be the human-ai hybrid
                self.player = self.players[0]

                # set the human player to the forced value (debug option)
        self.set_forced_player(force_player_id)

        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."
            )
示例#6
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:
示例#7
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 and is_pirate = 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 not None:
			self.player.inventory.add_change_listener(self.session.ingame_gui.update_gold, \
			                                          call_listener_now=True)

		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


		# remove parts that are occupied by island
		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)

		# use a dict because it's directly supported by the pathfinding algo
		self.water = dict.fromkeys(list(self.ground_map), 1.0)

		# 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 = copy.copy(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[coord] = 1.0

		# 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)
			# there are 0 or 1 pirate AIs so this is safe
			pirate_data = savegame_db("SELECT rowid FROM player WHERE is_pirate = 1")
			if pirate_data:
				self.pirate = Pirate.load(self.session, savegame_db, pirate_data[0][0])

		# 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)
			# let pirate command it's ships. we have to do this here cause ships have to be
			# initialised for this, and pirate has to exist before ships are loaded.
			if self.pirate:
				self.pirate.load_ship_states(savegame_db)

		self.inited = True
		"""TUTORIAL:
示例#8
0
	def _init(self, savegame_db, force_player_id=None, disasters_enabled=True):
		"""
		@param savegame_db: Dbreader with loaded savegame database
		@param force_player_id: the worldid of the selected human player or default if None (debug option)
		"""
		"""
		All essential and non-essential parts of the world are set up here, you don't need to
		know everything that happens.
		"""
		#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 and is_pirate = 0 ORDER BY rowid"):
			player = None
			# check if player is an ai
			ai_data = self.session.db("SELECT class_package, class_name FROM ai WHERE client_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)
		self.owner_highlight_active = False
		self.health_visible_for_all_health_instances = False

		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]
			elif not human_players and self.players:
				# the first player should be the human-ai hybrid
				self.player = self.players[0]

		# set the human player to the forced value (debug option)
		self.set_forced_player(force_player_id)

		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.')

		# all static data
		self.load_raw_map(savegame_db)

		# 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)

		# use a dict because it's directly supported by the pathfinding algo
		self.water = dict.fromkeys(list(self.ground_map), 1.0)
		self._init_water_bodies()
		self.sea_number = self.water_body[(self.min_x, self.min_y)]

		# 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 = copy.copy(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[coord] = 1.0

		# create ship position list. entries: ship_map[(x, y)] = ship
		self.ship_map = {}
		self.ground_unit_map = {}

		# create shiplist, which is currently used for saving ships
		# and having at least one reference to them
		self.ships = []
		self.ground_units = []

		# create bullets list, used for saving bullets in ongoing attacks
		self.bullets = []

		if self.session.is_game_loaded():
			# there are 0 or 1 trader AIs so this is safe
			trader_data = savegame_db("SELECT rowid FROM player WHERE is_trader = 1")
			if trader_data:
				self.trader = Trader.load(self.session, savegame_db, trader_data[0][0])
			# there are 0 or 1 pirate AIs so this is safe
			pirate_data = savegame_db("SELECT rowid FROM player WHERE is_pirate = 1")
			if pirate_data:
				self.pirate = Pirate.load(self.session, savegame_db, pirate_data[0][0])

		# 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.
			if self.trader:
				self.trader.load_ship_states(savegame_db)

			# let pirate command it's ships. we have to do this here cause ships have to be
			# initialised for this, and pirate has to exist before ships are loaded.
			if self.pirate:
				self.pirate.load_ship_states(savegame_db)

			# load the AI stuff only when we have AI players
			if any(isinstance(player, AIPlayer) for player in self.players):
				AIPlayer.load_abstract_buildings(self.session.db) # TODO: find a better place for this

			# load the AI players
			# this has to be done here because otherwise the ships and other objects won't exist
			for player in self.players:
				if not isinstance(player, HumanPlayer):
					player.finish_loading(savegame_db)

		# load bullets
		if self.session.is_game_loaded():
			for (worldid, sx, sy, dx, dy, speed, img) in savegame_db("SELECT worldid, startx, starty, destx, desty, speed, image FROM bullet"):
				Bullet(img, Point(sx, sy), Point(dx, dy), speed, self.session, False, worldid)

		# load ongoing attacks
		if self.session.is_game_loaded():
			Weapon.load_attacks(self.session, savegame_db)

		# load diplomacy
		self.diplomacy = Diplomacy()
		if self.session.is_game_loaded():
			self.diplomacy.load(self, savegame_db)

		# add diplomacy notification listeners
		def notify_change(caller, old_state, new_state, a, b):
			player1 = u"%s" % a.name
			player2 = u"%s" % b.name

			data = {'player1' : player1, 'player2' : player2}

			self.session.ingame_gui.message_widget.add(
			  None, None, 'DIPLOMACY_STATUS_'+old_state.upper()+"_"+new_state.upper(), data)

		self.diplomacy.add_diplomacy_status_changed_listener(notify_change)

		disasters_disabled_by_properties = 'disasters_enabled' in self.properties and not self.properties['disasters_enabled']
		# if savegame or parameter disables disasters, it's disabled (both have to be set to enable to actually enable)
		disasters_disabled = not disasters_enabled or disasters_disabled_by_properties

		self.disaster_manager = DisasterManager(self.session, disabled=disasters_disabled)
		if self.session.is_game_loaded():
			self.disaster_manager.load(savegame_db)

		self.inited = True
		"""TUTORIAL:
示例#9
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 and is_pirate = 0 ORDER BY rowid"):
			player = None
			# check if player is an ai
			ai_data = self.session.db("SELECT class_package, class_name FROM ai WHERE client_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]
			elif not human_players and self.players:
				# the first player should be the human-ai hybrid
				self.player = self.players[0]

		if self.player is not None:
			self.player.inventory.add_change_listener(self.session.ingame_gui.update_gold, \
			                                          call_listener_now=True)

		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 = 0, 0, 0, 0
		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

		# 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

		# 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)

		# use a dict because it's directly supported by the pathfinding algo
		self.water = dict.fromkeys(list(self.ground_map), 1.0)
		self._init_water_bodies()
		self.sea_number = self.water_body[(self.min_x, self.min_y)]

		# 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 = copy.copy(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[coord] = 1.0

		# create ship position list. entries: ship_map[(x, y)] = ship
		self.ship_map = {}
		self.ground_unit_map = {}

		# create shiplist, which is currently used for saving ships
		# and having at least one reference to them
		self.ships = []
		self.ground_units = []

		# create bullets list, used for saving bullets in ongoing attacks
		self.bullets = []

		if self.session.is_game_loaded():
			# there are 0 or 1 trader AIs so this is safe
			trader_data = savegame_db("SELECT rowid FROM player WHERE is_trader = 1")
			if trader_data:
				self.trader = Trader.load(self.session, savegame_db, trader_data[0][0])
			# there are 0 or 1 pirate AIs so this is safe
			pirate_data = savegame_db("SELECT rowid FROM player WHERE is_pirate = 1")
			if pirate_data:
				self.pirate = Pirate.load(self.session, savegame_db, pirate_data[0][0])

		# 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.
			if self.trader:
				self.trader.load_ship_states(savegame_db)

			# let pirate command it's ships. we have to do this here cause ships have to be
			# initialised for this, and pirate has to exist before ships are loaded.
			if self.pirate:
				self.pirate.load_ship_states(savegame_db)

			# load the AI players
			# this has to be done here because otherwise the ships and other objects won't exist
			AIPlayer.load_abstract_buildings(self.session.db) # TODO: find a better place for this
			for player in self.players:
				if not isinstance(player, HumanPlayer):
					player.finish_loading(savegame_db)

		# load bullets
		if self.session.is_game_loaded():
			for (worldid, sx, sy, dx, dy, speed, img) in savegame_db("SELECT worldid, startx, starty, destx, desty, speed, image FROM bullet"):
				Bullet(img, Point(sx, sy), Point(dx, dy), speed, self.session, False, worldid)

		# load ongoing attacks
		if self.session.is_game_loaded():
			Weapon.load_attacks(self.session, savegame_db)

		# load diplomacy
		self.diplomacy = Diplomacy()
		if self.session.is_game_loaded():
			self.diplomacy.load(self, savegame_db)

		# add diplomacy notification listeners
		def notify_change(caller, change_type, a, b):
			player1 = a.name
			player2 = b.name

			#check if status really changed, if so update status string
			if change_type == 'friend':
				status = 'friends'
			elif change_type == 'enemy':
				status = 'enemies'
			else:
				status = 'neutral'

			self.session.ingame_gui.message_widget.add(self.max_x/2, self.max_y/2, 'DIPLOMACY_STATUS_CHANGED',
				{'player1' : player1, 'player2' : player2, 'status' : status})

		self.diplomacy.add_diplomacy_status_changed_listener(notify_change)

		self.inited = True
		"""TUTORIAL:
	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))]

		for x in xrange(self.min_x, self.max_x, 10):
			for y in xrange(self.min_y, self.max_y, 10):
				ground = default_grounds(self.session, x, y)
				# -5 to 5 to accomodate for nen shifted 10x10 tile graphic
				for x_offset in xrange(-5,6):
					for y_offset in xrange(-5,6):
						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]

		self.num_water = len(self.ground_map)
		self.water = list(self.ground_map)

		# 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.
			# BACTODO: disable trader
			#self.trader.load_ship_states(savegame_db)
			pass

		self.inited = True
		"""TUTORIAL: