Exemplo n.º 1
0
    def extend_settlement_with_storage(self, target_position):
        """Build a storage to extend the settlement towards the given position. Return a BUILD_RESULT constant."""
        if not self.have_resources(BUILDINGS.STORAGE):
            return BUILD_RESULT.NEED_RESOURCES

        storage_class = Entities.buildings[BUILDINGS.STORAGE]
        storage_spots = self.island.terrain_cache.get_buildability_intersection(
            storage_class.terrain_type, storage_class.size,
            self.settlement.buildability_cache, self.buildability_cache)
        storage_surrounding_offsets = Rect.get_surrounding_offsets(
            storage_class.size)
        coastline = self.land_manager.coastline

        options = []
        for (x, y) in sorted(storage_spots):
            builder = BasicBuilder.create(BUILDINGS.STORAGE, (x, y), 0)

            alignment = 1
            for (dx, dy) in storage_surrounding_offsets:
                coords = (x + dx, y + dy)
                if coords in coastline or coords not in self.plan or self.plan[
                        coords][0] != BUILDING_PURPOSE.NONE:
                    alignment += 1

            distance = distances.distance_rect_rect(target_position,
                                                    builder.position)
            value = distance - alignment * 0.7
            options.append((-value, builder))
        return self.build_best_option(options, BUILDING_PURPOSE.STORAGE)
	def extend_settlement_with_storage(self, target_position):
		"""Build a storage to extend the settlement towards the given position. Return a BUILD_RESULT constant."""
		if not self.have_resources(BUILDINGS.STORAGE):
			return BUILD_RESULT.NEED_RESOURCES

		storage_class = Entities.buildings[BUILDINGS.STORAGE]
		storage_spots = self.island.terrain_cache.get_buildability_intersection(storage_class.terrain_type,
			storage_class.size, self.settlement.buildability_cache, self.buildability_cache)
		storage_surrounding_offsets = Rect.get_surrounding_offsets(storage_class.size)
		coastline = self.land_manager.coastline

		options = []
		for (x, y) in sorted(storage_spots):
			builder = BasicBuilder.create(BUILDINGS.STORAGE, (x, y), 0)

			alignment = 1
			for (dx, dy) in storage_surrounding_offsets:
				coords = (x + dx, y + dy)
				if coords in coastline or coords not in self.plan or self.plan[coords][0] != BUILDING_PURPOSE.NONE:
					alignment += 1

			distance = distances.distance_rect_rect(target_position, builder.position)
			value = distance - alignment * 0.7
			options.append((-value, builder))
		return self.build_best_option(options, BUILDING_PURPOSE.STORAGE)
