示例#1
0
	def testPoint(self):
		p1 = Point(0,0)
		p2 = Point(0,2)
		self.assertEqual(p1.distance(p2), 2)
		self.assertEqual(p1.distance((0,1)), 1)
		self.assertEqual(p1.get_coordinates(), [(0,0)])
		self.assertEqual(p1, p1.copy())
def test_point():
	p1 = Point(0, 0)
	p2 = Point(0, 2)
	assert p1.distance(p2) == 2
	assert p1.distance((0, 1)) == 1
	assert p1.get_coordinates() == [(0, 0)]
	assert p1 == p1.copy()
示例#3
0
	def calculate_ship_dispersion(cls, ship_group):
		"""
		There are many solutions to solve the problem of caculating ship_group dispersion efficiently.
		We generally care about computing that in linear time, rather than having accurate numbers in O(n^2).
		We settle for a diagonal of a bounding box for the whole group.
		@return: dispersion factor
		@rtype: float
		"""
		positions = [ship.position for ship in ship_group]
		bottom_left = Point(min(positions, key=lambda position: position.x).x, min(positions, key=lambda position: position.y).y)
		top_right = Point(max(positions, key=lambda position: position.x).x, max(positions, key=lambda position: position.y).y)
		diagonal = bottom_left.distance(top_right)
		return diagonal
