Ejemplo n.º 1
0
    def save(self, db):
        """Saves the current game to the specified db.
		@param db: DbReader object of the db the game is saved to."""
        super(World, self).save(db)
        if isinstance(self.map_name, list):
            db("INSERT INTO metadata VALUES(?, ?)", 'random_island_sequence',
               ' '.join(self.map_name))
        else:
            db("INSERT INTO metadata VALUES(?, ?)", 'map_name', self.map_name)

        for island in self.islands:
            island.save(db)
        for player in self.players:
            player.save(db)
        if self.trader is not None:
            self.trader.save(db)
        if self.pirate is not None:
            self.pirate.save(db)
        for unit in self.ships + self.ground_units:
            unit.save(db)
        for bullet in self.bullets:
            bullet.save(db)
        self.diplomacy.save(db)
        Weapon.save_attacks(db)
        self.disaster_manager.save(db)
Ejemplo n.º 2
0
	def save(self, db):
		"""Saves the current game to the specified db.
		@param db: DbReader object of the db the game is saved to."""
		super(World, self).save(db)
		if isinstance(self.map_name, list):
			db("INSERT INTO metadata VALUES(?, ?)", 'random_island_sequence', ' '.join(self.map_name))
		else:
			# the map name has to be simplified because the absolute paths won't be transferable between machines
			simplified_name = self.map_name
			if self.map_name.startswith(PATHS.USER_MAPS_DIR):
				simplified_name = 'USER_MAPS_DIR:' + simplified_name[len(PATHS.USER_MAPS_DIR):]
			db("INSERT INTO metadata VALUES(?, ?)", 'map_name', simplified_name)

		for island in self.islands:
			island.save(db)
		for player in self.players:
			player.save(db)
		if self.trader is not None:
			self.trader.save(db)
		if self.pirate is not None:
			self.pirate.save(db)
		for unit in self.ships + self.ground_units:
			unit.save(db)
		for bullet in self.bullets:
			bullet.save(db)
		self.diplomacy.save(db)
		Weapon.save_attacks(db)
		self.disaster_manager.save(db)
Ejemplo n.º 3
0
    def save(self, db):
        """Saves the current game to the specified db.
		@param db: DbReader object of the db the game is saved to."""
        super().save(db)
        if isinstance(self.map_name, list):
            db("INSERT INTO metadata VALUES(?, ?)", 'random_island_sequence',
               ' '.join(self.map_name))
        else:
            # the map name has to be simplified because the absolute paths won't be transferable between machines
            simplified_name = self.map_name
            if self.map_name.startswith(PATHS.USER_MAPS_DIR):
                simplified_name = 'USER_MAPS_DIR:' + simplified_name[
                    len(PATHS.USER_MAPS_DIR):]
            db("INSERT INTO metadata VALUES(?, ?)", 'map_name',
               simplified_name)

        for island in self.islands:
            island.save(db)
        for player in self.players:
            player.save(db)
        if self.trader is not None:
            self.trader.save(db)
        if self.pirate is not None:
            self.pirate.save(db)
        for unit in self.ships + self.ground_units:
            unit.save(db)
        self.diplomacy.save(db)
        Weapon.save_attacks(db)
        self.disaster_manager.save(db)
Ejemplo n.º 4
0
	def _load_combat(self, 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)
Ejemplo n.º 5
0
    def _load_combat(self, 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)
Ejemplo n.º 6
0
 def load(self, db, worldid):
     super(WeaponHolder, self).load(db, worldid)
     self.__init()
     weapons = db(
         "SELECT weapon_id, number, remaining_ticks FROM weapon_storage WHERE owner_id = ?",
         worldid)
     for weapon_id, number, ticks in weapons:
         # create weapon and add to storage manually
         if self.session.db.get_weapon_stackable(weapon_id):
             weapon = StackableWeapon(self.session, weapon_id)
             weapon.set_number_of_weapons(number)
         else:
             weapon = Weapon(self.session, weapon_id)
         self._weapon_storage.append(weapon)
         # if weapon not ready add scheduled call and remove from fireable
         if ticks:
             weapon.attack_ready = False
             Scheduler().add_new_object(weapon.make_attack_ready, weapon,
                                        ticks)
         else:
             self._fireable.append(weapon)
         weapon.add_weapon_fired_listener(
             Callback(self._remove_from_fireable, weapon))
         weapon.add_attack_ready_listener(
             Callback(self._add_to_fireable, weapon))
         weapon.add_weapon_fired_listener(
             self._increase_fired_weapons_number)
     self.on_storage_modified()
     # load target after all objects have been loaded
     Scheduler().add_new_object(Callback(self.load_target, db),
                                self,
                                run_in=0)
     self.log.debug("%s weapon storage after load: %s", self,
                    self._weapon_storage)
