def perform(level, box, options): logging.info("BoundingBox coordinates: ({},{}),({},{}),({},{})".format( box.miny, box.maxy, box.minx, box.maxx, box.minz, box.maxz)) # ==== PREPARATION ===== logging.info("Options : {}".format(options)) logging.info("Preparation") (width, height, depth) = toolbox.getBoxSize(box) logging.info("Selection box dimensions {}, {}, {}".format( width, height, depth)) world = toolbox.generateMatrix(level, box, width, depth, height) world_space = toolbox.dotdict({ "y_min": 0, "y_max": height - 1, "x_min": 0, "x_max": width - 1, "z_min": 0, "z_max": depth - 1 }) logging.info("Generating simple height map") simple_height_map = toolbox.getSimpleHeightMap( level, box) #no height = -1 when water like block logging.info("Saving and erasing the trees") tree_list = TreeGestion.prepareMap( world, simple_height_map ) #get a list of all trees and erase them, so we can put some of them back after logging.info("Generating normal height map") height_map = toolbox.getHeightMap(level, box) logging.info("Preparing settlement deck card") cityDeck = toolbox.generateCityDeck(options["Settlement type"], width, depth) logging.info("Setting the settlement type") tree_counter = TreeGestion.countTreeSpecies(tree_list) logging.info( "Counting the occurrence of the different tree species in the area") wood_material = TreeGestion.selectWoodFromTreeCounter(tree_counter) # ==== PARTITIONING OF NEIGHBOURHOODS ==== logging.info( "Partitioning of the map, getting city center and neighbourhoods") (center, neighbourhoods) = generateCenterAndNeighbourhood(world_space, height_map) all_buildings = [] # ==== GENERATING CITY CENTER ==== logging.info("Generating city center") minimum_h = 50 minimum_w = 25 mininum_d = 25 iterate = 100 minimum_lots = 6 available_lots = 0 maximum_tries = 50 current_try = 0 threshold = 20 partitioning_list = [] temp_partitioning_list = [] # run the partitioning algorithm for iterate times to get different partitionings of the same area logging.info( "Generating {} different partitionings for the the City Centre {}". format(iterate, center)) while available_lots < minimum_lots and current_try < maximum_tries: for i in range(iterate): # generate a partitioning through some algorithm if RNG.random() < 0.5: partitioning = binarySpacePartitioning(center[0], center[1], center[2], center[3], center[4], center[5], []) else: partitioning = quadtreeSpacePartitioning( center[0], center[1], center[2], center[3], center[4], center[5], []) # 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 = [] cond1 = toolbox.hasValidGroundBlocks(x_min, x_max, z_min, z_max, height_map) if cond1 == False: failed_conditions.append(1) cond2 = toolbox.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 = toolbox.hasAcceptableSteepness( x_min, x_max, z_min, z_max, height_map, toolbox.getScoreArea_type4, threshold) if cond3 == False: failed_conditions.append(3) if cond1 and cond2 and cond3: score = toolbox.getScoreArea_type4(height_map, x_min, x_max, z_min, z_max) valid_partitioning.append((score, p)) logging.info("Passed the 3 conditions!") else: logging.info( "Failed Conditions {}".format(failed_conditions)) partitioning_list.extend(valid_partitioning) logging.info( "Generated a partition with {} valid lots and {} invalids ones" .format(len(valid_partitioning), len(partitioning) - len(valid_partitioning))) # sort partitions by steepness partitioning_list = sorted(partitioning_list) final_partitioning = toolbox.getNonIntersectingPartitions( partitioning_list) available_lots = len(final_partitioning) logging.info( "Current partitioning with most available_lots: {}, current threshold {}" .format(available_lots, threshold)) threshold += 2 current_try += 1 logging.info("Final lots ({}) for the City Centre {}: ".format( len(final_partitioning), center)) for (score, partition) in final_partitioning: logging.info("\t{}".format(partition)) #for (score, partition) in final_partitioning: # #building = generateBuilding(world, partition, height_map, simple_height_map) # wood_material = TreeGestion.selectWoodFromTreeCounter(tree_counter) # logging.info("Wood material used : {}".format(wood_material)) # building = generateStructureFromDeck(world, score, partition, height_map, simple_height_map, wood_material, cityDeck, "center") # all_buildings.append(building) l = len(final_partitioning) fountain = generateFountain(world, final_partitioning[0][1], height_map, simple_height_map) all_buildings.append(fountain) for i in range(1, l): wood_material = TreeGestion.selectWoodFromTreeCounter(tree_counter) logging.info("Wood material used : {}".format(wood_material)) score = i / (l * 1.0) # turns the result to float building = generateStructureFromDeck(world, score, final_partitioning[i][1], height_map, simple_height_map, wood_material, cityDeck, "center") all_buildings.append(building) # ==== GENERATING NEIGHBOURHOODS ==== logging.info("Generating neighbourhoods") minimum_h = 10 minimum_w = 16 mininum_d = 16 iterate = 100 maximum_tries = 80 current_try = 0 minimum_lots = 50 available_lots = 0 threshold = 50 partitioning_list = [] final_partitioning = [] while available_lots < minimum_lots and current_try < maximum_tries: partitioning_list = [] for i in range(iterate): for neigh in neighbourhoods: logging.info( "Generating {} different partitionings for the neighbourhood {}" .format(iterate, neigh)) if RNG.random() < 0.5: partitioning = binarySpacePartitioning( neigh[0], neigh[1], neigh[2], neigh[3], neigh[4], neigh[5], []) else: partitioning = quadtreeSpacePartitioning( neigh[0], neigh[1], neigh[2], neigh[3], neigh[4], neigh[5], []) 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 = [] cond1 = toolbox.hasValidGroundBlocks( x_min, x_max, z_min, z_max, height_map) if cond1 == False: failed_conditions.append(1) cond2 = toolbox.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 = toolbox.hasAcceptableSteepness( x_min, x_max, z_min, z_max, height_map, toolbox.getScoreArea_type4, threshold) if cond3 == False: failed_conditions.append(3) if cond1 and cond2 and cond3: score = toolbox.getScoreArea_type4( height_map, x_min, x_max, z_min, z_max) valid_partitioning.append((score, p)) logging.info("Passed the 3 conditions!") else: logging.info( "Failed Conditions {}".format(failed_conditions)) partitioning_list.extend(valid_partitioning) logging.info( "Generated a partition with {} valid lots and {} invalids ones" .format(len(valid_partitioning), len(partitioning) - len(valid_partitioning))) temp_partitioning_list.extend(partitioning_list) # sort partitions by steepness temp_partitioning_list = sorted(temp_partitioning_list) final_partitioning = toolbox.getNonIntersectingPartitions( temp_partitioning_list) available_lots = len(final_partitioning) logging.info( "Current neighbourhood partitioning with most available_lots: {}, current threshold {}" .format(available_lots, threshold)) threshold += 2 current_try += 1 logging.info("Final lots ({})for the neighbourhood {}: ".format( len(final_partitioning), neigh)) for (score, partition) in final_partitioning: logging.info("\t{}".format(partition)) logging.info("Building in the neighbourhood") #for (score, partition) in final_partitioning: # wood_material = TreeGestion.selectWoodFromTreeCounter(tree_counter) # logging.info("Wood material used : {}".format(wood_material)) # building = generateStructureFromDeck(world, score, partition, height_map, simple_height_map, wood_material, cityDeck, "neighbourhood") # all_buildings.append(building) l = len(final_partitioning) for i in range(l): wood_material = TreeGestion.selectWoodFromTreeCounter(tree_counter) logging.info("Wood material used : {}".format(wood_material)) score = i / (l * 1.0) # turns the result to float building = generateStructureFromDeck(world, score, final_partitioning[i][1], height_map, simple_height_map, wood_material, cityDeck, "neighbourhood") all_buildings.append(building) #n = 0 #for i in xrange(0, int(len(final_partitioning) * 0.50) + 1): # house = generateHouse(world, final_partitioning[i], height_map, simple_height_map) # all_buildings.append(house) # logging.info("House number : {} built on lot number {}".format(n + 1, i + 1)) # n += 1 #n = 0 #for i in xrange(int(len(final_partitioning) * 0.50) + 1, int(len(final_partitioning) * 0.70) + 1): # # generate either a regular farm or a smiley farm # farm = generateFarm(world, final_partitioning[i], height_map, simple_height_map) if (RNG.randint(0, 2) == 0) else generateFarm(world, final_partitioning[i], height_map, simple_height_map, "smiley") # all_buildings.append(farm) # logging.info("Farm number : {} built on lot number {}".format(n + 1, i + 1)) # n += 1 #n = 0 #m = 0 #for i in xrange(int(len(final_partitioning)*0.70)+1, len(final_partitioning)): # RollerCoaster = generateRollerCoaster(world, final_partitioning[i], height_map, simple_height_map) # if RollerCoaster.type == "tower": # all_buildings.append(RollerCoaster) # logging.info("Tower number : {} built on lot number {}".format(n + 1, i + 1)) # n += 1 # else: # logging.info("RollerCoaster number : {} built on lot number {}".format(m + 1, i + 1)) # m += 1 # ==== GENERATE THE TrainLine NETWORK ==== if options["allow Train Line"] == True: wood_material = "urban" if options[ "Train Line Style"] == "Urban" else TreeGestion.selectWoodFromTreeCounter( tree_counter) stations = generateTrainLine(world, center, height_map, simple_height_map, wood_material, cityDeck.getNbStations()) for station in stations: all_buildings.append(station) # ==== GENERATE PATH MAP ==== # generate a path map that gives the cost of moving to each neighbouring cell logging.info("Generating path map and simple path map") pathMap = toolbox.getPathMap(height_map, width, depth) simple_pathMap = toolbox.getPathMap(simple_height_map, width, depth) #not affected by water # ==== CONNECTING BUILDINGS WITH ROADS ==== logging.info("Calling MST on {} buildings".format(len(all_buildings))) MST = toolbox.getMST_Manhattan(all_buildings) for m in MST: p1 = m[1] p2 = m[2] if p1.type == "farm" or p2.type == "farm": pavement_Type = "Grass" bridge_Type = "Wood" else: pavement_Type = "Stone" bridge_Type = "Stone" try: logging.info( "Trying to find a path between {} and {}, finding potential bridges" .format(p1.entranceLot, p2.entranceLot)) simple_path = toolbox.simpleAStar( p1.entranceLot, p2.entranceLot, simple_pathMap, simple_height_map) #water and height are not important list_end_points = toolbox.findBridgeEndPoints( world, simple_path, simple_height_map) if list_end_points != []: for i in xrange(0, len(list_end_points), 2): logging.info( "Found water between {} and {}. Trying to generating a {} bridge..." .format(list_end_points[i], list_end_points[i + 1], bridge_Type)) Bridge.generateBridge(world, simple_height_map, list_end_points[i], list_end_points[i + 1], bridge_Type) list_end_points.insert(0, p1.entranceLot) list_end_points.append(p2.entranceLot) for i in xrange(0, len(list_end_points), 2): path = toolbox.aStar(list_end_points[i], list_end_points[i + 1], pathMap, height_map) logging.info( "Connecting end points of the bridge(s), Generating {} road between {} and {}" .format(pavement_Type, list_end_points[i], list_end_points[i + 1])) Path.generatePath(world, path, height_map, pavement_Type) else: logging.info( "No potential bridge found, Generating road between {} and {}" .format(list_end_points[i], list_end_points[i + 1])) Path.generatePath(world, simple_path, height_map, pavement_Type) except: logging.info( "Bridge found but is not buildable, Trying to find a path between {} and {} avoiding water" .format(p1.entranceLot, p2.entranceLot)) path = toolbox.aStar(p1.entranceLot, p2.entranceLot, pathMap, height_map) if path != None: logging.info( "Path found, Generating {} road between {} and {}".format( pavement_Type, p1.entranceLot, p2.entranceLot)) Path.generatePath(world, path, height_map, pavement_Type) else: logging.info( "Couldnt find path between {} and {}. Generating a straight road" .format(p1.entranceLot, p2.entranceLot)) #Path.generatePath_StraightLine(world, p1.entranceLot[1], p1.entranceLot[2], p2.entranceLot[1], p2.entranceLot[2], height_map, pavement_Type) # ==== PUT BACK UNTOUCHED TREES ==== logging.info("Putting back untouched trees") TreeGestion.putBackTrees( world, height_map, tree_list ) #put back the trees that are not cut buy the building and are not in unwanted places # ==== UPDATE WORLD ==== if options["Generation"] == True: logging.info("Generating the world") world.updateWorld() else: logging.info("Generation set to false, stops here")
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)
def perform(level, box, options): logging.info("BoundingBox coordinates: ({},{}),({},{}),({},{})".format( box.miny, box.maxy, box.minx, box.maxx, box.minz, box.maxz)) # ==== PREPARATION ===== (width, height, depth) = utilityFunctions.getBoxSize(box) logging.info("Selection box dimensions {}, {}, {}".format( width, height, depth)) world = utilityFunctions.generateMatrix(level, box, width, depth, height) world_space = utilityFunctions.dotdict({ "y_min": 0, "y_max": height - 1, "x_min": 0, "x_max": width - 1, "z_min": 0, "z_max": depth - 1 }) height_map = utilityFunctions.getHeightMap(level, box) # ==== PARTITIONING OF NEIGHBOURHOODS ==== (center, neighbourhoods) = generateCenterAndNeighbourhood(world_space, height_map) all_buildings = [] # ==== GENERATING CITY CENTER ==== minimum_h = 50 minimum_w = 25 mininum_d = 25 iterate = 100 minimum_lots = 6 available_lots = 0 maximum_tries = 50 current_try = 0 threshold = 1 partitioning_list = [] temp_partitioning_list = [] # run the partitioning algorithm for iterate times to get different partitionings of the same area logging.info( "Generating {} different partitionings for the the City Centre {}". format(iterate, center)) while available_lots < minimum_lots and current_try < maximum_tries: for i in range(iterate): # generate a partitioning through some algorithm if RNG.random() < 0.5: partitioning = binarySpacePartitioning(center[0], center[1], center[2], center[3], center[4], center[5], []) else: partitioning = quadtreeSpacePartitioning( center[0], center[1], center[2], center[3], center[4], center[5], []) # 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 = [] cond1 = utilityFunctions.hasValidGroundBlocks( x_min, x_max, z_min, z_max, height_map) if cond1 == False: failed_conditions.append(1) 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 cond1 and cond2 and cond3: score = utilityFunctions.getScoreArea_type1( height_map, x_min, x_max, z_min, z_max) 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 lots and {} invalids ones" .format(len(valid_partitioning), len(partitioning) - len(valid_partitioning))) # order partitions by steepness partitioning_list = sorted(partitioning_list) final_partitioning = utilityFunctions.getNonIntersectingPartitions( partitioning_list) available_lots = len(final_partitioning) logging.info( "Current partitioning with most available_lots: {}, current threshold {}" .format(available_lots, threshold)) threshold += 1 current_try += 1 logging.info("Final lots ({}) for the City Centre {}: ".format( len(final_partitioning), center)) for p in final_partitioning: logging.info("\t{}".format(p)) for partition in final_partitioning: building = generateBuilding(world, partition, height_map) all_buildings.append(building) # ==== GENERATING NEIGHBOURHOODS ==== minimum_h = 3 minimum_w = 7 mininum_d = 6 iterate = 100 maximum_tries = 50 current_try = 0 minimum_lots = 20 available_lots = 0 threshold = 1 partitioning_list = [] final_partitioning = [] while available_lots < minimum_lots and current_try < maximum_tries: partitioning_list = [] for i in range(iterate): for neigh in neighbourhoods: logging.info( "Generating {} different partitionings for the neighbourhood {}" .format(iterate, neigh)) if RNG.random() < 0.5: partitioning = binarySpacePartitioning( neigh[0], neigh[1], neigh[2], neigh[3], neigh[4], neigh[5], []) else: partitioning = quadtreeSpacePartitioning( neigh[0], neigh[1], neigh[2], neigh[3], neigh[4], neigh[5], []) 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 = [] cond1 = utilityFunctions.hasValidGroundBlocks( x_min, x_max, z_min, z_max, height_map) if cond1 == False: failed_conditions.append(1) 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 cond1 and cond2 and cond3: score = utilityFunctions.getScoreArea_type1( height_map, x_min, x_max, z_min, z_max) valid_partitioning.append((score, p)) logging.info("Passed the 3 conditions!") else: logging.info( "Failed Conditions {}".format(failed_conditions)) partitioning_list.extend(valid_partitioning) logging.info( "Generated a partition with {} valid lots and {} invalids ones" .format(len(valid_partitioning), len(partitioning) - len(valid_partitioning))) temp_partitioning_list.extend(partitioning_list) # order partitions by steepness temp_partitioning_list = sorted(temp_partitioning_list) final_partitioning = utilityFunctions.getNonIntersectingPartitions( temp_partitioning_list) available_lots = len(final_partitioning) logging.info( "Current neighbourhood partitioning with most available_lots: {}, current threshold {}" .format(available_lots, threshold)) threshold += 1 current_try += 1 logging.info("Final lots ({})for the neighbourhood {}: ".format( len(final_partitioning), neigh)) for p in final_partitioning: logging.info("\t{}".format(p)) for partition in final_partitioning: house = generateHouse(world, partition, height_map) all_buildings.append(house) # ==== GENERATE PATH MAP ==== # generate a path map that gives the cost of moving to each neighbouring cell pathMap = utilityFunctions.getPathMap(height_map, width, depth) # ==== CONNECTING BUILDINGS WITH ROADS ==== logging.info("Calling MST on {} buildings".format(len(all_buildings))) MST = utilityFunctions.getMST_Manhattan(all_buildings, pathMap, height_map) pavementBlockID = 4 pavementBlockSubtype = 0 for m in MST: p1 = m[1] p2 = m[2] logging.info("Pavement with distance {} between {} and {}".format( m[0], p1.entranceLot, p2.entranceLot)) path = utilityFunctions.aStar(p1.entranceLot, p2.entranceLot, pathMap, height_map) if path != None: logging.info( "Found path between {} and {}. Generating road...".format( p1.entranceLot, p2.entranceLot)) GeneratePath.generatPath(world, path, height_map, (pavementBlockID, pavementBlockSubtype)) else: logging.info( "Couldnt find path between {} and {}. Generating a straight road between them..." .format(p1.entranceLot, p2.entranceLot)) GeneratePath.generatPath_StraightLine( world, p1.entranceLot[1], p1.entranceLot[2], p2.entranceLot[1], p2.entranceLot[2], height_map, (pavementBlockID, pavementBlockSubtype)) # ==== UPDATE WORLD ==== world.updateWorld()
def perform(level, box, options): logging.info("BoundingBox coordinates: ({},{}),({},{}),({},{})".format( box.miny, box.maxy, box.minx, box.maxx, box.minz, box.maxz)) # ==== PREPARATION ===== (width, height, depth) = utilityFunctions.getBoxSize(box) logging.info("Selection box dimensions {}, {}, {}".format( width, height, depth)) world = utilityFunctions.generateMatrix(level, box, width, depth, height) world_space = utilityFunctions.dotdict({ "y_min": 0, "y_max": height - 1, "x_min": 0, "x_max": width - 1, "z_min": 0, "z_max": depth - 1 }) height_map = utilityFunctions.getHeightMap(level, box, None, False) # === Wood quantity and Biome analyzer === # air_like = [ 0, 4, 5, 6, 20, 23, 29, 30, 35, 37, 38, 39, 40, 44, 46, 47, 50, 59, 66, 83, 85, 86, 95, 102, 104, 105, 107, 126, 141, 142, 160, 175 ] wood_height_map = utilityFunctions.getHeightMap(level, box, air_like, True) (usable_wood, biome) = EnvironmentAnalyzer.determinate_usable_wood( level, wood_height_map, box.minx, box.maxx, box.minz, box.maxz) # === City stats === # biome_with_well = ['Desert', 'Badlands'] APARTMENT_SIZE = 2 HOUSE_SIZE = 4 GREENHOUSE_CAPACITY = 15 inhabitants = 0 greenhouse_count = 0 well_count = 0 # ==== PARTITIONING OF THE SELECTION IN AREA IN ORDER TO FLATTEN ==== # Work in progress do not use #earthwork_height_map = utilityFunctions.getHeightMap(level,box, None, True) #area_partitioning_and_flattening(world_space, earthwork_height_map, world, biome) # ==== PARTITIONING OF NEIGHBOURHOODS ==== (center, neighbourhoods) = generateCenterAndNeighbourhood(world_space, height_map) all_buildings = [] # ==== GENERATING CITY CENTER ==== minimum_h = 50 minimum_w = 25 mininum_d = 25 iterate = 100 minimum_lots = 6 available_lots = 0 maximum_tries = 50 current_try = 0 threshold = 1 partitioning_list = [] temp_partitioning_list = [] # run the partitioning algorithm for iterate times to get different partitionings of the same area logging.info( "Generating {} different partitionings for the the City Centre {}". format(iterate, center)) while available_lots < minimum_lots and current_try < maximum_tries: for i in range(iterate): # generate a partitioning through some algorithm if RNG.random() < 0.5: partitioning = binarySpacePartitioning(center[0], center[1], center[2], center[3], center[4], center[5], []) else: partitioning = quadtreeSpacePartitioning( center[0], center[1], center[2], center[3], center[4], center[5], []) # 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 = [] cond1 = utilityFunctions.hasValidGroundBlocks( x_min, x_max, z_min, z_max, height_map) if cond1 == False: failed_conditions.append(1) 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 cond1 and cond2 and cond3: score = utilityFunctions.getScoreArea_type1( height_map, x_min, x_max, z_min, z_max) 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 lots and {} invalids ones" .format(len(valid_partitioning), len(partitioning) - len(valid_partitioning))) # order partitions by steepness partitioning_list = sorted(partitioning_list) final_partitioning = utilityFunctions.getNonIntersectingPartitions( partitioning_list) available_lots = len(final_partitioning) logging.info( "Current partitioning with most available_lots: {}, current threshold {}" .format(available_lots, threshold)) threshold += 1 current_try += 1 logging.info("Final lots ({}) for the City Centre {}: ".format( len(final_partitioning), center)) for p in final_partitioning: logging.info("\t{}".format(p)) for partition in final_partitioning: building, apartments_inhabitants = generateBuilding( world, partition, height_map, usable_wood, biome) inhabitants += apartments_inhabitants all_buildings.append(building) # ==== GENERATING NEIGHBOURHOODS ==== minimum_h = 10 minimum_w = 16 mininum_d = 16 iterate = 100 maximum_tries = 50 current_try = 0 minimum_lots = 20 available_lots = 0 threshold = 1 partitioning_list = [] final_partitioning = [] while available_lots < minimum_lots and current_try < maximum_tries: partitioning_list = [] for i in range(iterate): for neigh in neighbourhoods: logging.info( "Generating {} different partitionings for the neighbourhood {}" .format(iterate, neigh)) if RNG.random() < 0.5: partitioning = binarySpacePartitioning( neigh[0], neigh[1], neigh[2], neigh[3], neigh[4], neigh[5], []) else: partitioning = quadtreeSpacePartitioning( neigh[0], neigh[1], neigh[2], neigh[3], neigh[4], neigh[5], []) 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 = [] cond1 = utilityFunctions.hasValidGroundBlocks( x_min, x_max, z_min, z_max, height_map) if cond1 == False: failed_conditions.append(1) 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 cond1 and cond2 and cond3: score = utilityFunctions.getScoreArea_type1( height_map, x_min, x_max, z_min, z_max) valid_partitioning.append((score, p)) logging.info("Passed the 3 conditions!") else: logging.info( "Failed Conditions {}".format(failed_conditions)) partitioning_list.extend(valid_partitioning) logging.info( "Generated a partition with {} valid lots and {} invalids ones" .format(len(valid_partitioning), len(partitioning) - len(valid_partitioning))) temp_partitioning_list.extend(partitioning_list) # order partitions by steepness temp_partitioning_list = sorted(temp_partitioning_list) final_partitioning = utilityFunctions.getNonIntersectingPartitions( temp_partitioning_list) available_lots = len(final_partitioning) logging.info( "Current neighbourhood partitioning with most available_lots: {}, current threshold {}" .format(available_lots, threshold)) threshold += 1 current_try += 1 logging.info("Final lots ({})for the neighbourhood {}: ".format( len(final_partitioning), neigh)) for p in final_partitioning: logging.info("\t{}".format(p)) for partition in final_partitioning: if well_count < 1 and biome in biome_with_well: well = generateWell(world, partition, height_map, biome) well_count += 1 all_buildings.append(well) elif greenhouse_count * GREENHOUSE_CAPACITY < inhabitants: greenhouse = generateGreenhouse(world, partition, height_map, usable_wood, biome) greenhouse_count += 1 all_buildings.append(greenhouse) else: house = generateHouse(world, partition, height_map, usable_wood, biome) inhabitants += RNG.randint(1, HOUSE_SIZE) all_buildings.append(house) # ==== GENERATE PATH MAP ==== # generate a path map that gives the cost of moving to each neighbouring cell pathMap = utilityFunctions.getPathMap(height_map, width, depth) # ==== CONNECTING BUILDINGS WITH ROADS ==== logging.info("Calling MST on {} buildings".format(len(all_buildings))) MST = utilityFunctions.getMST_Manhattan(all_buildings, pathMap, height_map) pavementBlockID = BlocksInfo.getPavmentId(biome) for m in MST: p1 = m[1] p2 = m[2] logging.info("Pavement with distance {} between {} and {}".format( m[0], p1.entranceLot, p2.entranceLot)) path = utilityFunctions.aStar(p1.entranceLot, p2.entranceLot, pathMap, height_map) if path != None: logging.info( "Found path between {} and {}. Generating road...".format( p1.entranceLot, p2.entranceLot)) GeneratePath.generatPath(world, path, height_map, pavementBlockID) else: logging.info( "Couldnt find path between {} and {}. Generating a straight road between them..." .format(p1.entranceLot, p2.entranceLot)) GeneratePath.generatPath_StraightLine(world, p1.entranceLot[1], p1.entranceLot[2], p2.entranceLot[1], p2.entranceLot[2], height_map, pavementBlockID) # ==== UPDATE WORLD ==== world.updateWorld()