示例#4
0
	def __init(self, origin, filename, preview=False):
		"""
		Load the actual island from a file
		@param origin: Point
		@param filename: String, filename of island db or random map id
		@param preview: flag, map preview mode
		"""
		self.file = filename
		self.origin = origin
		db = self._get_island_db()

		p_x, p_y, width, height = db("SELECT (MIN(x) + ?), (MIN(y) + ?), (1 + MAX(x) - MIN(x)), (1 + MAX(y) - MIN(y)) FROM ground", self.origin.x, self.origin.y)[0]

		# rect for quick checking if a tile isn't on this island
		# NOTE: it contains tiles, that are not on the island!
		self.rect = Rect(Point(p_x, p_y), width, height)

		self.ground_map = {}
		for (rel_x, rel_y, ground_id, action_id, rotation) in db("SELECT x, y, ground_id, action_id, rotation FROM ground"): # Load grounds
			if not preview: # actual game, need actual tiles
				ground = Entities.grounds[ground_id](self.session, self.origin.x + rel_x, self.origin.y + rel_y)
				ground.act(action_id, rotation)
			else:
				ground = Point(self.origin.x + rel_x, self.origin.y + rel_y)
				ground.classes = tuple()
				ground.settlement = None
			# These are important for pathfinding and building to check if the ground tile
			# is blocked in any way.
			self.ground_map[(ground.x, ground.y)] = ground

		self._init_cache()

		self.settlements = []
		self.wild_animals = []
		self.num_trees = 0

		# define the rectangle with the smallest area that contains every island tile its position
		min_x = min(zip(*self.ground_map.keys())[0])
		max_x = max(zip(*self.ground_map.keys())[0])
		min_y = min(zip(*self.ground_map.keys())[1])
		max_y = max(zip(*self.ground_map.keys())[1])
		self.position = Rect.init_from_borders(min_x, min_y, max_x, max_y)

		if not preview: # this isn't needed for previews, but it is in actual games
			self.path_nodes = IslandPathNodes(self)

			# repopulate wild animals every 2 mins if they die out.
			Scheduler().add_new_object(self.check_wild_animal_population, self, Scheduler().get_ticks(120), -1)

		"""TUTORIAL:
示例#5
0
	def _get_event_coord(self, event):
		"""Returns position of event as uh map coordinate tuple or None"""
		mouse_position = Point(event.getX(), event.getY())
		if not hasattr(self, "icon"):
			icon_pos = Point(*self.overlay_icon.getAbsolutePos())
			abs_mouse_position = icon_pos + mouse_position
			if not self.location.contains(abs_mouse_position):
				# mouse click was on icon but not actually on minimap
				return
			abs_mouse_position = abs_mouse_position.to_tuple()
		else:
			abs_mouse_position = mouse_position.to_tuple()
		if self._get_rotation_setting():
			abs_mouse_position = self._get_from_rotated_coords(abs_mouse_position)
		return self._minimap_coord_to_world_coord(abs_mouse_position)
	def find_warehouse_location(cls, ship, land_manager):
		"""
		Finds a location for the warehouse on the given island
		@param LandManager: the LandManager of the island
		@return _BuildPosition: a possible build location
		"""
		moves = [(-1, 0), (0, -1), (0, 1), (1, 0)]
		island = land_manager.island
		world = island.session.world
		personality = land_manager.owner.personality_manager.get('FoundSettlement')
		options = []

		for (x, y), tile in sorted(island.ground_map.iteritems()):
			ok = False
			for x_offset, y_offset in moves:
				for d in xrange(2, 6):
					coords = (x + d * x_offset, y + d * y_offset)
					if coords in world.water_body and world.water_body[coords] == world.water_body[ship.position.to_tuple()]:
						# the planned warehouse should be reachable from the ship's water body
						ok = True
			if not ok:
				continue

			build_info = None
			point = Point(x, y)
			warehouse = Builder(BUILDINGS.WAREHOUSE, land_manager, point, ship = ship)
			if not warehouse:
				continue

			cost = 0
			for coords in land_manager.village:
				distance = point.distance(coords)
				if distance < personality.too_close_penalty_threshold:
					cost += personality.too_close_constant_penalty + personality.too_close_linear_penalty / (distance + 1.0)
				else:
					cost += distance

			for settlement_manager in land_manager.owner.settlement_managers:
				cost += warehouse.position.distance(settlement_manager.settlement.warehouse.position) * personality.linear_warehouse_penalty

			options.append((cost, warehouse))

		for _, build_info in sorted(options):
			(x, y) = build_info.position.get_coordinates()[4]
			if ship.check_move(Circle(Point(x, y), BUILDINGS.BUILD.MAX_BUILDING_SHIP_DISTANCE)):
				return build_info
		return None
示例#7
0
 def _make_surrounding_transparent(self, building):
     """Makes the surrounding of building_position transparent"""
     world_contains = self.session.world.map_dimensions.contains_without_border
     for coord in building.position.get_radius_coordinates(
             self.nearby_objects_radius, include_self=True):
         p = Point(*coord)
         if not world_contains(p):
             continue
         tile = self.session.world.get_tile(p)
         if tile.object is not None and tile.object.buildable_upon:
             inst = tile.object.fife_instance
             inst.get2dGfxVisual().setTransparency(
                 BUILDINGS.TRANSPARENCY_VALUE)
             self._transparent_instances.add(weakref.ref(inst))
示例#8
0
	def _check_island(cls, session, position, island=None):
		# this might raise, just let it through
		super(BuildableSingleOnOcean, cls)._check_island(session, position, island)
		if island is None:
			island = session.world.get_island(position.center)
			if island is None:
				raise _NotBuildableError(BuildableErrorTypes.NO_ISLAND)
		posis = position.get_coordinates()
		for tile in posis:
			for rad in Circle(Point(*tile), 3):
				if island.get_tile(rad) is None:
					# Tile not on island -> deep water
					return island
		raise _NotBuildableError(BuildableErrorTypes.NO_OCEAN_NEARBY)
示例#9
0
	def begin_current_job(self):
		# we can only move on 1 building; simulate this by choosing a random location with
		# the building
		coords = self._get_random_positions_on_object(self.job.object)

		# move to first walkable target coord we find
		for coord in coords:
			# job target is walkable, so at least one coord of it has to be
			# so we can safely assume, that we will find a walkable coord
			target_location = Point(*coord)
			if self.check_move(target_location):
				super(FarmAnimal, self).begin_current_job(job_location=target_location)
				return
		assert False
示例#10
0
    def __make_new_builder(self, building_id, x, y, needs_collector,
                           orientation):
        """Return a Builder object if it is allowed to be built at the location, otherwise return None (not cached)."""
        coords = (x, y)
        # quick check to see whether the origin square is allowed to be in the requested place
        if building_id == BUILDINGS.CLAY_PIT or building_id == BUILDINGS.IRON_MINE:
            # clay deposits and mountains are outside the production plan until they are constructed
            if coords in self.plan or coords not in self.settlement.ground_map:
                return None
        elif building_id in self.coastal_building_classes:
            # coastal buildings can use coastal tiles
            if coords not in self.land_manager.coastline and coords in self.plan and self.plan[
                    coords][0] != BUILDING_PURPOSE.NONE:
                return None
        else:
            if coords not in self.plan or self.plan[coords][
                    0] != BUILDING_PURPOSE.NONE or coords not in self.settlement.ground_map:
                return None

        # create the builder, make sure that it is allowed according to the game logic
        builder = Builder.create(building_id,
                                 self.land_manager,
                                 Point(x, y),
                                 orientation=orientation)
        if not builder or not self.land_manager.legal_for_production(
                builder.position):
            return None

        # make sure that the position of the building is allowed according to the plan
        if building_id in self.coastal_building_classes:
            # coastal buildings can use coastal tiles
            for coords in builder.position.tuple_iter():
                if coords not in self.land_manager.coastline and coords in self.plan and self.plan[
                        coords][0] != BUILDING_PURPOSE.NONE:
                    return None
        elif building_id in [BUILDINGS.CLAY_PIT, BUILDINGS.IRON_MINE]:
            # clay deposits and mountains can't be in areas restricted by the plan
            pass
        else:
            for coords in builder.position.tuple_iter():
                if coords not in self.plan or self.plan[coords][
                        0] != BUILDING_PURPOSE.NONE:
                    return None

        # make sure the building is close enough to a collector if it produces any resources that have to be collected
        if needs_collector and not any(
                True for building in self.collector_buildings if building.
                position.distance(builder.position) <= building.radius):
            return None
        return builder
示例#11
0
	def _check_island(cls, session, position, island=None):
		# this might raise, just let it through
		super(BuildableSingleOnOcean, cls)._check_island(session, position, island)
		if island is None:
			island = session.world.get_island(position.center)
			if island is None:
				raise _NotBuildableError(BuildableErrorTypes.NO_ISLAND)
		posis = position.get_coordinates()
		for tile in posis:
			for rad in Circle(Point(*tile), 3):
				if rad in session.world.water_body and session.world.water_body[rad] == session.world.sea_number:
					# Found legit see tile
					return island
		raise _NotBuildableError(BuildableErrorTypes.NO_OCEAN_NEARBY)
    def go(self, x, y):
        from horizons.world.units.movingobject import MoveNotPossible
        """Moves the unit.
		This is called when a unit is selected and the right mouse button is pressed outside the unit"""
        x = int(round(x))
        y = int(round(y))
        move_target = Point(x, y)

        try:
            self.instance.move(move_target)
        except MoveNotPossible:
            # find a near tile to move to
            surrounding = Circle(move_target, radius=1)
            move_target = None
            # try with smaller circles, increase radius if smaller circle isn't reachable
            while surrounding.radius < 5:
                try:
                    self.instance.move(surrounding)
                except MoveNotPossible:
                    surrounding.radius += 1
                    continue
                # update actual target coord
                move_target = self.instance.get_move_target()
                break
        if self.instance.owner.is_local_player:
            self.instance.session.ingame_gui.minimap.show_unit_path(
                self.instance)
        if move_target is None:  # can't move
            if not self.instance.owner.is_local_player:
                return
            if self.session.world.get_tile(Point(
                    x, y)) is None:  # not even in world
                string_id = "MOVE_OUTSIDE_OF_WORLD"
            else:  # in world, but still unreachable
                string_id = "MOVE_INVALID_LOCATION"
            self.session.ingame_gui.message_widget.add(point=Point(x, y),
                                                       string_id=string_id)
    def execute(self):
        (result, building) = super(LumberjackEvaluator, self).execute()
        if result != BUILD_RESULT.OK:
            return (result, None)

        for coords in building.position.get_radius_coordinates(
                Entities.buildings[BUILDINGS.LUMBERJACK].radius):
            if coords in self.area_builder.plan and self.area_builder.plan[
                    coords][0] == BUILDING_PURPOSE.NONE:
                self.area_builder.register_change(coords[0], coords[1],
                                                  BUILDING_PURPOSE.TREE, None)
                # TODO: don't ignore the return value
                Builder.create(BUILDINGS.TREE, self.area_builder.land_manager,
                               Point(coords[0], coords[1])).execute()
        return (BUILD_RESULT.OK, building)
示例#14
0
def get_random_possible_ground_unit_position(world):
    """Returns a position in water, that is not at the border of the world"""
    offset = 2
    while True:
        x = world.session.random.randint(world.min_x + offset,
                                         world.max_x - offset)
        y = world.session.random.randint(world.min_y + offset,
                                         world.max_y - offset)

        if (x, y) in world.ground_unit_map:
            continue

        for island in world.islands:
            if (x, y) in island.path_nodes.nodes:
                return Point(x, y)
示例#15
0
def get_random_possible_ground_unit_position(world):
    """Returns a random position upon an island"""
    offset = 2
    while True:
        x = world.session.random.randint(world.min_x + offset,
                                         world.max_x - offset)
        y = world.session.random.randint(world.min_y + offset,
                                         world.max_y - offset)

        if (x, y) in world.ground_unit_map:
            continue

        for island in world.islands:
            if (x, y) in island.path_nodes.nodes:
                return Point(x, y)
    def find_warehouse_location(cls, ship, land_manager):
        """Return the coordinates of a location for the warehouse on the given island."""
        warehouse_class = Entities.buildings[BUILDINGS.WAREHOUSE]
        pos_offsets = []
        for dx in xrange(warehouse_class.width):
            for dy in xrange(warehouse_class.height):
                pos_offsets.append((dx, dy))

        island = land_manager.island
        personality = land_manager.owner.personality_manager.get(
            'FoundSettlement')

        available_spots_list = list(
            sorted(island.terrain_cache.cache[warehouse_class.terrain_type][
                warehouse_class.size].intersection(
                    island.available_land_cache.cache[warehouse_class.size])))
        if not available_spots_list:
            return None

        options = []
        limited_spots = island.session.random.sample(
            available_spots_list,
            min(len(available_spots_list), personality.max_options))
        for (x, y) in limited_spots:
            cost = 0
            for (x2, y2) in land_manager.village:
                dx = x2 - x
                dy = y2 - y
                distance = (dx * dx + dy * dy)**0.5
                if distance < personality.too_close_penalty_threshold:
                    cost += personality.too_close_constant_penalty + personality.too_close_linear_penalty / (
                        distance + 1.0)
                else:
                    cost += distance

            for settlement_manager in land_manager.owner.settlement_managers:
                cost += settlement_manager.settlement.warehouse.position.distance(
                    (x, y)) * personality.linear_warehouse_penalty
            options.append((cost, x, y))

        for _, x, y in sorted(options):
            if ship.check_move(
                    Circle(
                        Point(x + warehouse_class.width // 2,
                              y + warehouse_class.height // 2),
                        BUILDINGS.BUILD.MAX_BUILDING_SHIP_DISTANCE)):
                return (x, y)
        return None
示例#17
0
	def __init__(self, x, y, rotation, owner, island, level=None, **kwargs):
		self.__pre_init(owner, rotation, Point(x, y), level=level)
		super().__init__(x=x, y=y, rotation=rotation, owner=owner,
		                                    island=island, **kwargs)
		self.__init()
		self.island = island

		settlements = self.island.get_settlements(self.position, owner)
		self.settlement = None
		if settlements:
			self.settlement = settlements[0]
		elif owner:
			# create one if we have an owner
			self.settlement = self.island.add_settlement(self.position, self.radius, owner)

		assert self.settlement is None or isinstance(self.settlement, Settlement)
示例#18
0
		def patched_world_location_from_event(self, evt):
			"""Typically we expect a Mock MouseEvent, genereated by `_make_mouse_event`.

			However NavigationTool keeps track of the last event position, which is
			an instance of fife.ScreenPoint.
			"""
			try:
				# fife.MouseEvent
				x = evt.getX()
				y = evt.getY()
			except AttributeError:
				# fife.ScreenPoint
				x = evt.x
				y = evt.y

			return Point(x, y)
示例#19
0
 def build_roads(self):
     """Try to build all roads in the village area, record the result in the field roads_built."""
     all_built = True
     for coords, (purpose, (section, _)) in self.plan.iteritems():
         if section > self.current_section:
             all_built = False
             continue
         if purpose != BUILDING_PURPOSE.ROAD:
             continue
         object = self.island.ground_map[coords].object
         if object is not None and object.id == BUILDINGS.TRAIL:
             continue
         if Builder.create(BUILDINGS.TRAIL, self.land_manager,
                           Point(coords[0], coords[1])).execute() is None:
             all_built = False
     self.roads_built = all_built
def test_get_tile_alignment_action(expected, tiles):
    """Tests for the road/wall orientation code.

	Basically `get_tile_alignment_action` returns the sorted list of fields that the tile in
	position . should connect.


	Tile names:

		h a e
		d . b
		g c f
	"""
    tiles, accessor = make_tiles(tiles)
    aligned = get_tile_alignment_action(Point(0, 0), accessor)
    assert aligned == expected
示例#21
0
    def __init(self, db, island_id, preview):
        """
		Load the actual island from a file
		@param preview: flag, map preview mode
		"""
        p_x, p_y, width, height = db(
            "SELECT MIN(x), MIN(y), (1 + MAX(x) - MIN(x)), (1 + MAX(y) - MIN(y)) FROM ground WHERE island_id = ?",
            island_id - 1001)[0]

        # rect for quick checking if a tile isn't on this island
        # NOTE: it contains tiles, that are not on the island!
        self.rect = Rect(Point(p_x, p_y), width, height)

        self.ground_map = {}
        for (x, y, ground_id, action_id, rotation) in db(
                "SELECT x, y, ground_id, action_id, rotation FROM ground WHERE island_id = ?",
                island_id - 1001):  # Load grounds
            if not preview:  # actual game, need actual tiles
                ground = Entities.grounds[str(
                    '%d-%s' % (ground_id, action_id))](self.session, x, y)
                ground.act(rotation)
            else:
                ground = MapPreviewTile(x, y, ground_id)
            # These are important for pathfinding and building to check if the ground tile
            # is blocked in any way.
            self.ground_map[(ground.x, ground.y)] = ground

        self._init_cache()

        self.settlements = []
        self.wild_animals = []
        self.num_trees = 0

        # define the rectangle with the smallest area that contains every island tile its position
        min_x = min(zip(*self.ground_map.keys())[0])
        max_x = max(zip(*self.ground_map.keys())[0])
        min_y = min(zip(*self.ground_map.keys())[1])
        max_y = max(zip(*self.ground_map.keys())[1])
        self.position = Rect.init_from_borders(min_x, min_y, max_x, max_y)

        if not preview:  # this isn't needed for previews, but it is in actual games
            self.path_nodes = IslandPathNodes(self)

            # repopulate wild animals every 2 mins if they die out.
            Scheduler().add_new_object(self.check_wild_animal_population, self,
                                       Scheduler().get_ticks(120), -1)
        """TUTORIAL:
