def test_combat_save_load(): """ create a savegame with combat units and actual combat, then save/load it """ session, player = new_session() (p0, s0), (p1, s1) = setup_combat(session, UNITS.FRIGATE) s0_worldid, s1_worldid = s0.worldid, s1.worldid session.run(seconds=1) # saveload session = saveload(session) s0 = WorldObject.get_object_by_id(s0_worldid) s1 = WorldObject.get_object_by_id(s1_worldid) # fight AddEnemyPair(p0, p1).execute(session) Attack(s0, s1).execute(session) Attack(s1, s0).execute(session) session.run(seconds=20) # saveload session = saveload(session) assert one_dead(s0_worldid, s1_worldid) session.end()
def test(session, _): """Let 2 AI players play for four minutes.""" session.run(seconds = 4 * 60) assert session.world.settlements # simple test for luck: storages are known to easily break on remove: for settlement in session.world.settlements: for stor in settlement.get_buildings_by_id(BUILDINGS.STORAGE_CLASS): wid = stor.worldid Tear(stor)(stor.owner) try: WorldObject.get_object_by_id(wid) except WorldObjectNotFound: pass else: assert False session.run(seconds = 4) # for the heck of it, tear the rest as well for settlement in session.world.settlements: for building in settlement.buildings[:]: if building.id != BUILDINGS.WAREHOUSE_CLASS: Tear(building)(building.owner) assert len(settlement.buildings) == 1 session.run(seconds = 60)
def load(self, db): data = db('SELECT value FROM last_active_settlement WHERE type = "PLAYER"') self._last_player_settlement = weakref.ref(WorldObject.get_object_by_id(data[0][0])) if data else None data = db('SELECT value FROM last_active_settlement WHERE type = "ANY"') self._cur_settlement = weakref.ref(WorldObject.get_object_by_id(data[0][0])) if data else None data = db('SELECT value FROM last_active_settlement WHERE type = "LAST_NONE_FLAG"') self._last_player_settlement_hovered_was_none = bool(data[0][0])
def _load(self, db, worldid, success_callback, failure_callback): db_result = db( "SELECT source_settlement_manager, destination_settlement_manager, ship, state FROM ai_mission_special_domestic_trade WHERE rowid = ?", worldid)[0] self.source_settlement_manager = WorldObject.get_object_by_id( db_result[0]) self.destination_settlement_manager = WorldObject.get_object_by_id( db_result[1]) self.state = self.missionStates[db_result[3]] super(SpecialDomesticTrade, self).load(db, worldid, success_callback, failure_callback, WorldObject.get_object_by_id(db_result[2])) if self.state is self.missionStates.moving_to_source_settlement: self.ship.add_move_callback( Callback(self._reached_source_settlement)) self.ship.add_blocked_callback( Callback(self._move_to_source_settlement)) elif self.state is self.missionStates.moving_to_destination_settlement: self.ship.add_move_callback( Callback(self._reached_destination_settlement)) self.ship.add_blocked_callback( Callback(self._move_to_destination_settlement)) else: assert False, 'invalid state'
def load_selection(self, db): # Re-select old selected instance for (instance_id, ) in db("SELECT id FROM selected WHERE `group` IS NULL"): obj = WorldObject.get_object_by_id(instance_id) self.session.selected_instances.add(obj) obj.get_component(SelectableComponent).select() # Re-show old tab (if there was one) or multiselection if len(self.session.selected_instances) == 1: tabname = db("SELECT value FROM metadata WHERE name = ?", 'selected_tab')[0][0] # This can still be None due to old savegames not storing the information tabclass = None if tabname is None else resolve_tab(tabname) obj.get_component(SelectableComponent).show_menu( jump_to_tabclass=tabclass) elif self.session.selected_instances: self.show_multi_select_tab(self.session.selected_instances) # Load user defined unit selection groups (Ctrl+number) for (num, group) in enumerate(self.session.selection_groups): for (instance_id, ) in db( "SELECT id FROM selected WHERE `group` = ?", num): obj = WorldObject.get_object_by_id(instance_id) group.add(obj)
def _load(self, db, worldid, success_callback, failure_callback): db_result = db( "SELECT settlement_manager, settlement, ship, bought_resource, sold_resource, state FROM ai_mission_international_trade WHERE rowid = ?", worldid)[0] self.settlement_manager = WorldObject.get_object_by_id(db_result[0]) self.settlement = WorldObject.get_object_by_id(db_result[1]) self.bought_resource = db_result[3] self.sold_resource = db_result[4] self.state = self.missionStates[db_result[5]] super(InternationalTrade, self).load(db, worldid, success_callback, failure_callback, WorldObject.get_object_by_id(db_result[2])) if self.state is self.missionStates.moving_to_my_settlement: self.ship.add_move_callback(Callback(self._reached_my_settlement)) self.ship.add_blocked_callback( Callback(self._move_to_my_settlement)) elif self.state is self.missionStates.moving_to_other_settlement: self.ship.add_move_callback( Callback(self._reached_other_settlement)) self.ship.add_blocked_callback( Callback(self._move_to_other_settlement)) elif self.state is self.missionStates.returning_to_my_settlement: self.ship.add_move_callback( Callback(self._returned_to_my_settlement)) self.ship.add_blocked_callback( Callback(self._return_to_my_settlement)) else: assert False, 'invalid state'
def one_dead(wid1, wid2): for wid in (wid1, wid2): at_least_one_dead = False try: WorldObject.get_object_by_id(wid) except WorldObjectNotFound: at_least_one_dead = True return at_least_one_dead
def load(self, db): self.message_widget.load(db) self.logbook.load(db) self.resource_overview.load(db) if self.session.is_game_loaded(): LastActivePlayerSettlementManager().load(db) cur_settlement = LastActivePlayerSettlementManager().get_current_settlement() self.cityinfo.set_settlement(cur_settlement) self.minimap.draw() # update minimap to new world self.current_cursor = 'default' self.cursor = mousetools.SelectionTool(self.session) # Set cursor correctly, menus might need to be opened. # Open menus later; they may need unit data not yet inited self.cursor.apply_select() # Re-select old selected instance for (instance_id, ) in db("SELECT id FROM selected WHERE `group` IS NULL"): obj = WorldObject.get_object_by_id(instance_id) self.session.selected_instances.add(obj) obj.get_component(SelectableComponent).select() # Re-show old tab (if there was one) or multiselection if len(self.session.selected_instances) == 1: tabname = db("SELECT value FROM metadata WHERE name = ?", 'selected_tab')[0][0] # This can still be None due to old savegames not storing the information tabclass = None if tabname is None else resolve_tab(tabname) obj.get_component(SelectableComponent).show_menu(jump_to_tabclass=tabclass) elif self.session.selected_instances: self.show_multi_select_tab(self.session.selected_instances) # Load user defined unit selection groups (Ctrl+number) for (num, group) in enumerate(self.session.selection_groups): for (instance_id, ) in db("SELECT id FROM selected WHERE `group` = ?", num): obj = WorldObject.get_object_by_id(instance_id) group.add(obj) if not self.session.is_game_loaded(): # Fire a message for new world creation self.message_widget.add('NEW_WORLD') # Show message when the relationship between players changed 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} string_id = 'DIPLOMACY_STATUS_{old}_{new}'.format(old=old_state.upper(), new=new_state.upper()) self.message_widget.add(string_id=string_id, message_dict=data) self.session.world.diplomacy.add_diplomacy_status_changed_listener(notify_change)
def _load(self, db, worldid, success_callback, failure_callback): db_result = db("SELECT land_manager, ship, x, y, state FROM ai_mission_found_settlement WHERE rowid = ?", worldid)[0] self.land_manager = WorldObject.get_object_by_id(db_result[0]) self.coords = (int(db_result[2]), int(db_result[3])) self.warehouse = None self.state = self.missionStates[db_result[4]] super(FoundSettlement, self).load(db, worldid, success_callback, failure_callback, WorldObject.get_object_by_id(db_result[1])) if self.state == self.missionStates.moving: self.ship.add_move_callback(Callback(self._reached_destination_area)) self.ship.add_blocked_callback(Callback(self._move_to_destination_area)) else: assert False, 'invalid state'
def load_location(self, db, worldid): """ Does not alter self, just gets island and settlement from a savegame. @return: tuple: (island, settlement) """ location_obj = WorldObject.get_object_by_id(db.get_building_location(worldid)) if isinstance(location_obj, Settlement): # workaround: island can't be fetched from world, because it isn't fully constructed island = WorldObject.get_object_by_id(db.get_settlement_island(location_obj.worldid)) settlement = location_obj else: # loc is island island = location_obj settlement = None return (island, settlement)
def _load(self, db, worldid, success_callback, failure_callback): db_result = db("SELECT settlement_manager, ship, feeder_island, state FROM ai_mission_prepare_foundation_ship WHERE rowid = ?", worldid)[0] self.settlement_manager = WorldObject.get_object_by_id(db_result[0]) self.warehouse = self.settlement_manager.settlement.warehouse self.feeder_island = db_result[2] self.state = self.missionStates[db_result[3]] super(PrepareFoundationShip, self).load(db, worldid, success_callback, failure_callback, WorldObject.get_object_by_id(db_result[1])) if self.state == self.missionStates.moving: self.ship.add_move_callback(Callback(self._reached_destination_area)) self.ship.add_blocked_callback(Callback(self._move_to_destination_area)) else: assert False, 'invalid state'
def _load(self, db, worldid, success_callback, failure_callback): db_result = db("SELECT source_settlement_manager, destination_settlement_manager, ship, state FROM ai_mission_domestic_trade WHERE rowid = ?", worldid)[0] self.source_settlement_manager = WorldObject.get_object_by_id(db_result[0]) self.destination_settlement_manager = WorldObject.get_object_by_id(db_result[1]) self.state = self.missionStates[db_result[3]] super(DomesticTrade, self).load(db, worldid, success_callback, failure_callback, WorldObject.get_object_by_id(db_result[2])) if self.state == self.missionStates.moving_to_source_warehouse: self.ship.add_move_callback(Callback(self._reached_source_warehouse_area)) self.ship.add_blocked_callback(Callback(self._move_to_source_warehouse_area)) elif self.state == self.missionStates.moving_to_destination_warehouse: self.ship.add_move_callback(Callback(self._reached_destination_warehouse_area)) self.ship.add_blocked_callback(Callback(self._move_to_destination_warehouse_area)) else: assert False, 'invalid state'
def load(self, db, worldid): self.island, self.settlement = self.load_location(db, worldid) x, y, location, rotation, level = db.get_building_row(worldid) owner_id = db.get_settlement_owner(location) owner = None if owner_id is None else WorldObject.get_object_by_id(owner_id) # early init before super() call self.__pre_init(owner, rotation, Point(x, y), level=level) super(BasicBuilding, self).load(db, worldid) remaining_ticks_of_month = None if self.has_running_costs: db_data = db("SELECT ticks FROM remaining_ticks_of_month WHERE rowid=?", worldid) if not db_data: # this can happen when running costs are set when there were no before # we shouldn't crash because of changes in yaml code, still it's suspicious self.log.warning('Object %s of type %s does not know when to pay its rent.\n' 'Disregard this when loading old savegames or on running cost changes.', self.worldid, self.id) remaining_ticks_of_month = 1 else: remaining_ticks_of_month = db_data[0][0] self.__init(remaining_ticks_of_month=remaining_ticks_of_month) # island.add_building handles registration of building for island and settlement self.island.add_building(self, self.owner, load=True)
def fix_job_object(): # resolve worldid to object later if self.job: if self.job.object == -1: self.job.object = None else: self.job.object = WorldObject.get_object_by_id( self.job.object )
def transfer_to_storageholder(self, amount, res_id, transfer_to, signal_errors=False): """Transfers amount of res_id to transfer_to. @param transfer_to: worldid or object reference @param signal_errors: whether to play an error sound in case the transfer completely failed (no res transferred) @return: amount that was actually transferred (NOTE: this is different from the return value of inventory.alter, since here are 2 storages involved) """ try: transfer_to = WorldObject.get_object_by_id(int(transfer_to)) except TypeError: # transfer_to not an int, assume already obj pass # take res from self ret = self.get_component(StorageComponent).inventory.alter( res_id, -amount) # check if we were able to get the planned amount ret = amount if amount < abs(ret) else abs(ret) # put res to transfer_to ret = transfer_to.get_component(StorageComponent).inventory.alter( res_id, amount - ret) self.get_component(StorageComponent).inventory.alter( res_id, ret) # return resources that did not fit actually_transfered = amount - ret if signal_errors and actually_transfered == 0: AmbientSoundComponent.play_special('error') return actually_transfered
def load(self, db, worldid): super().load(db, worldid) # get own properties health, can_reproduce = db.get_wildanimal_row(worldid) # get home island island = WorldObject.get_object_by_id(db.get_unit_owner(worldid)) self.__init(island, bool(can_reproduce), health)
def _load(self, db, owner, worldid): self.owner = owner super(SettlementManager, self).load(db, worldid) # load the main part land_manager_id = db("SELECT land_manager FROM ai_settlement_manager WHERE rowid = ?", worldid)[0][0] land_manager = WorldObject.get_object_by_id(land_manager_id) # find the settlement for settlement in self.owner.session.world.settlements: if settlement.owner == self.owner and settlement.island == land_manager.island: land_manager.settlement = settlement break assert land_manager.settlement self.resource_manager = ResourceManager.load(db, self) self.trade_manager = TradeManager.load(db, self) self.__init(land_manager) # load the master builders self.village_builder = VillageBuilder.load(db, self) self.production_builder = ProductionBuilder.load(db, self) self.village_builder.display() self.production_builder.display() self.__init_goals() # the add_building events happen before the settlement manager is loaded so they have to be repeated here for building in self.settlement.buildings: self.add_building(building)
def load(self, db, worldid): super(BuildingInfluencingDisaster, self).load(db, worldid) for building_id, ticks in db("SELECT building, remaining_ticks_havoc FROM building_influencing_disaster WHERE disaster = ?", worldid): # do half of infect() building = WorldObject.get_object_by_id(building_id) self.log.debug("%s loading disaster %s", self, building) self.infect(building, load=(db, worldid))
def load(self, db, worldid): super(WildAnimal, self).load(db, worldid) # get own properties health, can_reproduce = db.get_wildanimal_row(worldid) # get home island island = WorldObject.get_object_by_id(db.get_unit_owner(worldid)) self.__init(island, bool(can_reproduce), health)
def fix_job_object(): # resolve worldid to object later if self.job: if self.job.object == -1: self.job.object = None # e.g. when hunters have killed their prey else: self.job.object = WorldObject.get_object_by_id(self.job.object)
def __call__(self, issuer): """Execute the command @param issuer: the issuer of the command """ try: building = WorldObject.get_object_by_id(self.building) except WorldObjectNotFound: self.log.debug("Tear: building %s already gone, not tearing it again.", self.building) return # invalid command, possibly caused by mp delay if building is None or building.fife_instance is None: self.log.error("Tear: attempting to tear down a building that shouldn't exist %s", building) elif building.id in BUILDINGS.EXPAND_RANGE: building_to_destroy = len(self.destroyable_buildings(building.position, building.settlement)[0]) if building_to_destroy == 0: self.log.debug("Tear: tearing down %s", building) building.remove() elif building_to_destroy == 1: title = _("Destroy all buildings") msg = _("This will destroy all the buildings that fall outside of the settlement range.\n\n1 additional building will be destroyed") should_abandon = building.session.ingame_gui.show_popup(title, msg, show_cancel_button=True) if should_abandon: self.log.debug("Tear: tearing down %s", building) building.remove() else: title = _("Destroy all buildings") msg = _("This will destroy all the buildings that fall outside of the settlement range.\n\n%s additional buildings will be destroyed" %building_to_destroy) should_abandon = building.session.ingame_gui.show_popup(title, msg, show_cancel_button=True) if should_abandon: self.log.debug("Tear: tearing down %s", building) building.remove() else: self.log.debug("Tear: tearing down %s", building) building.remove()
def load(self, db, worldid): self.island, self.settlement = self.load_location(db, worldid) x, y, location, rotation, level = db.get_building_row(worldid) owner_id = db.get_settlement_owner(location) owner = None if owner_id is None else WorldObject.get_object_by_id(owner_id) # early init before super() call self.__pre_init(owner, rotation, Point(x, y), level=level) super().load(db, worldid) remaining_ticks_of_month = None if self.has_running_costs: db_data = db("SELECT ticks FROM remaining_ticks_of_month WHERE rowid=?", worldid) if not db_data: # this can happen when running costs are set when there were no before # we shouldn't crash because of changes in yaml code, still it's suspicious self.log.warning('Object %s of type %s does not know when to pay its rent.\n' 'Disregard this when loading old savegames or on running cost changes.', self.worldid, self.id) remaining_ticks_of_month = 1 else: remaining_ticks_of_month = db_data[0][0] self.__init(remaining_ticks_of_month=remaining_ticks_of_month) # island.add_building handles registration of building for island and settlement self.island.add_building(self, self.owner, load=True)
def _load(self, db, owner, worldid): self.owner = owner super(SettlementManager, self).load(db, worldid) # load the main part land_manager_id = db( "SELECT land_manager FROM ai_settlement_manager WHERE rowid = ?", worldid)[0][0] land_manager = WorldObject.get_object_by_id(land_manager_id) # find the settlement for settlement in self.owner.session.world.settlements: if settlement.owner == self.owner and settlement.island == land_manager.island: land_manager.settlement = settlement break assert land_manager.settlement self.resource_manager = ResourceManager.load(db, self) self.trade_manager = TradeManager.load(db, self) self.__init(land_manager) # load the master builders self.village_builder = VillageBuilder.load(db, self) self.production_builder = ProductionBuilder.load(db, self) self.village_builder.display() self.production_builder.display() self.__init_goals() # the add_building events happen before the settlement manager is loaded so they have to be repeated here for building in self.settlement.buildings: self.add_building(building)
def load(cls, db, worldid, session, island): self = cls.__new__(cls) self.session = session super(Settlement, self).load(db, worldid) owner = db("SELECT owner FROM settlement WHERE rowid = ?", worldid)[0][0] upgrade_permissions = {} tax_settings = {} for level, allowed, tax in db("SELECT level, upgrading_allowed, tax_setting FROM settlement_level_properties WHERE settlement = ?", worldid): upgrade_permissions[level] = allowed tax_settings[level] = tax self.__init(session, WorldObject.get_object_by_id(owner), upgrade_permissions, tax_settings) # load the settlement tile map tile_data = db("SELECT data FROM settlement_tiles WHERE rowid = ?", worldid)[0][0] coords_list = [tuple(raw_coords) for raw_coords in json.loads(tile_data)] # json saves tuples as list for coords in coords_list: tile = island.ground_map[coords] self.ground_map[coords] = tile tile.settlement = self # load all buildings in this settlement from horizons.world import load_building for building_id, building_type in \ db("SELECT rowid, type FROM building WHERE location = ?", worldid): building = load_building(session, db, building_type, building_id) if building_type == BUILDINGS.WAREHOUSE: self.warehouse = building for res, amount in db("SELECT res, amount FROM settlement_produced_res WHERE settlement = ?", worldid): self.produced_res[res] = amount return self
def __call__(self, issuer): """Execute the command @param issuer: the issuer of the command """ building = WorldObject.get_object_by_id(self.building) self.log.debug("Tear: tearing down %s", building) building.remove()
def test_load_inactive_production(): """ create a savegame with a inactive production, load it """ session, player = new_session() settlement, island = settle(session) lj = Build(BUILDINGS.LUMBERJACK, 30, 30, island, settlement=settlement)(player) # Set lumberjack to inactive lj.get_component(Producer).set_active(active=False) worldid = lj.worldid session.run(seconds=1) # Save and reload game session = saveload(session) loadedlj = WorldObject.get_object_by_id(worldid) # Make sure it really is not active producer = loadedlj.get_component(Producer) assert not producer.is_active() # Trigger bug #1359 ToggleActive(producer).execute(session) session.end()
def _check_rotation(cls, session, position, rotation): """The rotation should be the same as the one of the underlying mountain""" tearset = cls._check_buildings(session, position) # will raise on problems # rotation fix code is only reached when building is buildable mountain = WorldObject.get_object_by_id(iter(tearset).next()) return mountain.rotation
def user_attack(self, targetid): """ Called when the user triggeres the attack, executes the user_attack_issued callbacks @param targetid: world id of the unit that is to be attacked """ self.attack(WorldObject.get_object_by_id(targetid)) self.on_user_attack_issued()
def _load(self, worldid, owner, db, destroy_callback): super(Fleet, self).load(db, worldid) self.owner = owner state_id, dest_x, dest_y, radius, ratio = db("SELECT state_id, dest_x, dest_y, radius, ratio FROM fleet WHERE fleet_id = ?", worldid)[0] if radius: # Circle self.destination = Circle(Point(dest_x, dest_y), radius) elif dest_x and dest_y: # Point self.destination = Point(dest_x, dest_y) else: # No destination pass if ratio: self.ratio = ratio ships_states = [(WorldObject.get_object_by_id(ship_id), self.shipStates[ship_state_id]) for ship_id, ship_state_id in db("SELECT ship_id, state_id FROM fleet_ship WHERE fleet_id = ?", worldid)] ships = [item[0] for item in ships_states] self.__init(ships, destroy_callback) self.state = self.fleetStates[state_id] for ship, state in ships_states: self._ships[ship] = state if self.state == self.fleetStates.moving: for ship in self.get_ships(): if self._ships[ship] == self.shipStates.moving: ship.add_move_callback(Callback(self._ship_reached, ship)) if destroy_callback: self.destroy_callback = destroy_callback
def load(self, db): enabled, self.current_waypoint, self.wait_at_load, self.wait_at_unload = \ db("SELECT enabled, current_waypoint, wait_at_load, wait_at_unload " "FROM ship_route WHERE ship_id = ?", self.ship.worldid)[0] query = "SELECT warehouse_id FROM ship_route_waypoint WHERE ship_id = ? ORDER BY waypoint_index" offices_id = db(query, self.ship.worldid) for office_id, in offices_id: warehouse = WorldObject.get_object_by_id(office_id) query = "SELECT res, amount FROM ship_route_resources WHERE ship_id = ? and waypoint_index = ?" resource_list = dict(db(query, self.ship.worldid, len(self.waypoints))) self.waypoints.append({ 'warehouse' : warehouse, 'resource_list' : resource_list }) waiting = False for res, amount in db("SELECT res, amount FROM ship_route_current_transfer WHERE ship_id = ?", self.ship.worldid): waiting = True self.current_transfer[res] = amount Scheduler().add_new_object(self.on_route_warehouse_reached, self, GAME_SPEED.TICKS_PER_SECOND) if enabled and not waiting: self.current_waypoint -= 1 self.enable()
def _get_source_settlement_manager(self): """Return the settlement manager of the settlement from which we should pick up resources next or None if none are needed.""" # TODO: find a better way of getting the following constants ship_capacity = STORAGE.SHIP_TOTAL_STORAGE ship_resource_slots = STORAGE.SHIP_TOTAL_SLOTS_NUMBER options = [] # [(available resource amount, available number of resources, settlement_manager_id), ...] for settlement_manager in self.owner.settlement_managers: if settlement_manager is self.settlement_manager: continue resource_manager = settlement_manager.resource_manager num_resources = 0 total_amount = 0 for resource_id, amount in resource_manager.trade_storage[self.settlement_manager.worldid].items(): available_amount = int(min(math.floor(amount), settlement_manager.settlement.get_component(StorageComponent).inventory[resource_id])) if available_amount > 0: num_resources += 1 total_amount += available_amount ships_needed = int(max(math.ceil(num_resources / float(ship_resource_slots)), math.ceil(total_amount / float(ship_capacity)))) if ships_needed > self.ships_sent[settlement_manager.worldid]: self.log.info('have %d ships, need %d ships, %d resource types, %d total amount', self.ships_sent[settlement_manager.worldid], ships_needed, num_resources, total_amount) options.append((total_amount - ship_capacity * self.ships_sent[settlement_manager.worldid], num_resources - ship_resource_slots * self.ships_sent[settlement_manager.worldid], settlement_manager.worldid)) return None if not options else WorldObject.get_object_by_id(max(options)[2])
def test_load_inactive_production(): """ create a savegame with a inactive production, load it """ session, player = new_session() settlement, island = settle(session) lj = Build(BUILDINGS.LUMBERJACK_CLASS, 30, 30, island, settlement=settlement)(player) # Set lumberjack to inactive lj.get_component(Producer).set_active(active = False) worldid = lj.worldid session.run(seconds=1) fd, filename = tempfile.mkstemp() os.close(fd) assert session.save(savegamename=filename) session.end(keep_map=True) # Load game session = load_session(filename) loadedlj = WorldObject.get_object_by_id(worldid) # Make sure it really is not active producer = loadedlj.get_component(Producer) assert not producer.is_active() # Trigger bug #1359 ToggleActive(producer).execute(session) session.end()
def _get_source_settlement_manager(self): """Return the settlement manager of the settlement from which we should pick up resources next or None if none are needed.""" # TODO: find a better way of getting the following constants ship_capacity = 120 ship_resource_slots = 4 options = [] # [(available resource amount, available number of resources, settlement_manager_id), ...] for settlement_manager in self.owner.settlement_managers: if settlement_manager is self.settlement_manager: continue resource_manager = settlement_manager.resource_manager num_resources = 0 total_amount = 0 for resource_id, amount in resource_manager.trade_storage[self.settlement_manager.worldid].iteritems(): available_amount = int(min(math.floor(amount), settlement_manager.settlement.get_component(StorageComponent).inventory[resource_id])) if available_amount > 0: num_resources += 1 total_amount += available_amount ships_needed = int(max(math.ceil(num_resources / float(ship_resource_slots)), math.ceil(total_amount / float(ship_capacity)))) if ships_needed > self.ships_sent[settlement_manager.worldid]: self.log.info('have %d ships, need %d ships, %d resource types, %d total amount', self.ships_sent[settlement_manager.worldid], ships_needed, num_resources, total_amount) options.append((total_amount - ship_capacity * self.ships_sent[settlement_manager.worldid], num_resources - ship_resource_slots * self.ships_sent[settlement_manager.worldid], settlement_manager.worldid)) return None if not options else WorldObject.get_object_by_id(max(options)[2])
def _load(self, worldid, owner, db, success_callback, failure_callback): super(ChaseShipsAndAttack, self)._load(db, worldid, success_callback, failure_callback, owner) (target_ship_id,) = db("SELECT target_ship_id FROM ai_mission_chase_ships_and_attack WHERE rowid = ?", worldid)[ 0 ] target_ship = WorldObject.get_object_by_id(target_ship_id) self.__init(target_ship)
def __call__(self, issuer): """__call__() gets called by the manager. @param issuer: the issuer of the command """ owner = WorldObject.get_object_by_id(self.owner_id) unit = Entities.units[self.unit_id](session=owner.session, owner=owner, x=self.x, y=self.y, **self.kwargs) unit.initialize() return unit
def fix_job_object(): # resolve worldid to object later if self.job: if self.job.object == -1: self.job.object = None else: self.job.object = WorldObject.get_object_by_id( self.job.object)
def finish_loading(self, db): """ This is called separately because most objects are loaded after the player. """ # load the ships for ship_id, state_id in db("SELECT rowid, state FROM ai_ship WHERE owner = ?", self.worldid): ship = WorldObject.get_object_by_id(ship_id) self.ships[ship] = self.shipStates[state_id] # load unit manager self.unit_manager = UnitManager.load(db, self) # load combat manager self.combat_manager = CombatManager.load(db, self) # load strategy manager self.strategy_manager = StrategyManager.load(db, self) # load BehaviorManager self.behavior_manager = BehaviorManager.load(db, self) # load the land managers for (worldid,) in db("SELECT rowid FROM ai_land_manager WHERE owner = ?", self.worldid): land_manager = LandManager.load(db, self, worldid) self.islands[land_manager.island.worldid] = land_manager # load the settlement managers and settlement foundation missions for land_manager in self.islands.itervalues(): db_result = db("SELECT rowid FROM ai_settlement_manager WHERE land_manager = ?", land_manager.worldid) if db_result: settlement_manager = SettlementManager.load(db, self, db_result[0][0]) self.settlement_managers.append(settlement_manager) self._settlement_manager_by_settlement_id[settlement_manager.settlement.worldid] = settlement_manager # load the foundation ship preparing missions db_result = db("SELECT rowid FROM ai_mission_prepare_foundation_ship WHERE settlement_manager = ?", settlement_manager.worldid) for (mission_id,) in db_result: self.missions.add(PrepareFoundationShip.load(db, mission_id, self.report_success, self.report_failure)) else: mission_id = db("SELECT rowid FROM ai_mission_found_settlement WHERE land_manager = ?", land_manager.worldid)[0][0] self.missions.add(FoundSettlement.load(db, mission_id, self.report_success, self.report_failure)) for settlement_manager in self.settlement_managers: # load the domestic trade missions db_result = db("SELECT rowid FROM ai_mission_domestic_trade WHERE source_settlement_manager = ?", settlement_manager.worldid) for (mission_id,) in db_result: self.missions.add(DomesticTrade.load(db, mission_id, self.report_success, self.report_failure)) # load the special domestic trade missions db_result = db("SELECT rowid FROM ai_mission_special_domestic_trade WHERE source_settlement_manager = ?", settlement_manager.worldid) for (mission_id,) in db_result: self.missions.add(SpecialDomesticTrade.load(db, mission_id, self.report_success, self.report_failure)) # load the international trade missions db_result = db("SELECT rowid FROM ai_mission_international_trade WHERE settlement_manager = ?", settlement_manager.worldid) for (mission_id,) in db_result: self.missions.add(InternationalTrade.load(db, mission_id, self.report_success, self.report_failure))
def test_ticket_1427(): """Boatbuilder production progress should be saved properly""" session, player = new_session() settlement, island = settle(session) boat_builder = Build(BUILDINGS.BOATBUILDER_CLASS, 35, 20, island, settlement=settlement)(player) worldid = boat_builder.worldid # Make sure no boards are available settlement.get_component(StorageComponent).inventory.alter(RES.BOARDS_ID, -1000) bb_storage = boat_builder.get_component(StorageComponent) # Add production to use resources bb_producer = boat_builder.get_component(Producer) bb_producer.add_production_by_id(PRODUCTIONLINES.HUKER) production = bb_producer._productions[PRODUCTIONLINES.HUKER] assert production.progress == 0.0 bb_storage.inventory.alter(RES.TEXTILE_ID, 10) bb_storage.inventory.alter(RES.BOARDS_ID, 6) production_line = production._prod_line # Make sure the boatbuilder consumes everything in his inventory session.run(seconds=10) # Check if correctly consumed wood assert production_line.consumed_res[RES.BOARDS_ID] == -2 # Save all production process for later expected_consumed_res = production_line.consumed_res expected_produced_res = production_line.produced_res expected_production = production_line.production expected_progress = production.progress # Make sure the producer used the boards assert bb_storage.inventory[RES.BOARDS_ID] == 0 fd, filename = tempfile.mkstemp() os.close(fd) assert session.save(savegamename=filename) session.end(keep_map=True) # Load game session = load_session(filename) loadedbb = WorldObject.get_object_by_id(worldid) production_loaded = loadedbb.get_component(Producer)._productions[PRODUCTIONLINES.HUKER] production_line_loaded = production_loaded._prod_line # Make sure everything is loaded correctly assert expected_consumed_res == production_line_loaded.consumed_res assert expected_produced_res == production_line_loaded.produced_res assert expected_production == production_line_loaded.production assert expected_progress == production_loaded.progress
def transfer_to_storageholder(self, amount, res_id, transfer_to_id): transfer_to = WorldObject.get_object_by_id(transfer_to_id) # take res from self ret = self.inventory.alter(res_id, -amount) # check if we were able to get the planed amount ret = amount if amount < abs(ret) else abs(ret) # put res to transfer_to ret = transfer_to.inventory.alter(res_id, amount - ret) self.inventory.alter(res_id, ret) #return resources that did not fit
def _load(self, worldid, owner, db, success_callback, failure_callback): super(ChaseShipsAndAttack, self)._load(db, worldid, success_callback, failure_callback, owner) (target_ship_id, ) = db( "SELECT target_ship_id FROM ai_mission_chase_ships_and_attack WHERE rowid = ?", worldid)[0] target_ship = WorldObject.get_object_by_id(target_ship_id) self.__init(target_ship)
def fife_instance_to_uh_instance(self, instance): """Visual fife instance to uh game logic object or None""" i_id = instance.getId() if i_id == '': return None try: return WorldObject.get_object_by_id(int(i_id)) except WorldObjectNotFound: return None
def test_ticket_1427(): """Boatbuilder production progress should be saved properly""" session, player = new_session() settlement, island = settle(session) boat_builder = Build(BUILDINGS.BOAT_BUILDER, 35, 20, island, settlement=settlement)(player) worldid = boat_builder.worldid # Make sure no boards are available settlement.get_component(StorageComponent).inventory.alter(RES.BOARDS, -1000) bb_storage = boat_builder.get_component(StorageComponent) # Add production to use resources bb_producer = boat_builder.get_component(Producer) bb_producer.add_production_by_id(PRODUCTIONLINES.HUKER) production = bb_producer._productions[PRODUCTIONLINES.HUKER] assert production.progress == 0.0 bb_storage.inventory.alter(RES.TEXTILE, 10) bb_storage.inventory.alter(RES.BOARDS, 6) production_line = production._prod_line # Make sure the boatbuilder consumes everything in its inventory session.run(seconds=10) # Check if correctly consumed wood assert production_line.consumed_res[RES.BOARDS] == -2 # Save all production process for later expected_consumed_res = production_line.consumed_res expected_produced_res = production_line.produced_res expected_production = production_line.production expected_progress = production.progress # Make sure the producer used the boards assert bb_storage.inventory[RES.BOARDS] == 0 # Save and reload game session = saveload(session) loadedbb = WorldObject.get_object_by_id(worldid) production_loaded = loadedbb.get_component(Producer)._productions[PRODUCTIONLINES.HUKER] production_line_loaded = production_loaded._prod_line # Make sure everything is loaded correctly assert expected_consumed_res == production_line_loaded.consumed_res assert expected_produced_res == production_line_loaded.produced_res assert expected_production == production_line_loaded.production assert expected_progress == production_loaded.progress # if you don't let the session run for a bit then collectors won't be fully initialized and can't be killed => another test will fail in session.end() session.run(seconds=1) session.end()
def test_build_tear(s, p): """ Build stuff and tear it later """ settlement, island = settle(s) tree = Build(BUILDINGS.TREE, 30, 35, island, settlement=settlement)(p) s.run(seconds=1) wid = tree.worldid Tear(tree)(p) try: WorldObject.get_object_by_id(wid) except WorldObjectNotFound: pass # should be gone else: assert False