Exemplo n.º 3
0
    def _enlarge_collector_area(self):
        if not self.production_builder.have_resources(BUILDINGS.STORAGE):
            return BUILD_RESULT.NEED_RESOURCES

        moves = [(-1, 0), (0, -1), (0, 1),
                 (1, 0)]  # valid moves for collectors
        collector_area = self.production_builder.get_collector_area()
        coastline = self.land_manager.coastline

        # area_label contains free tiles in the production area and all road tiles
        area_label = dict.fromkeys(
            self.land_manager.roads)  # {(x, y): area_number, ...}
        for coords, (purpose, _) in self.production_builder.plan.iteritems():
            if coords not in coastline and purpose == BUILDING_PURPOSE.NONE:
                area_label[coords] = None

        areas = 0
        for coords in collector_area:
            assert coords not in coastline
            if coords in area_label and area_label[coords] is not None:
                continue

            queue = deque([coords])
            while queue:
                x, y = queue[0]
                queue.popleft()
                for dx, dy in moves:
                    coords2 = (x + dx, y + dy)
                    if coords2 in area_label and area_label[coords2] is None:
                        area_label[coords2] = areas
                        queue.append(coords2)
            areas += 1

        coords_set_by_area = defaultdict(lambda: set())
        for coords, area_number in area_label.iteritems():
            if coords in self.production_builder.plan and self.production_builder.plan[
                    coords][
                        0] == BUILDING_PURPOSE.NONE and coords not in collector_area:
                coords_set_by_area[area_number].add(coords)

        storage_class = Entities.buildings[BUILDINGS.STORAGE]
        storage_spots = self.island.terrain_cache.get_buildability_intersection(
            storage_class.terrain_type, storage_class.size,
            self.settlement.buildability_cache,
            self.production_builder.buildability_cache)
        storage_surrounding_offsets = Rect.get_surrounding_offsets(
            storage_class.size)

        options = []
        num_offsets = int(
            len(self._radius_offsets) * self.personality.overlap_precision)
        radius_offsets = self.session.random.sample(self._radius_offsets,
                                                    num_offsets)
        for coords in sorted(storage_spots):
            if coords not in area_label:
                continue
            x, y = coords

            area_number = area_label[coords]
            area_coords_set = coords_set_by_area[area_number]
            useful_area = 0
            for dx, dy in radius_offsets:
                coords = (x + dx, y + dy)
                if coords in area_coords_set:
                    useful_area += 1
            if not useful_area:
                continue

            alignment = 1
            builder = BasicBuilder.create(BUILDINGS.STORAGE, (x, y), 0)
            for (dx, dy) in storage_surrounding_offsets:
                coords = (x + dx, y + dy)
                if coords in coastline or coords not in self.production_builder.plan or self.production_builder.plan[
                        coords][0] != BUILDING_PURPOSE.NONE:
                    alignment += 1

            value = useful_area + alignment * self.personality.alignment_coefficient
            options.append((value, builder))

        if options:
            return self.production_builder.build_best_option(
                options, BUILDING_PURPOSE.STORAGE)

        # enlarge the settlement area instead since just enlarging the collector area is impossible
        if self.village_builder.tent_queue:
            tent_size = Entities.buildings[BUILDINGS.RESIDENTIAL].size
            tent_radius = Entities.buildings[BUILDINGS.RESIDENTIAL].radius
            best_coords = None
            best_area = 0

            for x, y in self.village_builder.tent_queue:
                new_area = 0
                for coords in Rect.init_from_topleft_and_size(
                        x, y, tent_size[0],
                        tent_size[1]).get_radius_coordinates(tent_radius):
                    if coords in area_label and coords not in self.land_manager.roads and coords not in collector_area:
                        new_area += 1
                if new_area > best_area:
                    best_coords = (x, y)
                    best_area = new_area
            if best_coords is not None:
                return self.village_builder.extend_settlement_with_tent(
                    Rect.init_from_topleft_and_size_tuples(
                        best_coords, tent_size))
        return BUILD_RESULT.IMPOSSIBLE
	def _enlarge_collector_area(self):
		if not self.production_builder.have_resources(BUILDINGS.STORAGE):
			return BUILD_RESULT.NEED_RESOURCES

		moves = [(-1, 0), (0, -1), (0, 1), (1, 0)] # valid moves for collectors
		collector_area = self.production_builder.get_collector_area()
		coastline = self.land_manager.coastline

		# area_label contains free tiles in the production area and all road tiles
		area_label = dict.fromkeys(self.land_manager.roads) # {(x, y): area_number, ...}
		for coords, (purpose, _) in self.production_builder.plan.iteritems():
			if coords not in coastline and purpose == BUILDING_PURPOSE.NONE:
				area_label[coords] = None

		areas = 0
		for coords in collector_area:
			assert coords not in coastline
			if coords in area_label and area_label[coords] is not None:
				continue

			queue = deque([coords])
			while queue:
				x, y = queue.popleft()
				for dx, dy in moves:
					coords2 = (x + dx, y + dy)
					if coords2 in area_label and area_label[coords2] is None:
						area_label[coords2] = areas
						queue.append(coords2)
			areas += 1

		coords_set_by_area = defaultdict(set)
		for coords, area_number in area_label.iteritems():
			if coords in self.production_builder.plan and self.production_builder.plan[coords][0] == BUILDING_PURPOSE.NONE and coords not in collector_area:
				coords_set_by_area[area_number].add(coords)

		storage_class = Entities.buildings[BUILDINGS.STORAGE]
		storage_spots = self.island.terrain_cache.get_buildability_intersection(storage_class.terrain_type,
			storage_class.size, self.settlement.buildability_cache, self.production_builder.buildability_cache)
		storage_surrounding_offsets = Rect.get_surrounding_offsets(storage_class.size)

		options = []
		num_offsets = int(len(self._radius_offsets) * self.personality.overlap_precision)
		radius_offsets = self.session.random.sample(self._radius_offsets, num_offsets)
		for coords in sorted(storage_spots):
			if coords not in area_label:
				continue
			x, y = coords

			area_number = area_label[coords]
			area_coords_set = coords_set_by_area[area_number]
			useful_area = 0
			for dx, dy in radius_offsets:
				coords = (x + dx, y + dy)
				if coords in area_coords_set:
					useful_area += 1
			if not useful_area:
				continue

			alignment = 1
			builder = BasicBuilder.create(BUILDINGS.STORAGE, (x, y), 0)
			for (dx, dy) in storage_surrounding_offsets:
				coords = (x + dx, y + dy)
				if coords in coastline or coords not in self.production_builder.plan or self.production_builder.plan[coords][0] != BUILDING_PURPOSE.NONE:
					alignment += 1

			value = useful_area + alignment * self.personality.alignment_coefficient
			options.append((value, builder))

		if options:
			return self.production_builder.build_best_option(options, BUILDING_PURPOSE.STORAGE)

		# enlarge the settlement area instead since just enlarging the collector area is impossible
		if self.village_builder.tent_queue:
			tent_size = Entities.buildings[BUILDINGS.RESIDENTIAL].size
			tent_radius = Entities.buildings[BUILDINGS.RESIDENTIAL].radius
			best_coords = None
			best_area = 0

			for x, y in self.village_builder.tent_queue:
				new_area = 0
				for coords in Rect.init_from_topleft_and_size(x, y, tent_size[0], tent_size[1]).get_radius_coordinates(tent_radius):
					if coords in area_label and coords not in self.land_manager.roads and coords not in collector_area:
						new_area += 1
				if new_area > best_area:
					best_coords = (x, y)
					best_area = new_area
			if best_coords is not None:
				return self.village_builder.extend_settlement_with_tent(Rect.init_from_topleft_and_size_tuples(best_coords, tent_size))
		return BUILD_RESULT.IMPOSSIBLE