示例#22
0
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)
示例#23
0
    def _round_map_coords(self, map_x, map_y):
        """Returns the coordinates of an event at the map.

		Why roundhalfplus?

		        a      b     a-b   round(a)-round(b)  roundplus(a)-roundplus(b)

		       1.50   0.50   1.00       1.00               1.0
		       0.50  -0.49   0.99       1.00               1.0
		      -0.49  -1.49   1.00       1.00               1.0
		Error: 0.50  -0.50   1.00       2.00               1.0

		This error would result in fields at position 0 to be smaller than the others,
		because both sides (-0.5 and 0.5) would be wrongly assigned to the other fields.

		@return Point with int coordinates"""
        return Point(roundhalfplus(map_x), roundhalfplus(map_y))
示例#24
0
	def build(self, settlement_manager, resource_id):
		production_builder = settlement_manager.production_builder
		purpose = self.get_purpose(resource_id)
		if not production_builder.unused_fields[purpose]:
			return (BUILD_RESULT.NEED_PARENT_FIRST, None)
		if not self.have_resources(settlement_manager):
			return (BUILD_RESULT.NEED_RESOURCES, None)

		assert production_builder.unused_fields[purpose], 'expected field spot to be available'
		coords = production_builder.unused_fields[purpose][0]
		builder = Builder.create(self.id, settlement_manager.land_manager, Point(coords[0], coords[1]))
		building = builder.execute()
		if not building:
			return (BUILD_RESULT.UNKNOWN_ERROR, None)
		production_builder.unused_fields[purpose].popleft()
		production_builder.register_change(coords[0], coords[1], purpose, None)
		return (BUILD_RESULT.OK, building)
