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] = json.loads(value) if 'disasters_enabled' not in self.properties: # set on first init self.properties['disasters_enabled'] = disasters_enabled self._load_players(savegame_db, force_player_id) # all static data LoadingProgress.broadcast(self, 'world_load_map') self.load_raw_map(savegame_db) # load world buildings (e.g. fish) LoadingProgress.broadcast(self, 'world_load_buildings') buildings = savegame_db( "SELECT rowid, type FROM building WHERE location = ?", self.worldid) for (building_worldid, building_typeid) in buildings: load_building(self.session, savegame_db, building_typeid, building_worldid) # use a dict because it's directly supported by the pathfinding algo LoadingProgress.broadcast(self, 'world_init_water') self.water = {tile: 1.0 for tile in self.ground_map} self._init_water_bodies() self.sea_number = self.water_body[(self.min_x, self.min_y)] for island in self.islands: island.terrain_cache.create_sea_cache() # 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.items(): if 'coastline' in tile.classes or 'constructible' not in tile.classes: self.water_and_coastline[coord] = 1.0 self._init_shallow_water_bodies() self.shallow_sea_number = self.shallow_water_body[(self.min_x, self.min_y)] # create ship position list. entries: ship_map[(x, y)] = ship self.ship_map = {} self.ground_unit_map = {} 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) LoadingProgress.broadcast(self, 'world_load_units') 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 and pirate command their ships. we have to do this here # because ships have to be initialized for this, and they have # to exist before ships are loaded. if self.trader: self.trader.load_ship_states(savegame_db) if self.pirate: self.pirate.finish_loading(savegame_db) # load the AI stuff only when we have AI players LoadingProgress.broadcast(self, 'world_setup_ai') 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) LoadingProgress.broadcast(self, 'world_load_stuff') self._load_combat(savegame_db) self._load_diplomacy(savegame_db) self._load_disasters(savegame_db) self.inited = True """TUTORIAL:
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] = json.loads(value) if not 'disasters_enabled' in self.properties: # set on first init self.properties['disasters_enabled'] = disasters_enabled # create playerlist self.players = [] self.player = None # player sitting in front of this machine self.trader = None self.pirate = None self._load_players(savegame_db, force_player_id) # all static data LoadingProgress.broadcast(self, 'world_load_map') self.load_raw_map(savegame_db) # load world buildings (e.g. fish) LoadingProgress.broadcast(self, 'world_load_buildings') 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 LoadingProgress.broadcast(self, 'world_init_water') self.water = dict((tile, 1.0) for tile in self.ground_map) self._init_water_bodies() self.sea_number = self.water_body[(self.min_x, self.min_y)] for island in self.islands: island.terrain_cache.create_sea_cache() # 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 self._init_shallow_water_bodies() self.shallow_sea_number = self.shallow_water_body[(self.min_x, self.min_y)] # 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) LoadingProgress.broadcast(self, 'world_load_units') 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 and pirate command their ships. we have to do this here # because ships have to be initialized for this, and they have # to exist before ships are loaded. if self.trader: self.trader.load_ship_states(savegame_db) if self.pirate: self.pirate.finish_loading(savegame_db) # load the AI stuff only when we have AI players LoadingProgress.broadcast(self, 'world_setup_ai') 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) LoadingProgress.broadcast(self, 'world_load_stuff') self._load_combat(savegame_db) self._load_diplomacy(savegame_db) self._load_disasters(savegame_db) 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))] # 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:
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:
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:
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: