def new_session(mapgen=create_map, rng_seed=RANDOM_SEED, human_player = True, ai_players = 0): """ Create a new session with a map, add one human player and a trader (it will crash otherwise). It returns both session and player to avoid making the function-baed tests too verbose. """ session = SPTestSession(horizons.main.db, rng_seed=rng_seed) human_difficulty = DifficultySettings.DEFAULT_LEVEL ai_difficulty = DifficultySettings.EASY_LEVEL players = [] if human_player: players.append({'id': 1, 'name': 'foobar', 'color': Color[1], 'local': True, 'is_ai': False, 'difficulty': human_difficulty}) for i in xrange(ai_players): id = i + human_player + 1 players.append({'id': id, 'name': ('AI' + str(i)), 'color': Color[id], 'local': id == 1, 'is_ai': True, 'difficulty': ai_difficulty}) session.load(mapgen(), players) session.world.init_fish_indexer() # use different trader id here, so that init_new_world can be called # (else there would be a worldid conflict) session.world.trader = Trader(session, 99999 + 42, 'Free Trader', Color()) if ai_players > 0: # currently only ai tests use the ships for player in session.world.players: point = session.world.get_random_possible_ship_position() ship = CreateUnit(player.worldid, UNITS.PLAYER_SHIP_CLASS, point.x, point.y)(issuer=player) # give ship basic resources for res, amount in session.db("SELECT resource, amount FROM start_resources"): ship.get_component(StorageComponent).inventory.alter(res, amount) AIPlayer.load_abstract_buildings(session.db) return session, session.world.player
def init_new_world(self, trader_enabled, pirate_enabled, natural_resource_multiplier): """ This should be called if a new map is loaded (not a savegame, a fresh map). In other words when it is loaded for the first time. NOTE: commands for creating the world objects are executed directly, bypassing the manager This is necessary because else the commands would be transmitted over the wire in network games. @return: the coordinates of the players first ship """ # workaround: the creation of all the objects causes a lot of logging output, we don't need # therefore, reset the levels for now loggers_to_silence = { 'world.production' : None } for logger_name in loggers_to_silence: logger = logging.getLogger(logger_name) loggers_to_silence[logger_name] = logger.getEffectiveLevel() logger.setLevel( logging.WARN ) # add a random number of environmental objects if natural_resource_multiplier != 0: self._add_nature_objects(natural_resource_multiplier) # reset loggers, see above for logger_name, level in loggers_to_silence.iteritems(): logging.getLogger(logger_name).setLevel(level) # add free trader if trader_enabled: self.trader = Trader(self.session, 99999, u"Free Trader", Color()) ret_coords = None for player in self.players: # Adding ships for the players # hack to place the ship on the development map point = self.get_random_possible_ship_position() # Execute command directly, not via manager, because else it would be transmitted over the # network to other players. Those however will do the same thing anyways. ship = CreateUnit(player.worldid, UNITS.PLAYER_SHIP, point.x, point.y)(issuer=self.session.world.player) # give ship basic resources for res, amount in self.session.db("SELECT resource, amount FROM start_resources"): ship.get_component(StorageComponent).inventory.alter(res, amount) if player is self.player: ret_coords = point.to_tuple() # 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 # add a pirate ship if pirate_enabled: self.pirate = Pirate(self.session, 99998, "Captain Blackbeard", Color()) # Fire a message for new world creation self.session.ingame_gui.message_widget.add(None, None, 'NEW_WORLD') assert ret_coords is not None, "Return coords are None. No players loaded?" return ret_coords
def __create_unit(self): """Create the produced unit now.""" productions = self._productions.values() for production in productions: assert isinstance(production, UnitProduction) self.on_production_finished(production.get_produced_units()) for unit, amount in production.get_produced_units().iteritems(): for i in xrange(0, amount): radius = 1 found_tile = False # search for free water tile, and increase search radius if none is found while not found_tile: for coord in Circle(self.instance.position.center(), radius).tuple_iter(): point = Point(coord[0], coord[1]) if self.instance.island.get_tile(point) is None: tile = self.session.world.get_tile(point) if tile is not None and tile.is_water and coord not in self.session.world.ship_map: # execute bypassing the manager, it's simulated on every machine u = CreateUnit(self.instance.owner.worldid, unit, point.x, point.y)(issuer=self.instance.owner) # Fire a message indicating that the ship has been created name = u.get_component(NamedComponent).name self.session.ingame_gui.message_widget.add(string_id='NEW_UNIT', point=point, message_dict={'name' : name}) found_tile = True break radius += 1
def new_settlement(session, pos=Point(30, 20)): """ Creates a settlement at the given position. It returns the settlement and the island where it was created on, to avoid making function-baed tests too verbose. """ island = session.world.get_island(pos) assert island, "No island found at %s" % pos player = session.world.player ship = CreateUnit(player.worldid, UNITS.PLAYER_SHIP_CLASS, pos.x, pos.y)(player) for res, amount in session.db("SELECT resource, amount FROM start_resources"): ship.get_component(StorageComponent).inventory.alter(res, amount) building = Build(BUILDINGS.WAREHOUSE_CLASS, pos.x, pos.y, island, ship=ship)(player) assert building, "Could not build warehouse at %s" % pos return (building.settlement, island)
def new_settlement(session, pos=Point(30, 20)): """ Creates a settlement at the given position. It returns the settlement and the island where it was created on, to avoid making function-baed tests too verbose. """ island = session.world.get_island(pos) assert island, "No island found at %s" % pos player = session.world.player ship = CreateUnit(player.worldid, UNITS.PLAYER_SHIP, pos.x, pos.y)(player) for res, amount in session.db("SELECT resource, amount FROM start_resources"): ship.get_component(StorageComponent).inventory.alter(res, amount) building = Build(BUILDINGS.WAREHOUSE, pos.x, pos.y, island, ship=ship)(player) assert building, "Could not build warehouse at %s" % pos return (building.settlement, island)
def test_hunter(s, p): """ Hunter will produce food from dear meat. No animals were harmed in this test. """ settlement, island = settle(s) hunter = Build(BUILDINGS.HUNTER, 30, 30, island, settlement=settlement)(p) assert hunter assert hunter.get_component(StorageComponent).inventory[RES.FOOD] == 0 assert hunter.get_component(StorageComponent).inventory[RES.DEER_MEAT] == 0 for (x_off, y_off) in product([-5, -4, 4, 5], repeat=2): x = 30 + x_off y = 30 + y_off animal = CreateUnit(island.worldid, UNITS.WILD_ANIMAL, x, y)(None) # wild animals are slow eaters, we feed them directly animal.get_component(StorageComponent).inventory.alter(12, 10) animal.get_component(Producer).finish_production_now() assert animal s.run(seconds=30) assert hunter.get_component(StorageComponent).inventory[RES.FOOD]
def _place_unit(self, unit): radius = 1 found_tile = False while not found_tile: # search for a free tile around the building for tile in self.instance.island.get_surrounding_tiles(self.instance.position.center, radius): point = Point(tile.x, tile.y) if not (tile.is_water or tile.blocked) and (tile.x, tile.y) not in self.session.world.ground_unit_map: u = CreateUnit(self.instance.owner.worldid, unit, tile.x, tile.y)(issuer=self.instance.owner) # Fire a message indicating that the ship has been created name = u.get_component(NamedComponent).name self.session.ingame_gui.message_widget.add(string_id='NEW_SOLDIER', point=point, message_dict={'name': name}) found_tile = True break radius += 1
def __place_unit(self, unit): radius = 1 found_tile = False # search for free water tile, and increase search radius if none is found while not found_tile: for coord in Circle(self.instance.position.center, radius).tuple_iter(): point = Point(coord[0], coord[1]) if self.instance.island.get_tile(point) is not None: continue tile = self.session.world.get_tile(point) if tile is not None and tile.is_water and coord not in self.session.world.ship_map: # execute bypassing the manager, it's simulated on every machine u = CreateUnit(self.instance.owner.worldid, unit, point.x, point.y)(issuer=self.instance.owner) # Fire a message indicating that the ship has been created name = u.get_component(NamedComponent).name self.session.ingame_gui.message_widget.add(string_id='NEW_UNIT', point=point, message_dict={'name' : name}) found_tile = True break radius += 1
def _place_unit(self, unit): radius = 1 found_tile = False while not found_tile: # search for a free tile around the building for tile in self.instance.island.get_surrounding_tiles( self.instance.position.center, radius): point = Point(tile.x, tile.y) if not (tile.is_water or tile.blocked) and ( tile.x, tile.y) not in self.session.world.ground_unit_map: u = CreateUnit(self.instance.owner.worldid, unit, tile.x, tile.y)(issuer=self.instance.owner) # Fire a message indicating that the ship has been created name = u.get_component(NamedComponent).name self.session.ingame_gui.message_widget.add( string_id='NEW_SOLDIER', point=point, message_dict={'name': name}) found_tile = True break radius += 1
def init_new_world(self, trader_enabled, pirate_enabled, natural_resource_multiplier): """ This should be called if a new map is loaded (not a savegame, a fresh map). In other words, when it is loaded for the first time. NOTE: commands for creating the world objects are executed directly, bypassing the manager. This is necessary because else the commands would be transmitted over the wire in network games. @return: the coordinates of the players first ship """ # workaround: the creation of all the objects causes a lot of logging output we don't need. # therefore, reset the levels for now loggers_to_silence = {'world.production': None} for logger_name in loggers_to_silence: logger = logging.getLogger(logger_name) loggers_to_silence[logger_name] = logger.getEffectiveLevel() logger.setLevel(logging.WARN) # add a random number of environmental objects if natural_resource_multiplier != 0: self._add_nature_objects(natural_resource_multiplier) # reset loggers, see above for logger_name, level in loggers_to_silence.items(): logging.getLogger(logger_name).setLevel(level) # add free trader if trader_enabled: self.trader = Trader(self.session, 99999, "Free Trader", Color()) ret_coords = None for player in self.players: # Adding ships for the players # hack to place the ship on the development map point = self.get_random_possible_ship_position() # Execute command directly, not via manager, because else it would be transmitted over the # network to other players. Those however will do the same thing anyways. ship = CreateUnit(player.worldid, UNITS.PLAYER_SHIP, point.x, point.y)(issuer=self.session.world.player) # give ship basic resources for res, amount in self.session.db( "SELECT resource, amount FROM start_resources"): ship.get_component(StorageComponent).inventory.alter( res, amount) if player is self.player: ret_coords = point.to_tuple() # HACK: Store starting ship as first unit group, and select it def _preselect_player_ship(player_ship): sel_comp = player_ship.get_component(SelectableComponent) sel_comp.select(reset_cam=True) self.session.selected_instances = {player_ship} self.session.ingame_gui.handle_selection_group(1, True) sel_comp.show_menu() select_ship = partial(_preselect_player_ship, ship) Scheduler().add_new_object(select_ship, ship, run_in=0) # 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 # add a pirate ship if pirate_enabled: self.pirate = Pirate(self.session, 99998, "Captain Blackbeard", Color()) assert ret_coords is not None, "Return coords are None. No players loaded?" return ret_coords
def remove(s, p, before_ticks, after_ticks, tear_index): """ Place a couple of buildings and tear down one randomly, run a while afterwards. Called by test_removal with different parameters. """ settlement, island = settle(s) settlement.warehouse.get_component(StorageComponent).inventory.adjust_limit(sys.maxint) # Plant trees for (x, y) in product(range(23, 38), repeat=2): if s.random.randint(0, 1) == 1: tree = Build(BUILDINGS.TREE, x, y, island, settlement=settlement)(p) assert tree tree.get_component(Producer).finish_production_now() jack = Build(BUILDINGS.LUMBERJACK, 25, 30, island, settlement=settlement)(p) assert jack jack = Build(BUILDINGS.LUMBERJACK, 35, 30, island, settlement=settlement)(p) assert jack # Throw some fish into the water for x in (25, 30, 35): school = Build(BUILDINGS.FISH_DEPOSIT, x, 18, s.world, ownerless=True)(None) assert school school.get_component(Producer).finish_production_now() fisherman = Build(BUILDINGS.FISHER, 25, 20, island, settlement=settlement)(p) assert fisherman fisherman = Build(BUILDINGS.FISHER, 35, 20, island, settlement=settlement)(p) assert fisherman # Some wild animals in the forest for (x_off, y_off) in product([-5, -4, 4, 5], repeat=2): x = 30 + x_off y = 30 + y_off animal = CreateUnit(island.worldid, UNITS.WILD_ANIMAL, x, y)(None) assert animal animal.get_component(Producer).finish_production_now() hunter = Build(BUILDINGS.HUNTER, 30, 35, island, settlement=settlement)(p) assert hunter # Build a farm assert Build(BUILDINGS.FARM, 26, 33, island, settlement=settlement)(p) assert Build(BUILDINGS.PASTURE, 22, 33, island, settlement=settlement)(p) assert Build(BUILDINGS.PASTURE, 26, 37, island, settlement=settlement)(p) # Build roads for (start, dest) in [(Point(27, 30), Point(30, 23)), (Point(32, 23), Point(35, 29)), (Point(25, 22), Point(30, 23)), (Point(32, 23), Point(35, 22)), (Point(30, 34), Point(32, 25)), (Point(26, 32), Point(27, 30))]: path = RoadPathFinder()(island.path_nodes.nodes, start.to_tuple(), dest.to_tuple()) assert path for (x, y) in path: Build(BUILDINGS.TRAIL, x, y, island, settlement=settlement)(p) s.run(seconds=before_ticks) # Tear down a random building that is not a trail or tree. target = [b for b in settlement.buildings if b.id not in (BUILDINGS.TRAIL, BUILDINGS.TREE)][tear_index] Tear(target)(p) s.run(seconds=after_ticks)
def remove(s, p, before_ticks, after_ticks, tear_index): """ Place a couple of buildings and tear down one randomly, run a while afterwards. Called by test_removal with different parameters. """ settlement, island = settle(s) settlement.warehouse.get_component( StorageComponent).inventory.adjust_limit(sys.maxint) # Plant trees for (x, y) in product(range(23, 38), repeat=2): if s.random.randint(0, 1) == 1: tree = Build(BUILDINGS.TREE, x, y, island, settlement=settlement)(p) assert tree tree.get_component(Producer).finish_production_now() jack = Build(BUILDINGS.LUMBERJACK, 25, 30, island, settlement=settlement)(p) assert jack jack = Build(BUILDINGS.LUMBERJACK, 35, 30, island, settlement=settlement)(p) assert jack # Throw some fish into the water for x in (25, 30, 35): school = Build(BUILDINGS.FISH_DEPOSIT, x, 18, s.world, ownerless=True)(None) assert school school.get_component(Producer).finish_production_now() fisherman = Build(BUILDINGS.FISHER, 25, 20, island, settlement=settlement)(p) assert fisherman fisherman = Build(BUILDINGS.FISHER, 35, 20, island, settlement=settlement)(p) assert fisherman # Some wild animals in the forest for (x_off, y_off) in product([-5, -4, 4, 5], repeat=2): x = 30 + x_off y = 30 + y_off animal = CreateUnit(island.worldid, UNITS.WILD_ANIMAL, x, y)(None) assert animal animal.get_component(Producer).finish_production_now() hunter = Build(BUILDINGS.HUNTER, 30, 35, island, settlement=settlement)(p) assert hunter # Build a farm assert Build(BUILDINGS.FARM, 26, 33, island, settlement=settlement)(p) assert Build(BUILDINGS.PASTURE, 22, 33, island, settlement=settlement)(p) assert Build(BUILDINGS.PASTURE, 26, 37, island, settlement=settlement)(p) # Build roads for (start, dest) in [(Point(27, 30), Point(30, 23)), (Point(32, 23), Point(35, 29)), (Point(25, 22), Point(30, 23)), (Point(32, 23), Point(35, 22)), (Point(30, 34), Point(32, 25)), (Point(26, 32), Point(27, 30))]: path = RoadPathFinder()(island.path_nodes.nodes, start.to_tuple(), dest.to_tuple()) assert path for (x, y) in path: Build(BUILDINGS.TRAIL, x, y, island, settlement=settlement)(p) s.run(seconds=before_ticks) # Tear down a random building that is not a trail or tree. target = [ b for b in settlement.buildings if b.id not in (BUILDINGS.TRAIL, BUILDINGS.TREE) ][tear_index] Tear(target)(p) s.run(seconds=after_ticks)