示例#25
0
	def execute(self, land_manager, ship=None):
		"""Build the building."""
		building_class = Entities.buildings[self.building_id]
		building_level = building_class.get_initial_level(land_manager.owner)
		action_set_id = building_class.get_random_action_set(level = building_level)

		build_position = Entities.buildings[self.building_id].check_build(land_manager.session,
		    Point(*self.coords), rotation=self.rotations[self.orientation],
		    check_settlement=(ship is None), ship=ship, issuer=land_manager.owner)
		assert build_position.buildable

		cmd = Build(self.building_id, self.coords[0], self.coords[1], land_manager.island,
			self._get_rotation(land_manager.session, build_position.rotation),
			settlement=land_manager.settlement, ship=ship, tearset=build_position.tearset,
			action_set_id=action_set_id)
		result = cmd(land_manager.owner)
		assert result
		return result
示例#26
0
		def high(i=0):
			i += 1
			render_name = self._get_render_name("highlight")+str(tup)
			self.minimap_image.set_drawing_enabled()
			self.minimap_image.rendertarget.removeAll(render_name)
			if i > STEPS:
				if finish_callback:
					finish_callback()
				return
			part = i # grow bigger
			if i > STEPS // 2: # after the first half
				part = STEPS-i  # become smaller

			radius = MIN_RAD + int(( float(part) / (STEPS // 2) ) * (MAX_RAD - MIN_RAD) )

			for x, y in Circle( Point(*tup), radius=radius ).get_border_coordinates():
				self.minimap_image.rendertarget.addPoint(render_name, fife.Point(x, y), *color)

			ExtScheduler().add_new_object(lambda : high(i), self, INTERVAL, loops=1)
示例#27
0
	def _make_surrounding_transparent(self, building):
		"""Makes the surrounding of building_position transparent and hide buildings
		that are built upon (tearset)"""
		world_contains = self.session.world.map_dimensions.contains_without_border
		get_tile = self.session.world.get_tile
		for coord in building.position.get_radius_coordinates(self.nearby_objects_radius, include_self=True):
			p = Point(*coord)
			if not world_contains(p):
				continue
			tile = get_tile(p)
			if tile.object is not None and tile.object.buildable_upon:
				inst = tile.object.fife_instance
				inst.get2dGfxVisual().setTransparency(BUILDINGS.TRANSPARENCY_VALUE)
				self._transparencified_instances.add(weakref.ref(inst))

		for to_tear_worldid in building.tearset:
			inst = WorldObject.get_object_by_id(to_tear_worldid).fife_instance
			inst.get2dGfxVisual().setTransparency(255) # full transparency = hidden
			self._transparencified_instances.add(weakref.ref(inst))
示例#28
0
    def fire_all_weapons(self, dest, rotated=False, bullet_delay=0):
        """
		Fires all weapons in storage at a given position
		@param dest: Point with the given position
		@param rotated: If True weapons will be fired at different locations, rotated around dest
			override to True for units that need to fire at rotated coords
		"""
        self.log.debug("%s fire all weapons", self)
        self._fired_weapons_number = 0
        if not self.can_attack_position(dest):
            self.log.debug("%s can't attack this position", self)
            return

        if not rotated:
            for weapon in self._fireable:
                weapon.fire(dest, self.position.center, bullet_delay)
        else:
            angle = (math.pi / 60) * (-len(self._fireable) / 2)
            cos = math.cos(angle)
            sin = math.sin(angle)

            x = self.position.center.x
            y = self.position.center.y

            dest_x = dest.x
            dest_y = dest.y

            dest_x = (dest_x - x) * cos - (dest_y - y) * sin + x
            dest_y = (dest_x - x) * sin + (dest_y - y) * cos + y

            angle = math.pi / 60
            cos = math.cos(angle)
            sin = math.sin(angle)

            for weapon in self._fireable:
                destination = Point(dest_x, dest_y)
                weapon.fire(destination, self.position.center, bullet_delay)
                dest_x = (dest_x - x) * cos - (dest_y - y) * sin + x
                dest_y = (dest_x - x) * sin + (dest_y - y) * cos + y

        if self._fired_weapons_number != 0:
            self.act_attack(dest)
示例#29
0
	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
示例#30
0
	def check_build_line(cls, session, point1, point2, rotation=45, ship=None):

		# Pathfinding currently only supports buildingsize 1x1, so don't use it in this case
		if cls.size != (1, 1):
			return [ cls.check_build_fuzzy(session, point2, rotation=rotation, ship=ship) ]

		# use pathfinding to get a path, then try to build along it
		island = session.world.get_island(point1)
		if island is None:
			return []

		if cls.id == BUILDINGS.TRAIL:
			nodes = island.path_nodes.nodes
		elif cls.id == BUILDINGS.BARRIER:
			# Allow nodes that can be walked upon and existing barriers when finding a
			# build path
			nodes = ChainedContainer(island.path_nodes.nodes, island.barrier_nodes.nodes)
		else:
			raise Exception('BuildableLine does not support building id {0}'.format(cls.id))

		path = a_star_find_path(point1.to_tuple(), point2.to_tuple(), nodes, rotation in (45, 225))
		if path is None: # can't find a path between these points
			return [] # TODO: maybe implement alternative strategy

		possible_builds = []

		#TODO duplicates recalculation code in world.building.path
		for x, y in path:
			action = ''
			for action_char, (xoff, yoff) in \
			    sorted(BUILDINGS.ACTION.action_offset_dict.items()): # order is important here
				if action_char in 'abcd' and (xoff + x, yoff + y) in path:
					action += action_char
			if action == '':
				action = 'single' # single trail piece with no neighbors

			build = cls.check_build(session, Point(x, y))
			build.action = action
			possible_builds.append(build)

		return possible_builds
    def check_build_line(cls, session, point1, point2, rotation=45, ship=None):

        # Pathfinding currently only supports buildingsize 1x1, so don't use it in this case
        if cls.size != (1, 1):
            return [
                cls.check_build_fuzzy(session,
                                      point2,
                                      rotation=rotation,
                                      ship=ship)
            ]

        # use pathfinding to get a path, then try to build along it
        island = session.world.get_island(point1)
        if island is None:
            return []

        path = RoadPathFinder()(island.path_nodes.nodes, point1.to_tuple(),
                                point2.to_tuple(), rotation == 45
                                or rotation == 225)
        if path is None:  # can't find a path between these points
            return []  # TODO: maybe implement alternative strategy

        possible_builds = []

        #TODO duplicates recalculation code in world.building.path
        for x, y in path:
            action = ''
            for action_char, (xoff, yoff) in \
                sorted(BUILDINGS.ACTION.action_offset_dict.iteritems()): # order is important here
                if action_char in 'abcd' and (xoff + x, yoff + y) in path:
                    action += action_char
            if action == '':
                action = 'single'  # single trail piece with no neighbours

            build = cls.check_build(session, Point(x, y))
            build.action = action
            possible_builds.append(build)

        return possible_builds
示例#32
0
    def _load(self, db, worldid):
        super(Pirate, self)._load(db, worldid)
        self.__init()

        remaining_ticks, = db(
            "SELECT remaining_ticks FROM ai_pirate WHERE rowid = ?",
            worldid)[0]
        Scheduler().add_new_object(Callback(self.tick), self, remaining_ticks,
                                   -1, self.tick_interval)

        remaining_ticks_long, = db(
            "SELECT remaining_ticks_long FROM ai_pirate WHERE rowid = ?",
            worldid)[0]
        Scheduler().add_new_object(Callback(self.tick_long), self,
                                   remaining_ticks_long, -1,
                                   self.tick_interval)

        home = db("SELECT x, y FROM pirate_home_point")[0]
        self.home_point = Point(home[0], home[1])

        self.log.debug("Pirate: home at (%d, %d), radius %d",
                       self.home_point.x, self.home_point.y, self.home_radius)
示例#33
0
 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
示例#34
0
	def __init__(self, *args):
		if len(args) == 2 and isinstance(args[0], Point) and isinstance(args[1], Point): #args: edge1, edge2
			self.top = min(args[0].y, args[1].y)
			self.left = min(args[0].x, args[1].x)
			self.right = max(args[0].x, args[1].x)
			self.bottom = max(args[0].y, args[1].y)
		elif len(args) == 3 and isinstance(args[0], Point) and isinstance(args[1], int) and isinstance(args[2], int): #args: position, width, height
			self.top = args[0].y
			self.left = args[0].x
			self.right = self.left + args[1]
			self.bottom = self.top + args[2]
		elif len(args) == 4 and isinstance(args[0], int) and isinstance(args[1], int) and isinstance(args[2], int) and isinstance(args[3], int):
			self.top = min(args[1], args[3])
			self.left = min(args[0], args[2])
			self.right = max(args[0], args[2])
			self.bottom = max(args[1], args[3])

		else:
			assert False

		# Convenience attributes (can be used to make code more easy to read/understand)
		self.origin = Point(self.left, self.top)
示例#35
0
    def create(cls, area_builder, x, y, new_field_purpose):
        building_id = None
        if new_field_purpose == BUILDING_PURPOSE.POTATO_FIELD:
            building_id = BUILDINGS.POTATO_FIELD
        elif new_field_purpose == BUILDING_PURPOSE.PASTURE:
            building_id = BUILDINGS.PASTURE
        elif new_field_purpose == BUILDING_PURPOSE.SUGARCANE_FIELD:
            building_id = BUILDINGS.SUGARCANE_FIELD
        elif new_field_purpose == BUILDING_PURPOSE.TOBACCO_FIELD:
            building_id = BUILDINGS.TOBACCO_FIELD
        builder = Builder.create(building_id, area_builder.land_manager,
                                 Point(x, y))
        if not builder:
            return None

        value = 0
        personality = area_builder.owner.personality_manager.get(
            'ModifiedFieldEvaluator')
        if new_field_purpose == BUILDING_PURPOSE.POTATO_FIELD:
            value += personality.add_potato_field_value
        elif new_field_purpose == BUILDING_PURPOSE.PASTURE:
            value += personality.add_pasture_value
        elif new_field_purpose == BUILDING_PURPOSE.SUGARCANE_FIELD:
            value += personality.add_sugarcane_field_value
        elif new_field_purpose == BUILDING_PURPOSE.TOBACCO_FIELD:
            value += personality.add_tobacco_field_value

        old_field_purpose = area_builder.plan[(x, y)][0]
        if old_field_purpose == BUILDING_PURPOSE.POTATO_FIELD:
            value -= personality.remove_unused_potato_field_penalty
        elif old_field_purpose == BUILDING_PURPOSE.PASTURE:
            value -= personality.remove_unused_pasture_penalty
        elif old_field_purpose == BUILDING_PURPOSE.SUGARCANE_FIELD:
            value -= personality.remove_unused_sugarcane_field_penalty
        elif old_field_purpose == BUILDING_PURPOSE.TOBACCO_FIELD:
            value -= personality.remove_unused_tobacco_field_penalty
        return ModifiedFieldEvaluator(area_builder, builder, value,
                                      old_field_purpose)
示例#36
0
def spawn_ships(session, owner_id, ship_id, number, *position):
    """
	Creates a number of ships controlled by a certain player around a position on the map.
	@param owner_id: the owner worldid
	@param ship_id: the ship id
	@param number: number of ships to be spawned
	@param position: position around the ships to be spawned
	"""
    center = Point(*position)
    player = WorldObject.get_object_by_id(owner_id)
    # calculate a radius that should fit all the ships
    # if it doesn't fit them all increase the radius
    radius = int(math.sqrt(number))
    while number != 0:
        for point in Circle(center, radius):
            if (point.x, point.y) in session.world.ship_map \
             or session.world.get_island(point) is not None:
                continue
            CreateUnit(owner_id, ship_id, point.x, point.y)(issuer=player)
            number -= 1
            if number == 0:
                break
        radius += 1
示例#37
0
	def _recalculate(self, where=None, dump_data=False):
		"""Calculate which pixel of the minimap should display what and draw it
		@param where: Rect of minimap coords. Defaults to self.location
		@param dump_data: Don't draw but return calculated data"""
		self.minimap_image.set_drawing_enabled()

		rt = self.minimap_image.rendertarget
		render_name = self._get_render_name("base")

		if where is None:
			where = self.location
			rt.removeAll(render_name)

		# calculate which area of the real map is mapped to which pixel on the minimap
		pixel_per_coord_x, pixel_per_coord_y = self._world_to_minimap_ratio

		# calculate values here so we don't have to do it in the loop
		pixel_per_coord_x_half_as_int = int(pixel_per_coord_x/2)
		pixel_per_coord_y_half_as_int = int(pixel_per_coord_y/2)

		real_map_point = Point(0, 0)
		world_min_x = self.world.min_x
		world_min_y = self.world.min_y
		get_island_tuple = self.world.get_island_tuple
		island_col = self.COLORS["island"]
		location_left = self.location.left
		location_top = self.location.top
		if dump_data:
			data = []
			drawPoint = lambda name, fife_point, r, g, b : data.append( (fife_point.x, fife_point.y, r, g, b) )
		else:
			drawPoint = rt.addPoint
		fife_point = fife.Point(0,0)

		use_rotation = self._get_rotation_setting()

		# loop through map coordinates, assuming (0, 0) is the origin of the minimap
		# this faciliates calculating the real world coords
		for x in xrange(where.left-self.location.left, where.left+where.width-self.location.left):
			# Optimisation: remember last island
			last_island = None
			island = None
			for y in xrange(where.top-self.location.top, where.top+where.height-self.location.top):

				"""
				This code should be here, but since python can't do inlining, we have to inline
				ourselves for performance reasons
				covered_area = Rect.init_from_topleft_and_size(
				  int(x * pixel_per_coord_x)+world_min_x, \
				  int(y * pixel_per_coord_y)+world_min_y), \
				  int(pixel_per_coord_x), int(pixel_per_coord_y))
				real_map_point = covered_area.center
				"""
				# use center of the rect that the pixel covers
				real_map_point.x = int(x*pixel_per_coord_x)+world_min_x + \
											pixel_per_coord_x_half_as_int
				real_map_point.y = int(y*pixel_per_coord_y)+world_min_y + \
											pixel_per_coord_y_half_as_int
				real_map_point_tuple = (real_map_point.x, real_map_point.y)

				# check what's at the covered_area
				if last_island is not None and real_map_point_tuple in last_island.ground_map:
					island = last_island
				else:
					island = get_island_tuple(real_map_point_tuple)
				if island is not None:
					last_island = island
					# this pixel is an island
					settlement = island.get_settlement(real_map_point)
					if settlement is None:
						# island without settlement
						color = island_col
					else:
						# pixel belongs to a player
						color = settlement.owner.color.to_tuple()
				else:
					continue

				if use_rotation:
					# inlined _get_rotated_coords
					rot_x, rot_y = self._rotate( (location_left + x, location_top + y), self._rotations)
					fife_point.set(rot_x - location_left, rot_y - location_top)
				else:
					fife_point.set(x, y)

				drawPoint(render_name, fife_point, *color)

		if dump_data:
			return json.dumps( data )