def generateSlopeStructure(matrix, height_map, h_max, x_min, x_max, z_min, z_max, allowStraightRails=False): logging.info("Trying to generate roller coaster") cleanProperty(matrix, height_map, h_max, x_min, x_max, z_min, z_max) #spawnFlowers(matrix, height_map, x_min, x_max, z_min, z_max) return_value = generateRollerCoaster(matrix, height_map, h_max, x_min, x_max, z_min, z_max, allowStraightRails) if return_value == 0: return 0 slope = utilityFunctions.dotdict() slope.type = "rollerCoaster" slope.lotArea = utilityFunctions.dotdict({ "y_min": 0, "y_max": h_max, "x_min": x_min, "x_max": x_max, "z_min": z_min, "z_max": z_max }) slope.buildArea = utilityFunctions.dotdict({ "y_min": 0, "y_max": h_max, "x_min": x_min, "x_max": x_max, "z_min": z_min, "z_max": z_max }) slope.orientation = getOrientation() slope.entranceLot = (height_map[x_min][z_min], slope.lotArea.x_min, slope.lotArea.z_min) return slope
def generateHouse(matrix, h_min, h_max, x_min, x_max, z_min, z_max, biome, usable_wood): house = utilityFunctions.dotdict() house.type = "house" house.lotArea = utilityFunctions.dotdict({ "y_min": h_min, "y_max": h_max, "x_min": x_min, "x_max": x_max, "z_min": z_min, "z_max": z_max }) #generateFence(matrix, h_min, x_min, x_max, z_min, z_max) (h_min, h_max, x_min, x_max, z_min, z_max) = getHouseAreaInsideLot(h_min, h_max, x_min, x_max, z_min, z_max) # calculate the top height of the walls, i.e. where the first # row of blocks of the pitched roof will be placed ceiling_bottom = h_max - int((h_max - h_min) * 0.5) house.buildArea = utilityFunctions.dotdict({ "y_min": h_min, "y_max": ceiling_bottom, "x_min": x_min, "x_max": x_max, "z_min": z_min, "z_max": z_max }) logging.info("Generating house at area {}".format(house.lotArea)) logging.info("Construction area {}".format(house.buildArea)) utilityFunctions.cleanProperty2(matrix, house.lotArea.y_min + 1, house.lotArea.y_max, x_min - 1, x_max + 1, z_min - 1, z_max + 1) picked_wood = utilityFunctions.selectRandomWood(usable_wood) floor = BlocksInfo.getHouseFloorId(biome, picked_wood) wall = BlocksInfo.getHouseWallId(biome) wall = BlocksInfo.getPlankId(picked_wood) if wall[0] == -1 else wall pillar = BlocksInfo.getHousePillarId(wall, picked_wood) ceiling = BlocksInfo.getStairsId(biome, picked_wood) roof = BlocksInfo.getStructureBlockId(biome, picked_wood) pavement_block = BlocksInfo.getPavmentId(biome) house.orientation = getOrientation(matrix, house.lotArea) window_y = house.buildArea.y_min + 3 door_y = house.buildArea.y_min + 1 if house.orientation == "N": door_x = RNG.randint(house.buildArea.x_min + 4, house.buildArea.x_max - 4) door_z = house.buildArea.z_min utilityFunctions.cleanProperty2(matrix, h_min + 1, h_max, door_x - 1, door_x + 1, house.lotArea.z_min + 1, z_min - 1) # generate walls from x_min+1, x_max-1, etc to leave space for the roof generateWalls(matrix, house.buildArea.y_min, house.buildArea.y_max, house.buildArea.x_min, house.buildArea.x_max, house.buildArea.z_min, house.buildArea.z_max, wall, pillar) generateFloor(matrix, house.buildArea.y_min, house.buildArea.x_min, house.buildArea.x_max, house.buildArea.z_min, house.buildArea.z_max, floor) generateDoor(matrix, door_y, door_x, door_z, (64, 9), (64, 1)) house.entranceLot = (h_min + 1, door_x, house.lotArea.z_min) # entrance path for z in range(house.lotArea.z_min, door_z): matrix.setValue(h_min, door_x, z, pavement_block) matrix.setValue(h_min, door_x - 1, z, pavement_block) matrix.setValue(h_min, door_x + 1, z, pavement_block) elif house.orientation == "S": door_x = RNG.randint(house.buildArea.x_min + 4, house.buildArea.x_max - 4) door_z = house.buildArea.z_max utilityFunctions.cleanProperty2(matrix, h_min + 1, h_max, door_x - 1, door_x + 1, z_max + 1, house.lotArea.z_max - 1) # generate walls from x_min+1, x_max-1, etc to leave space for the roof generateWalls(matrix, house.buildArea.y_min, house.buildArea.y_max, house.buildArea.x_min, house.buildArea.x_max, house.buildArea.z_min, house.buildArea.z_max, wall, pillar) generateFloor(matrix, house.buildArea.y_min, house.buildArea.x_min, house.buildArea.x_max, house.buildArea.z_min, house.buildArea.z_max, floor) generateDoor(matrix, door_y, door_x, door_z, (64, 9), (64, 3)) house.entranceLot = (h_min + 1, door_x, house.lotArea.z_max) # entrance path for z in range(door_z + 1, house.lotArea.z_max): matrix.setValue(h_min, door_x, z, pavement_block) matrix.setValue(h_min, door_x - 1, z, pavement_block) matrix.setValue(h_min, door_x + 1, z, pavement_block) elif house.orientation == "W": door_x = house.buildArea.x_min door_z = RNG.randint(house.buildArea.z_min + 4, house.buildArea.z_max - 4) utilityFunctions.cleanProperty2(matrix, h_min + 1, h_max, house.lotArea.x_min + 1, x_min - 1, door_z - 1, door_z + 1) # generate walls from x_min+1, x_max-1, etc to leave space for the roof generateWalls(matrix, house.buildArea.y_min, house.buildArea.y_max, house.buildArea.x_min, house.buildArea.x_max, house.buildArea.z_min, house.buildArea.z_max, wall, pillar) generateFloor(matrix, house.buildArea.y_min, house.buildArea.x_min, house.buildArea.x_max, house.buildArea.z_min, house.buildArea.z_max, floor) generateDoor(matrix, door_y, door_x, door_z, (64, 8), (64, 0)) house.entranceLot = (h_min + 1, house.lotArea.x_min, door_z) # entrance path for x in range(house.lotArea.x_min, door_x): matrix.setValue(h_min, x, door_z, pavement_block) matrix.setValue(h_min, x, door_z - 1, pavement_block) matrix.setValue(h_min, x, door_z + 1, pavement_block) elif house.orientation == "E": door_x = house.buildArea.x_max door_z = RNG.randint(house.buildArea.z_min + 4, house.buildArea.z_max - 4) utilityFunctions.cleanProperty2(matrix, h_min + 1, h_max, x_max + 1, house.lotArea.x_max - 1, door_z - 1, door_z + 1) # generate walls from x_min+1, x_max-1, etc to leave space for the roof generateWalls(matrix, house.buildArea.y_min, house.buildArea.y_max, house.buildArea.x_min, house.buildArea.x_max, house.buildArea.z_min, house.buildArea.z_max, wall, pillar) generateFloor(matrix, house.buildArea.y_min, house.buildArea.x_min, house.buildArea.x_max, house.buildArea.z_min, house.buildArea.z_max, floor) generateDoor(matrix, door_y, door_x, door_z, (64, 9), (64, 2)) house.entranceLot = (h_min + 1, house.lotArea.x_max, door_z) # entrance path for x in range(door_x + 1, house.lotArea.x_max + 1): matrix.setValue(h_min, x, door_z, pavement_block) matrix.setValue(h_min, x, door_z - 1, pavement_block) matrix.setValue(h_min, x, door_z + 1, pavement_block) if house.orientation == "N" or house.orientation == "S": generateWindow_alongX(matrix, window_y, house.buildArea.x_min, house.buildArea.z_min, house.buildArea.z_max) generateWindow_alongX(matrix, window_y, house.buildArea.x_max, house.buildArea.z_min, house.buildArea.z_max) generateCeiling_x(matrix, ceiling_bottom, h_max, x_min - 1, x_max + 1, z_min - 1, z_max + 1, ceiling[0], roof, wall, 0) elif house.orientation == "E" or house.orientation == "W": generateWindow_alongZ(matrix, window_y, house.buildArea.z_min, house.buildArea.x_min, house.buildArea.x_max) generateWindow_alongZ(matrix, window_y, house.buildArea.z_max, house.buildArea.x_min, house.buildArea.x_max) generateCeiling_z(matrix, ceiling_bottom, h_max, x_min - 1, x_max + 1, z_min - 1, z_max + 1, ceiling[0], roof, wall, 0) generateInterior(matrix, h_min, ceiling_bottom, house.buildArea.x_min, house.buildArea.x_max, house.buildArea.z_min, house.buildArea.z_max, picked_wood, biome) return house
def generateTower(matrix, x_min, x_max, z_min, z_max, height_map): tower = utilityFunctions.dotdict() tower.type = "tower" (h_tower, min_h, max_h, x_min, x_max, z_min, z_max) = getTowerAreaInsideLot(x_min, x_max, z_min, z_max, height_map) tower.buildArea = utilityFunctions.dotdict({ "y_min": min_h, "y_max": h_tower, "x_min": x_min, "x_max": x_max, "z_min": z_min, "z_max": z_max }) (door_pos, door_y, tower.orientation) = getOrientationT(matrix, tower.buildArea, height_map) cleanTowerArea(matrix, door_y - 1, h_tower + 3, x_min, x_max, z_min, z_max) logging.info("Generating tower at area {}".format(tower.buildArea)) wall = (45, 0) floor = wall generateWalls(matrix, min_h + 1, h_tower, x_min, x_max, z_min, z_max, wall) generateCeiling(matrix, h_tower, x_min, x_max, z_min, z_max) if tower.orientation == "N": door_x = door_pos[0] door_z = door_pos[1] generateDoor(matrix, door_y, door_x, door_z, (64, 9), (64, 1)) tower.entranceLot = (door_x, door_z - 1) matrix.setValue(door_y - 1, door_x, door_z - 1, (1, 6)) elif tower.orientation == "S": door_x = door_pos[0] door_z = door_pos[1] generateDoor(matrix, door_y, door_x, door_z, (64, 9), (64, 3)) tower.entranceLot = (door_x, door_z + 1) matrix.setValue(door_y - 1, door_x, door_z + 1, (1, 6)) elif tower.orientation == "W": door_x = door_pos[0] door_z = door_pos[1] generateDoor(matrix, door_y, door_x, door_z, (64, 8), (64, 0)) tower.entranceLot = (door_x - 1, door_z) matrix.setValue(door_y - 1, door_x - 1, door_z, (1, 6)) elif tower.orientation == "E": door_x = door_pos[0] door_z = door_pos[1] generateDoor(matrix, door_y, door_x, door_z, (64, 9), (64, 2)) tower.entranceLot = (door_x + 1, door_z) matrix.setValue(door_y - 1, door_x + 1, door_z, (1, 6)) generateFloor(matrix, door_y - 1, x_min, x_max, z_min, z_max, floor) generateInside(matrix, door_y, h_tower, x_min, x_max, z_min, z_max, tower.orientation) return tower
def generateHouse(matrix, h_min, h_max, x_min, x_max, z_min, z_max, ceiling=None): house = utilityFunctions.dotdict() house.type = "house" house.lotArea = utilityFunctions.dotdict({ "y_min": h_min, "y_max": h_max, "x_min": x_min, "x_max": x_max, "z_min": z_min, "z_max": z_max }) utilityFunctions.cleanProperty(matrix, h_min + 1, h_max, x_min, x_max, z_min, z_max) #generateFence(matrix, h_min, x_min, x_max, z_min, z_max) (h_min, h_max, x_min, x_max, z_min, z_max) = getHouseAreaInsideLot(h_min, h_max, x_min, x_max, z_min, z_max) # calculate the top height of the walls, i.e. where the first # row of blocks of the pitched roof will be placed ceiling_bottom = h_max - int((h_max - h_min) * 0.5) house.buildArea = utilityFunctions.dotdict({ "y_min": h_min, "y_max": ceiling_bottom, "x_min": x_min, "x_max": x_max, "z_min": z_min, "z_max": z_max }) logging.info("Generating house at area {}".format(house.lotArea)) logging.info("Construction area {}".format(house.buildArea)) wall = (43, RNG.randint(11, 15)) ceiling = (5, RNG.randint(1, 5)) if ceiling == None else ceiling floor = wall # generate walls from x_min+1, x_max-1, etc to leave space for the roof generateWalls(matrix, house.buildArea.y_min, house.buildArea.y_max, house.buildArea.x_min, house.buildArea.x_max, house.buildArea.z_min, house.buildArea.z_max, wall) generateFloor(matrix, house.buildArea.y_min, house.buildArea.x_min, house.buildArea.x_max, house.buildArea.z_min, house.buildArea.z_max, floor) house.orientation = getOrientation(matrix, house.lotArea) window_y = house.buildArea.y_min + 3 door_y = house.buildArea.y_min + 1 if house.orientation == "N": door_x = RNG.randint(house.buildArea.x_min + 4, house.buildArea.x_max - 4) door_z = house.buildArea.z_min generateDoor(matrix, door_y, door_x, door_z, (64, 9), (64, 1)) house.entranceLot = (h_min + 1, door_x, house.lotArea.z_min) # entrance path for z in range(house.lotArea.z_min, door_z): matrix.setValue(h_min, door_x, z, (4, 0)) matrix.setValue(h_min, door_x - 1, z, (4, 0)) matrix.setValue(h_min, door_x + 1, z, (4, 0)) elif house.orientation == "S": door_x = RNG.randint(house.buildArea.x_min + 4, house.buildArea.x_max - 4) door_z = house.buildArea.z_max generateDoor(matrix, door_y, door_x, door_z, (64, 9), (64, 3)) house.entranceLot = (h_min + 1, door_x, house.lotArea.z_max) # entrance path for z in range(door_z + 1, house.lotArea.z_max): matrix.setValue(h_min, door_x, z, (4, 0)) matrix.setValue(h_min, door_x - 1, z, (4, 0)) matrix.setValue(h_min, door_x + 1, z, (4, 0)) elif house.orientation == "W": door_x = house.buildArea.x_min door_z = RNG.randint(house.buildArea.z_min + 4, house.buildArea.z_max - 4) generateDoor(matrix, door_y, door_x, door_z, (64, 8), (64, 0)) house.entranceLot = (h_min + 1, house.lotArea.x_min, door_z) # entrance path for x in range(house.lotArea.x_min, door_x): matrix.setValue(h_min, x, door_z, (4, 0)) matrix.setValue(h_min, x, door_z - 1, (4, 0)) matrix.setValue(h_min, x, door_z + 1, (4, 0)) elif house.orientation == "E": door_x = house.buildArea.x_max door_z = RNG.randint(house.buildArea.z_min + 4, house.buildArea.z_max - 4) generateDoor(matrix, door_y, door_x, door_z, (64, 9), (64, 2)) house.entranceLot = (h_min + 1, house.lotArea.x_max, door_z) # entrance path for x in range(door_x + 1, house.lotArea.x_max + 1): matrix.setValue(h_min, x, door_z, (4, 0)) matrix.setValue(h_min, x, door_z - 1, (4, 0)) matrix.setValue(h_min, x, door_z + 1, (4, 0)) if house.orientation == "N" or house.orientation == "S": generateWindow_alongX(matrix, window_y, house.buildArea.x_min, house.buildArea.z_min, house.buildArea.z_max) generateWindow_alongX(matrix, window_y, house.buildArea.x_max, house.buildArea.z_min, house.buildArea.z_max) generateCeiling_x(matrix, ceiling_bottom, h_max, x_min - 1, x_max + 1, z_min - 1, z_max + 1, ceiling, wall, 0) elif house.orientation == "E" or house.orientation == "W": generateWindow_alongZ(matrix, window_y, house.buildArea.z_min, house.buildArea.x_min, house.buildArea.x_max) generateWindow_alongZ(matrix, window_y, house.buildArea.z_max, house.buildArea.x_min, house.buildArea.x_max) generateCeiling_z(matrix, ceiling_bottom, h_max, x_min - 1, x_max + 1, z_min - 1, z_max + 1, ceiling, wall, 0) generateInterior(matrix, h_min, ceiling_bottom, house.buildArea.x_min, house.buildArea.x_max, house.buildArea.z_min, house.buildArea.z_max, ceiling) return house
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("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 }) logging.info("Generating simple height map") simple_height_map = utilityFunctions.getSimpleHeightMap( level, box) #no height = -1 when water like block logging.info("Saving and erasing the trees") list_trees = 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 = utilityFunctions.getHeightMap(level, box) #villageDeck = utilityFunctions.generateVillageDeck("city", width, depth) # ==== 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 = 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_type4, threshold) if cond3 == False: failed_conditions.append(3) if cond1 and cond2 and cond3: score = utilityFunctions.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))) # 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 += 2 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, simple_height_map) 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 = 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_type4, threshold) if cond3 == False: failed_conditions.append(3) if cond1 and cond2 and cond3: score = utilityFunctions.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) # 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 += 2 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)) logging.info("Building in the neighbourhood") 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)): slopeStructure = generateSlopeStructure(world, final_partitioning[i], height_map, simple_height_map) if slopeStructure.type == "tower": all_buildings.append(slopeStructure) 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 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 = utilityFunctions.getPathMap(height_map, width, depth) simple_pathMap = utilityFunctions.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 = utilityFunctions.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 = utilityFunctions.simpleAStar( p1.entranceLot, p2.entranceLot, simple_pathMap, simple_height_map) #water and height are not important list_end_points = utilityFunctions.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)) GenerateBridge.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 = utilityFunctions.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])) GeneratePath.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])) GeneratePath.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 = utilityFunctions.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)) GeneratePath.generatePath(world, path, height_map, pavement_Type) else: logging.info( "Couldnt find path between {} and {}. Generating a straight road" .format(p1.entranceLot, p2.entranceLot)) GeneratePath.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, list_trees ) #put back the trees that are not cut buy the building and are not in unwanted places # ==== 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) # ==== 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 generateBuilding(matrix, h_min, h_max, x_min, x_max, z_min, z_max): building = utilityFunctions.dotdict() building.type = "building" building.lotArea = utilityFunctions.dotdict({ "y_min": h_min, "y_max": h_max, "x_min": x_min, "x_max": x_max, "z_min": z_min, "z_max": z_max }) utilityFunctions.cleanProperty(matrix, h_min + 1, h_max, x_min, x_max, z_min, z_max) (h_min, h_max, x_min, x_max, z_min, z_max) = getBuildingAreaInsideLot(h_min, h_max, x_min, x_max, z_min, z_max) building.buildArea = (h_min, h_max, x_min, x_max, z_min, z_max) logging.info("Generating building at area {}".format(building.lotArea)) logging.info("Construction area {}".format(building.buildArea)) wall = (159, random.randint(0, 15)) ceiling = wall floor = wall floor_size = 8 max_height = h_max - h_min if max_height > 32: h_max = h_min + random.randint(32, 80 if max_height > 80 else max_height) while (h_max - h_min) % floor_size != 0: h_max -= 1 generateBuildingWalls(matrix, h_min, h_max, floor_size, x_min, x_max, z_min, z_max, wall) generateFloorsDivision(matrix, h_min, h_max, floor_size, x_min, x_max, z_min, z_max, wall) building.orientation = getOrientation() if building.orientation == "S": door_x = RNG.randint(x_min + 1, x_max - 1) door_z = z_max generateDoor(matrix, h_min + 1, door_x, door_z, (64, 9), (64, 3)) building.entranceLot = (door_x, building.lotArea.z_max) for z in range(door_z + 1, building.lotArea.z_max + 1): matrix.setValue(h_min, door_x, z, (1, 6)) matrix.setValue(h_min, door_x - 1, z, (1, 6)) matrix.setValue(h_min, door_x + 1, z, (1, 6)) # apartment windows generateBuildingWindows_AlongZ(matrix, h_min, h_max, floor_size, x_min, x_max, z_min) # corridor windows generateBuildingWindows_AlongZ(matrix, h_min, h_max, floor_size, x_min, x_max, z_max) generateCorridorInterior(matrix, h_min, h_max, floor_size, x_min, x_max, z_max - 6, z_max) generateFloorPlan(matrix, h_min, h_max, floor_size, x_min, x_max, z_min, z_max, wall) generateStairs(matrix, h_min, h_max, floor_size, x_min, x_max, z_min, z_max, wall) generateApartmentInterior(matrix, h_min, h_max, floor_size, x_min, x_max, z_min, z_max - 6) return building
def generateWell(matrix, h_min, h_max, x_min, x_max, z_min, z_max, biome): well = utilityFunctions.dotdict() well.type = "well" well.lotArea = utilityFunctions.dotdict({ "y_min": h_min, "y_max": h_max, "x_min": x_min, "x_max": x_max, "z_min": z_min, "z_max": z_max }) utilityFunctions.cleanProperty(matrix, h_min + 1, h_max, x_min, x_max, z_min, z_max) (h_min, h_max, x_min, x_max, z_min, z_max) = getWellAreaInsideLot(h_min, h_max, x_min, x_max, z_min, z_max) well.buildArea = utilityFunctions.dotdict({ "y_min": h_min, "y_max": h_max, "x_min": x_min, "x_max": x_max, "z_min": z_min, "z_max": z_max }) well.orientation = getOrientation() logging.info("Generating well at area {}".format(well.lotArea)) logging.info("Construction area {}".format(well.buildArea)) picked_wood = 'oak' fence = BlocksInfo.IRON_BAR_ID slab = BlocksInfo.getSlabId(biome, picked_wood, "Lower") wall = BlocksInfo.getWellWallId(biome) structure_bloc = BlocksInfo.getStructureBlockId(biome, picked_wood) pillar = BlocksInfo.getHousePillarId(biome, picked_wood) stairs = BlocksInfo.getStairsId(biome, picked_wood)[0] pavement_block = BlocksInfo.getPavmentId(biome) setGround(matrix, h_min - 1, x_min, x_max, z_min, z_max, structure_bloc) generateWall(matrix, h_min, x_min, x_max, z_min, z_max, wall, fence) generateCenterPart(matrix, h_min, x_min + 3, x_max - 3, z_min + 3, z_max - 3, slab, structure_bloc, pillar, fence, stairs, wall) if well.orientation == "N": generateEntrance(matrix, h_min, x_min + WELL_ENTRANCE_SIZE, x_max - WELL_ENTRANCE_SIZE, z_min, z_min, wall) generateBucket(matrix, h_min + 4, x_min + (WELL_AREA_SIZE / 2), z_min + (WELL_AREA_SIZE / 2), 1) well.entranceLot = (well.lotArea.y_min + 1, well.buildArea.x_min + (WELL_AREA_SIZE / 2), well.lotArea.z_min) door_x = x_min + WELL_ENTRANCE_SIZE # entrance path for z in range(well.lotArea.z_min, well.buildArea.z_min): for i in range(1, WELL_ENTRANCE_SIZE - 1): matrix.setValue(well.lotArea.y_min, door_x + i, z, pavement_block) elif well.orientation == "S": generateEntrance(matrix, h_min, x_min + WELL_ENTRANCE_SIZE, x_max - WELL_ENTRANCE_SIZE, z_max, z_max, wall) generateBucket(matrix, h_min + 4, x_max - (WELL_AREA_SIZE / 2), z_max - (WELL_AREA_SIZE / 2), 1) well.entranceLot = (well.lotArea.y_min + 1, well.buildArea.x_min + (WELL_AREA_SIZE / 2), well.lotArea.z_max) door_x = x_min + WELL_ENTRANCE_SIZE # entrance path for z in range(well.buildArea.z_max + 1, well.lotArea.z_max): for i in range(1, WELL_ENTRANCE_SIZE - 1): matrix.setValue(well.lotArea.y_min, door_x + i, z, pavement_block) elif well.orientation == "E": generateEntrance(matrix, h_min, x_max, x_max, z_min + WELL_ENTRANCE_SIZE, z_max - WELL_ENTRANCE_SIZE, wall) generateBucket(matrix, h_min + 4, x_max - (WELL_AREA_SIZE / 2), z_min + (WELL_AREA_SIZE / 2), 1) well.entranceLot = (well.lotArea.y_min + 1, well.lotArea.x_max, well.buildArea.z_min + (WELL_AREA_SIZE / 2)) door_z = z_min + WELL_ENTRANCE_SIZE # entrance path for x in range(well.buildArea.x_max + 1, well.lotArea.x_max): for i in range(1, WELL_ENTRANCE_SIZE - 1): matrix.setValue(well.lotArea.y_min, x, door_z + i, pavement_block) else: generateEntrance(matrix, h_min, x_min, x_min, z_min + WELL_ENTRANCE_SIZE, z_max - WELL_ENTRANCE_SIZE, wall) generateBucket(matrix, h_min + 4, x_min + (WELL_AREA_SIZE / 2), z_max - (WELL_AREA_SIZE / 2), 1) well.entranceLot = (well.lotArea.y_min + 1, well.lotArea.x_min, well.buildArea.z_min + (WELL_AREA_SIZE / 2)) door_z = z_min + WELL_ENTRANCE_SIZE # entrance path for x in range(well.lotArea.x_min, well.buildArea.x_min): for i in range(1, WELL_ENTRANCE_SIZE - 1): matrix.setValue(well.lotArea.y_min, x, door_z + i, pavement_block) return well
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()
def generateGreenhouse(matrix, h_min, h_max, x_min, x_max, z_min, z_max, usable_wood, biome): greenhouse = utilityFunctions.dotdict() greenhouse.type = "greenhouse" greenhouse.lotArea = utilityFunctions.dotdict({ "y_min": h_min, "y_max": h_max, "x_min": x_min, "x_max": x_max, "z_min": z_min, "z_max": z_max }) (h_min, h_max, x_min, x_max, z_min, z_max) = getGreenHouseAreaInsideLot(h_min, h_max, x_min, x_max, z_min, z_max) greenhouse.buildArea = utilityFunctions.dotdict({ "y_min": h_min, "y_max": h_max, "x_min": x_min, "x_max": x_max, "z_min": z_min, "z_max": z_max }) greenhouse.orientation = getOrientation() door_z = greenhouse.buildArea.z_min door_x = greenhouse.buildArea.x_min + GREENHOUSE_WIDTH / 2 greenhouse.entranceLot = (greenhouse.lotArea.y_min + 1, door_x, greenhouse.lotArea.z_min) logging.info("Generating greenhouse at area {}".format(greenhouse.lotArea)) logging.info("Construction area {}".format(greenhouse.buildArea)) utilityFunctions.cleanProperty2(matrix, greenhouse.lotArea.y_min + 1, greenhouse.lotArea.y_max, x_min - 1, x_max + 1, z_min - 1, z_max + 1) utilityFunctions.cleanProperty2(matrix, h_min + 1, h_max, door_x - 1, door_x + 1, greenhouse.lotArea.z_min + 1, z_min - 1) picked_wood = utilityFunctions.selectRandomWood(usable_wood) foundation = BlocksInfo.getGreenhouseFundationId(biome, picked_wood) ground = BlocksInfo.getGreenhouseGroundId(biome) used_glass = BlocksInfo.getGreenhouseGlassId(biome) pavement_block = BlocksInfo.getPavmentId(biome) generateGroundAndCropse(matrix, greenhouse.buildArea.y_min, greenhouse.buildArea.x_min, greenhouse.buildArea.x_max, greenhouse.buildArea.z_min, greenhouse.buildArea.z_max, foundation, ground) generateGlassDome(matrix, greenhouse.buildArea.y_min + 1, greenhouse.buildArea.y_min + GREENHOUSE_HEIGHT, greenhouse.buildArea.x_min, greenhouse.buildArea.x_max, greenhouse.buildArea.z_min, greenhouse.buildArea.z_max, used_glass) generateFront(matrix, greenhouse.buildArea.y_min + 1, greenhouse.buildArea.y_min + GREENHOUSE_HEIGHT, greenhouse.buildArea.x_min, greenhouse.buildArea.x_max, greenhouse.buildArea.z_min, greenhouse.buildArea.z_max, used_glass) # entrance path for z in range(greenhouse.lotArea.z_min, door_z): matrix.setValue(h_min, door_x, z, pavement_block) matrix.setValue(h_min, door_x - 1, z, pavement_block) return greenhouse
def generateFarm(matrix, h_min, h_max, x_min, x_max, z_min, z_max, farmType): farm = utilityFunctions.dotdict() farm.type = "farm" farm.lotArea = utilityFunctions.dotdict({ "y_min": h_min, "y_max": h_max, "x_min": x_min, "x_max": x_max, "z_min": z_min, "z_max": z_max }) utilityFunctions.cleanProperty(matrix, h_min + 1, h_max, x_min, x_max, z_min, z_max) (h_min, h_max, x_min, x_max, z_min, z_max) = getFarmAreaInsideLot(h_min, h_max, x_min, x_max, z_min, z_max, farmType) farm.buildArea = utilityFunctions.dotdict({ "y_min": h_min, "y_max": h_max, "x_min": x_min, "x_max": x_max, "z_min": z_min, "z_max": z_max }) logging.info("Generating farm at area {}".format(farm.lotArea)) logging.info("Construction area {}".format(farm.buildArea)) farm.orientation = getOrientation(matrix, farm.lotArea) if farmType == None: generateBasicPattern(matrix, h_min, x_min, x_max, z_min, z_max) elif farmType == "smiley": generateSmileyPattern(matrix, h_min, x_min, x_max, z_min, z_max) #create door and entrance path if farm.orientation == "S": door_x = x_max - 2 door_z = z_max - 1 farm.entranceLot = (door_x, farm.lotArea.z_max) generateEntrance(matrix, 0, h_min, door_x, door_z, door_z + 1, farm.lotArea.z_max + 1) elif farm.orientation == "N": door_x = x_min + 2 door_z = z_min + 1 farm.entranceLot = (door_x, farm.lotArea.z_min) generateEntrance(matrix, 2, h_min, door_x, door_z, farm.lotArea.z_min, door_z) elif farm.orientation == "W": door_x = x_min + 1 door_z = z_max - 2 farm.entranceLot = (farm.lotArea.x_min, door_z) generateEntrance(matrix, 1, h_min, door_x, door_z, farm.lotArea.x_min, door_x) elif farm.orientation == "E": door_x = x_max - 1 door_z = z_min + 2 farm.entranceLot = (farm.lotArea.x_max, door_z) generateEntrance(matrix, 3, h_min, door_x, door_z, door_x + 1, farm.lotArea.x_max + 1) return farm
def generateCrous(matrix, h_min, h_max, x_min, x_max, z_min, z_max, ceiling=None): house = utilityFunctions.dotdict() house.type = "house" house.lotArea = utilityFunctions.dotdict({ "y_min": h_min, "y_max": h_max, "x_min": x_min, "x_max": x_max, "z_min": z_min, "z_max": z_max }) utilityFunctions.cleanProperty(matrix, h_min + 1, h_max, x_min, x_max, z_min, z_max) room_size = 4 (h_min, h_max, x_min, x_max, z_min, z_max) = getBuildArea(h_min, h_max, x_min, x_max, z_min, z_max, room_size) house.buildArea = utilityFunctions.dotdict({ "y_min": h_min, "y_max": h_max, "x_min": x_min, "x_max": x_max, "z_min": z_min, "z_max": z_max }) # does not create the house if not enough space is given if abs(x_max - x_min) < room_size or abs(z_max - z_min) < room_size or abs( h_max - h_min) < 3: return logging.info("Generating lego house at area {}".format(house.lotArea)) logging.info("Construction area {}".format(house.buildArea)) height = 3 floors_rooms = [0] * ((h_max - h_min) // height) ori = orientation() single_ori = RNG.random() < 0.5 rooms = list() for z in range(z_min, z_max, room_size): for x in range(x_min, x_max, room_size): for f in range(h_min, h_max, height): ori = ori if single_ori else orientation() while not checkOrientation(f, x, z, matrix, ori): ori = orientation() wood = (5, RNG.randint(0, 5)) generateRoom(f, f + height, x, x + room_size, z, z + room_size, matrix, wood, (floors_rooms[(f - h_min) // height] == 0), ori) rooms.append([f, x, z, ori]) floors_rooms[(f - h_min) // height] += 1 if RNG.random() < 0.3: generateRoof(f + height, x, x + room_size, z, z + room_size, matrix, wood) break for room in rooms: generateDoorPath(room[0], room[1], room[2], matrix, room[3], h_min) for room in rooms: generateLadder(room[0], room[1], room[2], matrix, room[3], h_min) ori = orientationFromDoors(h_min, x_min, x_max, z_min, z_max, matrix, ori) house.orientation = ori generateEntrance(h_min, x_min, x_max, z_min, z_max, matrix, house, ori) return house
def generateBuilding(matrix, h_min, h_max, x_min, x_max, z_min, z_max, usable_wood, biome): building = utilityFunctions.dotdict() building.type = "building" building.area = utilityFunctions.dotdict({ "y_min": h_min, "y_max": h_max, "x_min": x_min, "x_max": x_max, "z_min": z_min, "z_max": z_max }) (h_min, h_max, x_min, x_max, z_min, z_max) = getBuildingAreaInsideLot(h_min, h_max, x_min, x_max, z_min, z_max) building.constructionArea = (h_min, h_max, x_min, x_max, z_min, z_max) logging.info("Generating building at area {}".format(building.area)) logging.info("Construction area {}".format(building.constructionArea)) utilityFunctions.cleanProperty2( matrix, building.area.y_min + 1, building.area.y_max, x_min - 1, x_max + 1, z_min - 3 if z_min - 3 > building.area.z_min else building.area.z_min, z_max + 1) picked_wood = utilityFunctions.selectRandomWood(usable_wood) wall = (159, random.randint(0, 15)) ceiling = wall floor = wall pavement_block = BlocksInfo.getPavmentId(biome) slab = BlocksInfo.getSlabId(biome, picked_wood, "Upper") stairs = BlocksInfo.getStairsId(biome, picked_wood) fence = BlocksInfo.getFenceId(biome, picked_wood) structureBloc = BlocksInfo.getStructureBlockId(biome, picked_wood) floor_size = 8 max_height = h_max - h_min if max_height > 32: h_max = h_min + random.randint(32, 80 if max_height > 80 else max_height) while (h_max - h_min) % floor_size != 0: h_max -= 1 building.orientation = getOrientation() if building.orientation == "S": door_x = RNG.randint(x_min + 1, x_max - 1) door_z = z_max utilityFunctions.cleanProperty2(matrix, h_min + 1, h_max, door_x - 1, door_x + 1, z_max + 1, building.area.z_max - 1) generateBuildingWalls(matrix, h_min, h_max, floor_size, x_min, x_max, z_min, z_max, wall) generateFloorsDivision(matrix, h_min, h_max, floor_size, x_min, x_max, z_min, z_max, wall) generateDoor(matrix, h_min + 1, door_x, door_z, (64, 9), (64, 3)) building.entranceLot = (h_min + 1, door_x, building.area.z_max) for z in range(door_z + 1, building.area.z_max): matrix.setValue(h_min, door_x, z, pavement_block) matrix.setValue(h_min, door_x - 1, z, pavement_block) matrix.setValue(h_min, door_x + 1, z, pavement_block) # determine which floor have two apartment instead of one double_apartment_floor = pickDoubleapartmentFloor( h_min, h_max, floor_size) # apartment windows generateBuildingWindows_AlongZ(matrix, h_min, h_max, floor_size, x_min, x_max, z_min, double_apartment_floor) # corridor windows generateBuildingWindows_AlongZ(matrix, h_min, h_max, floor_size, x_min, x_max, z_max, []) generateCorridorInterior(matrix, h_min, h_max, floor_size, x_min, x_max, z_max - 6, z_max, fence) generateFloorPlan(matrix, h_min, h_max, floor_size, x_min, x_max, z_min, z_max, wall, double_apartment_floor) generateStairs(matrix, h_min, h_max, floor_size, x_min, x_max, z_min, z_max, wall) generateRoof(matrix, h_min, h_max, floor_size, x_min, x_max, z_min, z_max, biome, usable_wood, wall, stairs) generateApartmentInterior(matrix, h_min, h_max, floor_size, x_min, x_max, z_min, z_max - 6, double_apartment_floor, usable_wood, biome, fence) generateBalconySouth(matrix, h_min, h_max, floor_size, x_min, x_max, z_min, building.area.z_min, building.orientation, double_apartment_floor, wall, slab, stairs, fence, structureBloc) inhabitants = RNG.randint( 1, 2) * (h_max / floor_size) + len(double_apartment_floor) return (building, inhabitants)