Ejemplo n.º 7
0
	def save(self, db):
		"""Saves the current game to the specified db.
		@param db: DbReader object of the db the game is saved to."""
		super(World, self).save(db)
		for name, value in self.properties.iteritems():
			db("INSERT INTO map_properties (name, value) VALUES (?, ?)", name, json.dumps(value))
		for island in self.islands:
			island.save(db)
		for player in self.players:
			player.save(db)
		if self.trader is not None:
			self.trader.save(db)
		if self.pirate is not None:
			self.pirate.save(db)
		for unit in self.ships + self.ground_units:
			unit.save(db)
		for bullet in self.bullets:
			bullet.save(db)
		self.diplomacy.save(db)
		Weapon.save_attacks(db)
		self.disaster_manager.save(db)
Ejemplo n.º 8
0
	def save(self, db):
		"""Saves the current game to the specified db.
		@param db: DbReader object of the db the game is saved to."""
		super(World, self).save(db)
		if isinstance(self.map_name, list):
			db("INSERT INTO metadata VALUES(?, ?)", 'random_island_sequence', ' '.join(self.map_name))
		else:
			db("INSERT INTO metadata VALUES(?, ?)", 'map_name', self.map_name)

		for island in self.islands:
			island.save(db)
		for player in self.players:
			player.save(db)
		if self.trader is not None:
			self.trader.save(db)
		if self.pirate is not None:
			self.pirate.save(db)
		for unit in self.ships + self.ground_units:
			unit.save(db)
		for bullet in self.bullets:
			bullet.save(db)
		self.diplomacy.save(db)
		Weapon.save_attacks(db)
		self.disaster_manager.save(db)
Ejemplo n.º 9
0
    def add_weapon_to_storage(self, weapon_id):
        """
		adds weapon to storage
		@param weapon_id : id of the weapon to be added
		"""
        self.log.debug("%s add weapon %s", self, weapon_id)
        #if weapon is stackable, try to stack
        weapon = None
        if self.equipped_weapon_number == self.total_number_of_weapons:
            self.log.debug("%s weapon storage full", self)
            return False
        if self.session.db.get_weapon_stackable(weapon_id):
            stackable = [
                w for w in self._weapon_storage if weapon_id == w.weapon_id
            ]
            #try to increase the number of weapons for one stackable weapon
            increased = False
            for weapon in stackable:
                try:
                    weapon.increase_number_of_weapons(1)
                    increased = True
                    break
                except SetStackableWeaponNumberError:
                    continue

            if not increased:
                weapon = StackableWeapon(self.session, weapon_id)
        else:
            weapon = Weapon(self.session, weapon_id)
        if weapon:
            self._weapon_storage.append(weapon)
            weapon.add_weapon_fired_listener(
                Callback(self._remove_from_fireable, weapon))
            weapon.add_attack_ready_listener(
                Callback(self._add_to_fireable, weapon))
            weapon.add_weapon_fired_listener(
                self._increase_fired_weapons_number)
            self._fireable.append(weapon)
            self.equipped_weapon_number += 1
        self.on_storage_modified()  # will update the range
        return True
Ejemplo n.º 10
0
 def _load_combat(self, savegame_db):
     # load ongoing attacks
     if self.session.is_game_loaded():
         Weapon.load_attacks(self.session, savegame_db)
Ejemplo n.º 11
0
	def _load_combat(self, savegame_db):
		# load ongoing attacks
		if self.session.is_game_loaded():
			Weapon.load_attacks(self.session, savegame_db)
Ejemplo n.º 12
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:
Ejemplo n.º 13
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: