Beispiel #1
0
 def calc_z_splits(self, offset):
     """
     Calculate horizontal splitting lines for the segment of surface map specified by offset (vertical offset)
         - Uses a depth first algorithm to create splitting lines.
     :params offset: vertical offset within the surface map. This is defined by the x_split
     :returns: a list of z values to specify the horizontal splitting lines for the current vertical offset
             within the surface map.
     """
     partition_lines = []
     segments = []
     if self.z_length / 2 > self.MIN_YARD_SIZE[1]:
         segments.append((self.z_length, 0))
     while len(segments) > 0:
         top, bottom = segments.pop()
         # NOTE: z_start+bottom and z_end+top are used as seeds to ensure different divisors
         rand_div = float(
             rand_range(self.z_start + bottom + offset,
                        self.z_end + top + offset, 230, 170)) / 100
         curr = bottom + (int(round(float(top - bottom) / rand_div)))
         partition_lines.append(curr)
         if (top - curr + 1) / 2 > self.MIN_YARD_SIZE[1]:
             segments.append((top, curr + 1))
         if (curr - bottom) / 2 > self.MIN_YARD_SIZE[1]:
             segments.append((curr, bottom))
     partition_lines.append(self.z_length)
     partition_lines.sort()
     return partition_lines
Beispiel #2
0
 def calc_x_splits(self):
     """
     Calculate vertical splitting lines for the surface map
         - Uses a depth first algorithm to create splitting lines.
     :returns: a list of x values to specify the vertical splitting line.
     """
     partition_lines = []
     segments = []
     if self.x_length / 2 > self.MIN_YARD_SIZE[0]:
         segments.append((self.x_length, 0))
     while len(segments) > 0:
         top, bottom = segments.pop()
         # NOTE: x_start+bottom and x_end+top are used as seeds to ensure different divisors
         rand_div = float(
             rand_range(self.x_start + bottom, self.x_end + top, 230,
                        170)) / 100
         curr = bottom + (int(round(float(top - bottom) / rand_div)))
         partition_lines.append(curr)
         if (top - curr + 1) / 2 > self.MIN_YARD_SIZE[0]:
             segments.append((top, curr + 1))
         if (curr - bottom) / 2 > self.MIN_YARD_SIZE[0]:
             segments.append((curr, bottom))
     partition_lines.append(self.x_length)
     partition_lines.sort()
     return partition_lines
Beispiel #3
0
    def generate_building_door_blocks(self, new_surface, partition):
        """
        Generate a single door block on the edge of the building lot
        :params new_surface: a post CA Surface object to be modified and returned
        :params x_start, x_end, z_start, z_end: the current partition bounds
        :returns: a modified new_surface that has the building door cells set
            (also fills the self.building_doors list with coords to the door block)
        """

        x_start, x_end, z_start, z_end = self.get_partition_bounds(partition)

        option = rand_range(x_start, z_start, 3,
                            0)  # pick one of four options for door placement
        curr = (x_end - ((x_end - x_start) / 2),
                (z_end - ((z_end - z_start) / 2))
                )  # set curr to center of yard
        if new_surface.surface_map[curr[0]][curr[1]].type != Block.BUILDING:
            # if center block is not a building lot, return
            return new_surface

        # OPTION 1: look for yard edge to the left
        if option == 0:
            while self.within_bounds(
                    new_surface, curr
            ) and new_surface.surface_map[curr[0]][curr[1]].type != Block.YARD:
                curr = (curr[0] + 1, curr[1])
            curr = (curr[0] - 1, curr[1])

        # OPTION 2: look for yard edge to the right
        elif option == 1:
            while self.within_bounds(
                    new_surface, curr
            ) and new_surface.surface_map[curr[0]][curr[1]].type != Block.YARD:
                curr = (curr[0] - 1, curr[1])
            curr = (curr[0] + 1, curr[1])

        # OPTION 3: look for yard edge upward
        elif option == 2:
            while self.within_bounds(
                    new_surface, curr
            ) and new_surface.surface_map[curr[0]][curr[1]].type != Block.YARD:
                curr = (curr[0], curr[1] + 1)
            curr = (curr[0], curr[1] - 1)

        # OPTION 4: look for yard edge to the downward
        elif option == 3:
            while self.within_bounds(
                    new_surface, curr
            ) and new_surface.surface_map[curr[0]][curr[1]].type != Block.YARD:
                curr = (curr[0], curr[1] - 1)
            curr = (curr[0], curr[1] + 1)
        self.building_door_blocks.append(curr)
        new_surface.surface_map[curr[0]][curr[1]].type = Block.BUILDING_DOOR
        return new_surface
Beispiel #4
0
    def generate_building_lots(self, new_surface, partition):
        """
        Generate a single building lot within the yard within the given partition
        :params new_surface: a post CA Surface object to be modified and returned
        :params x_start, x_end, z_start, z_end: the current partition bounds
        :returns: a modified new_surface that has the building lots set
            (also fills the self.building_coords list with tuples of coords to the corners of the building)
        """

        x_start, x_end, z_start, z_end = self.get_partition_bounds(partition)

        # Random Growth Rate for the building lots
        growth_1 = rand_range(x_start, z_start, 2, 1)
        growth_2 = 3 - growth_1

        # starting in center of yard
        corners = ((x_end - ((x_end - x_start) / 2),
                    (z_end - (z_end - z_start) / 2)),
                   (x_end - ((x_end - x_start) / 2),
                    (z_end - (z_end - z_start) / 2)))

        # extend corners down and right until not valid, then back up one extension step
        while self.are_valid_corners(new_surface, corners):
            corners = ((corners[0][0] - growth_1, corners[0][1] - growth_2),
                       (corners[1][0], corners[1][1]))
        corners = ((corners[0][0] + growth_1, corners[0][1] + growth_2),
                   (corners[1][0], corners[1][1]))

        # extend corners up and left until not valid, then back up one extension step
        while self.are_valid_corners(new_surface, corners):
            corners = ((corners[0][0], corners[0][1]),
                       (corners[1][0] + growth_2, corners[1][1] + growth_1))
        corners = ((corners[0][0], corners[0][1]), (corners[1][0] - growth_2,
                                                    corners[1][1] - growth_1))

        building_lot_area = abs(corners[1][0] -
                                corners[0][0]) * abs(corners[1][1] -
                                                     corners[0][1])
        if building_lot_area > YardGenerator.MIN_BUILDING_AREA:
            # if building lot of good size add to building coords and mark blocks in cells as buildings
            self.building_coords.append(corners)
            for i in range(corners[0][0], corners[1][0]):
                for j in range(corners[0][1], corners[1][1]):
                    new_surface.surface_map[i][j].type = Block.BUILDING
        else:
            # else erase the entire yard as it is not able to hold a valid building lot
            for i in range(x_start, x_end):
                for j in range(z_start, z_end):
                    new_surface.surface_map[i][j].type = Block.UNASSIGNED
        return new_surface