def prepareLot(matrix, p, height_map, biome): areaScore = utilityFunctions.getScoreArea_type1(height_map, p[2],p[3], p[4], p[5], height_map[p[2]][p[4]]) logging.info("Preparing lot {} with score {}".format(p, areaScore)) if areaScore != 0: terrain_height = flattenPartition(matrix, p[2],p[3], p[4], p[5], height_map, biome) logging.info("Terrain was flattened at height {}".format(terrain_height)) utilityFunctions.updateHeightMap(height_map, p[2], p[3], p[4], p[5], terrain_height) h = matrix.getMatrixY(terrain_height) else: heightCounts = utilityFunctions.getHeightCounts(height_map, p[2],p[3], p[4], p[5]) terrain_height = max(heightCounts, key=heightCounts.get) logging.info("No changes in terrain were necessary, terrain at height {}".format(terrain_height)) utilityFunctions.updateHeightMap(height_map, p[2], p[3], p[4], p[5], terrain_height) # update the ground with the grass block for x in range(x_min, x_max): for z in range(z_min,z_max): matrix.setValue(terrain_height, x, z, ground) h = matrix.getMatrixY(terrain_height) logging.info("Index of height {} in selection box matrix: {}".format(terrain_height, h)) return h
def flattenPartition(matrix, x_min, x_max, z_min, z_max, height_map, block): heightCounts = utilityFunctions.getHeightCounts(height_map, x_min, x_max, z_min, z_max) most_ocurred_height = max(heightCounts, key=heightCounts.get) logging.info("Flattening {}".format((x_min, x_max, z_min, z_max))) if block == None: block = utilityFunctions.getMostOcurredGroundBlock( matrix, height_map, x_min, x_max, z_min, z_max) if block == (3, 0): block = (2, 0) logging.info("Most occurred ground block: {}".format(block)) logging.info("Flattening at height {}".format(most_ocurred_height)) for x in range(x_min, x_max + 1): for z in range(z_min, z_max + 1): if height_map[x][z] == most_ocurred_height: # Equal height! No flattening needed # but lets use the base block just in case matrix.setValue(height_map[x][z], x, z, block) if height_map[x][z] != most_ocurred_height: if height_map[x][z] == -1: logging.warning( "Flattening invalid area. Position ", x, z, " of height_map is -1. Cannot do earthworks.") continue matrix_height = matrix.getMatrixY(height_map[x][z]) desired_matrix_height = matrix.getMatrixY(most_ocurred_height) if desired_matrix_height > matrix_height: for y in range(matrix_height, desired_matrix_height + 1): matrix.setValue(y, x, z, block) else: #update every block between top height and the desired height # when bringing the ground to a lower level, this will have the # effect of e.g. erasing trees that were on top of that block # this may cause some things to be unproperly erased # (e.g. a branch of a tree coming from an nearby block) # but this is probably the best/less complex solution for this for y in range(matrix.height - 1, desired_matrix_height, -1): matrix.setValue(y, x, z, 0) matrix.setValue(desired_matrix_height, x, z, block) return most_ocurred_height
def prepareLot(matrix, p, height_map, block): areaScore = utilityFunctions.getScoreArea_type4(height_map, p[2], p[3], p[4], p[5]) logging.info("Preparing lot {} with score {}".format(p, areaScore)) if areaScore != 0: terrain_height = flattenPartition(matrix, p[2], p[3], p[4], p[5], height_map, block) logging.info( "Terrain was flattened at height {}".format(terrain_height)) utilityFunctions.updateHeightMap(height_map, p[2], p[3], p[4], p[5], terrain_height) h = matrix.getMatrixY(terrain_height) else: heightCounts = utilityFunctions.getHeightCounts( height_map, p[2], p[3], p[4], p[5]) terrain_height = max(heightCounts, key=heightCounts.get) logging.info( "No changes in terrain were necessary, terrain at height {}". format(terrain_height)) utilityFunctions.updateHeightMap(height_map, p[2], p[3], p[4], p[5], terrain_height) # update the ground with the most occured block if block == None: block = utilityFunctions.getMostOcurredGroundBlock( matrix, height_map, p[2], p[3], p[4], p[5]) if block == (3, 0): block = (2, 0) for x in range(p[2], p[3] + 1): for z in range(p[4], p[5] + 1): matrix.setValue(terrain_height, x, z, block) h = matrix.getMatrixY(terrain_height) logging.info("Index of height {} in selection box matrix: {}".format( terrain_height, h)) return h
def flattenPartition(matrix, x_min, x_max, z_min, z_max, height_map, biome, shifting = 12): x_min_height_count = x_min - shifting if x_min - shifting >= 0 else 0 x_max_height_count = x_max + shifting if x_max + shifting < matrix.width else matrix.width - 1 z_min_height_count = z_min - shifting if z_min - shifting >= 0 else 0 z_max_height_count = z_max + shifting if z_max + shifting < matrix.depth else matrix.depth - 1 heightCounts = utilityFunctions.getHeightCounts(height_map, x_min_height_count, x_max_height_count, z_min_height_count, z_max_height_count) average_height = max(heightCounts, key=heightCounts.get) #count = 0 #for key in heightCounts.keys() : # value = heightCounts[key] # if value > round((x_max_height_count - x_min_height_count) * (z_max_height_count - z_min_height_count) * 0.01) : # average_height += key * value # count += value #average_height = average_height / count logging.info("Flattening {}".format((x_min, x_max, z_min, z_max))) base_block = utilityFunctions.getMostOcurredGroundBlock(matrix, height_map, x_min, x_max, z_min, z_max) if base_block == BlocksInfo.SAND_ID and biome == 'Badlands' : base_block = BlocksInfo.RED_SAND_ID elif base_block == BlocksInfo.DIRT_ID and biome == 'Taiga' : base_block = BlocksInfo.PODZOL_ID if base_block == BlocksInfo.TERRACOTTA_ID : #Temporary need change underground_block = BlocksInfo.TERRACOTTA_ID else : underground_block = BlocksInfo.getUndergroundBlockId(base_block) logging.info("Most occurred ground block: {}".format(base_block)) logging.info("Flattening at height {}".format(average_height)) saved_trees = utilityFunctions.saveTreesInArea(matrix, height_map, average_height, x_min, x_max, z_min, z_max) for x in range(x_min, x_max): for z in range(z_min,z_max): if height_map[x][z] == average_height: # Equal height! No flattening needed # but lets use the base block just in case matrix.setValue(height_map[x][z], x, z, base_block) if height_map[x][z] != average_height: if height_map[x][z] == -1: logging.warning("Flattening invalid area. Position ", x, z, " of height_map is -1. Cannot do earthworks.") continue matrix_height = matrix.getMatrixY(height_map[x][z]) desired_matrix_height = matrix.getMatrixY(average_height) if desired_matrix_height > matrix_height: for y in range(matrix_height, desired_matrix_height): matrix.setValue(y,x,z, underground_block) matrix.setValue(desired_matrix_height, x, z, base_block) else: for y in range(matrix.height-1, desired_matrix_height, -1): value = utilityFunctions.getBlockAndBlockData(matrix, y, x, z) if type(value) == tuple : value = value[0] if not value in BlocksInfo.LEAVES_ID : matrix.setValue(y, x, z, BlocksInfo.AIR_ID) matrix.setValue(desired_matrix_height,x,z, base_block) utilityFunctions.repositionateTrees(matrix, saved_trees, average_height, x_min, x_max, z_min, z_max) return average_height
def area_partitioning_and_flattening(space, height_map, matrix, biome): minimum_h = 10 minimum_w = 40 mininum_d = 40 iterate = 100 maximum_tries = 50 current_try = 0 minimum_lots = 100 #origin = 20 available_lots = 0 threshold = 10 partitioning_list = [] final_partitioning = [] while available_lots < minimum_lots and current_try < maximum_tries: partitioning_list = [] for i in range(iterate): # generate a partitioning through some algorithm if RNG.random() < 0.5: partitioning = binarySpacePartitioning( space.y_min, space.y_max, space.x_min, space.x_max, space.z_min, space.z_max, []) else: partitioning = quadtreeSpacePartitioning( space.y_min, space.y_max, space.x_min, space.x_max, space.z_min, space.z_max, []) # remove invalid partitions from the partitioning valid_partitioning = [] for p in partitioning: (y_min, y_max, x_min, x_max, z_min, z_max) = (p[0], p[1], p[2], p[3], p[4], p[5]) failed_conditions = [] #cond2 = utilityFunctions.hasMinimumSize(y_min, y_max, x_min, x_max,z_min,z_max, minimum_h, minimum_w, mininum_d) #if cond2 == False: failed_conditions.append(2) cond3 = utilityFunctions.hasAcceptableSteepness( x_min, x_max, z_min, z_max, height_map, utilityFunctions.getScoreArea_type1, threshold) if cond3 == False: failed_conditions.append(3) if cond3: heightCounts = utilityFunctions.getHeightCounts( height_map, x_min, x_max, z_min, z_max) score = max(heightCounts, key=heightCounts.get) valid_partitioning.append((score, p)) else: logging.info( "Failed Conditions {}".format(failed_conditions)) partitioning_list.extend(valid_partitioning) logging.info( "Generated a partition with {} valid area and {} invalids ones" .format(len(valid_partitioning), len(partitioning) - len(valid_partitioning))) # order partitions by steepness partitioning_list = sorted(partitioning_list) final_partitioning = utilityFunctions.fusionIntersectingPartitions( partitioning_list, height_map) available_lots = len(final_partitioning) logging.info( "Current partitioning with most available_lots: {}, current threshold {}" .format(available_lots, threshold)) threshold = threshold + 1 if threshold < 20 else 20 current_try += 1 for partition in final_partitioning: prepareArea(matrix, partition, height_map, biome)