Esempio n. 1
0
def makeWall(level, box, options):
    # make walls
    boxSize = utilityFunctions.getBoxSize(box)
    minimumWidth = min(boxSize[0], boxSize[2])
    minimumWidth = max(minimumWidth, 6)
    height = random.randint(5, minimumWidth)
    for x in range(box.minx, box.maxx):
        utilityFunctions.setBlockToGround(level,
                                          (options["Wall Material"].ID, 0), x,
                                          box.miny + height, box.minz,
                                          box.miny)
        utilityFunctions.setBlockToGround(level,
                                          (options["Wall Material"].ID, 0), x,
                                          box.miny + height, box.maxz - 1,
                                          box.miny)
    for z in range(box.minz, box.maxz):
        utilityFunctions.setBlockToGround(level,
                                          (options["Wall Material"].ID, 0),
                                          box.maxx - 1, box.miny + height, z,
                                          box.miny)
        utilityFunctions.setBlockToGround(level,
                                          (options["Wall Material"].ID, 0),
                                          box.minx, box.miny + height, z,
                                          box.miny)
    return height
Esempio n. 2
0
def binaryPartition(box):
	partitions = []
	# create a queue which holds the next areas to be partitioned
	queue = []
	queue.append(box)
	# for as long as the queue still has boxes to partition...
	count = 0
	while len(queue) > 0:
		count += 1
		splitMe = queue.pop(0)
		(width, height, depth) = utilityFunctions.getBoxSize(splitMe)
		# print "Current partition width,depth",width,depth 
		centre = 0
		# this bool lets me know which dimension I will be splitting on. It matters when we create the new outer bound size
		isWidth = False
		# find the larger dimension and divide in half
		# if the larger dimension is < 10, then block this from being partitioned
		minSize = 12
		if width > depth:
			# roll a random die, 1% change we stop anyways
			chance = random.randint(100)

			if depth < minSize or chance == 1:
				partitions.append(splitMe)
				continue

			isWidth = True
			centre = width / 2
		else:
			chance = random.randint(10)
			if width < minSize or chance == 1:
				partitions.append(splitMe)
				continue				
			centre = depth / 2

		# a random modifier for binary splitting which is somewhere between 0 and 1/16 the total box side length
		randomPartition = random.randint(0, (centre / 8) + 1)

		# creating the new bound
		newBound = centre + randomPartition

		#creating the outer edge bounds
		outsideNewBounds = 0
		if isWidth:
			outsideNewBound = width - newBound - 1
		else:
			outsideNewBound = depth - newBound - 1

		# creating the bounding boxes
		# NOTE: BoundingBoxes are objects contained within pymclevel and can be instantiated as follows
		# BoundingBox((x,y,z), (sizex, sizey, sizez))
		# in this instance, you specifiy which corner to start, and then the size of the box dimensions
		# this is an if statement to separate out binary partitions by dimension (x and z)
		if isWidth:
			queue.append(BoundingBox((splitMe.minx, splitMe.miny, splitMe.minz), (newBound-1, 256, depth)))
			queue.append(BoundingBox((splitMe.minx + newBound + 1, splitMe.miny, splitMe.minz), (outsideNewBound - 1, 256, depth)))
		else:
			queue.append(BoundingBox((splitMe.minx, splitMe.miny, splitMe.minz), (width, 256, newBound - 1)))
			queue.append(BoundingBox((splitMe.minx, splitMe.miny, splitMe.minz + newBound + 1), (width, 256, outsideNewBound - 1)))
	return partitions
def generateWalls(level, floor, buildingHeightInfo, options):
	print "Generating walls"
	# actual automata is going to be simulated in a matrix (it's much faster than rendering it in minecraft)
	# first we should define the matrix properties (i.e. width and height)
	(width, boxheight, depth) = utilityFunctions.getBoxSize(floor)
	height = buildingHeightInfo[0]
	print "X walls"
	for k in range(2):
		# we have our matrix for CA, now lets do CA
		matrix = [[0 for x in range(width)] for y in range(height)]
		matrixnew = randomlyAssign(matrix, width, height)
		# do 3 generations
		for gen in range(0,2):
			# print "Generation ", gen
			matrixnew = cellularAutomataGeneration(matrixnew, width, height)
		#after generation is over, place the walls according to the wall matrix, starting at the floor
		for y in range(height):
			for x in range(1,width):
				if k==1:
					# print "boom 1"
					if matrixnew[y][x] == 1:
						utilityFunctions.setBlock(level, (options["Material"].ID, 0), floor.minx+x, buildingHeightInfo[2] + y, floor.minz)
					else:
						utilityFunctions.setBlock(level, (20, 0), floor.minx+x, buildingHeightInfo[2] + y, floor.minz)
				else:
					# print "boom 2"
					if matrixnew[y][x] == 1:
						utilityFunctions.setBlock(level, (options["Material"].ID, 0), floor.minx+x, buildingHeightInfo[2] + y, floor.maxz)
					else:
						utilityFunctions.setBlock(level, (20, 0), floor.minx+x, buildingHeightInfo[2] + y, floor.maxz)
	print "Z Walls"
	for k in range(2):
		# we have our matrix for CA, now lets do CA
		matrix = [[0 for x in range(depth)] for y in range(height)]
		matrixnew = randomlyAssign(matrix, depth, height)

		# do 25 generations
		for gen in range(0,25):
			print "Generation ", gen
			matrixnew = cellularAutomataGeneration(matrixnew, depth, height)

		#after generation is over, place the walls according to the wall matrix, starting at the floor
		for y in range(height):
			for z in range(1,depth):
				if k==1:
					# print "boom 3"
					if matrixnew[y][z] == 1:
						utilityFunctions.setBlock(level, (options["Material"].ID, 0), floor.minx, buildingHeightInfo[2] + y, floor.minz+z)
					else:
						utilityFunctions.setBlock(level, (20, 0), floor.minx, buildingHeightInfo[2] + y, floor.minz+z)
				else:
					# print "boom 4"
					if matrixnew[y][z] == 1:
						utilityFunctions.setBlock(level, (options["Material"].ID, 0), floor.maxx, buildingHeightInfo[2] + y, floor.minz+z)
					else:
						utilityFunctions.setBlock(level, (20, 0), floor.maxx, buildingHeightInfo[2] + y, floor.minz+z)
Esempio n. 4
0
def buildFence(level, box, options, buildFenceHightRange=1):
    boxSize = utilityFunctions.getBoxSize(box)
    if min(boxSize[0],boxSize[1]) < 2:
        return box,box,box,box
    fenceLeft  =  CutBar(box, 1,1,0,0,buildFenceHightRange).left
    fenceRight =  CutBar(box, 1,1,0,0,buildFenceHightRange).right
    fenceFront =  CutBar(box, 0,0,1,1,buildFenceHightRange).front
    fenceBack  =  CutBar(box, 0,0,1,1,buildFenceHightRange).back

    utilityFunctions.fillLayerEmpty(level,fenceLeft,0,(85,0))
    utilityFunctions.fillLayerEmpty(level,fenceRight,0,(85,0))
    utilityFunctions.fillLayerEmpty(level,fenceFront,0,(85,0))
    utilityFunctions.fillLayerEmpty(level,fenceBack,0,(85,0))
    return fenceLeft, fenceRight,fenceFront, fenceBack
Esempio n. 5
0
def makePyramid(level, box, options, floors):
    [cx,cy,cz]=[(box.minx+box.maxx)/2, (box.miny+box.maxy)/2, (box.minz+box.maxz)/2]
    boxSize = utilityFunctions.getBoxSize(box)
    minWidth = min(boxSize[0], boxSize[2])
    step = 2
    count=0
    for floor in range(floors-1):
        subBox = BoundingBox((box.minx+floor,floor+box.miny,box.minz+floor),(boxSize[0]-step*floor, 1, boxSize[2]-step*floor))
        if subBox.width>1 and subBox.length>1:
            utilityFunctions.setSquareFrame(level,(options["Wall"].ID,0), subBox.minx, subBox.miny, subBox.minz, subBox.length,subBox.width)    
            count += 1
        else: 
            break
    subBox = BoundingBox((box.minx+count,count+box.miny,box.minz+count),(boxSize[0]-step*count, 1, boxSize[2]-step*count))
    print subBox
    makeFloor(level, subBox, options)
Esempio n. 6
0
    def __init__(self,
                 box,
                 recessLeft,
                 recessRight,
                 recessFront,
                 recessBack,
                 height=1,
                 offSetY=0):
        boxSize = utilityFunctions.getBoxSize(box)
        middle = BoundingBox((box.minx + recessLeft, box.miny + offSetY,
                              box.minz + recessFront),
                             (boxSize[0] - recessLeft - recessRight, height,
                              boxSize[2] - recessFront - recessBack))
        leftBar = BoundingBox(
            (box.minx, box.miny + offSetY, box.minz + recessFront),
            (recessLeft, height, boxSize[2] - recessFront))
        rightBar = BoundingBox(
            (box.maxx - recessRight, box.miny + offSetY, box.minz),
            (recessRight, height, boxSize[2] - recessBack))
        backBar = BoundingBox(
            (box.minx + recessLeft, box.miny + offSetY, box.maxz - recessBack),
            (boxSize[0] - recessLeft, height, recessBack))
        frontBar = BoundingBox((box.minx, box.miny + offSetY, box.minz),
                               (boxSize[0] - recessRight, height, recessFront))

        cornorLF = BoundingBox((box.minx, box.miny + offSetY, box.minz),
                               (recessLeft, height, recessFront))
        cornorLB = BoundingBox(
            (box.minx, box.miny + offSetY, box.maxz - recessBack),
            (recessLeft, height, recessBack))
        cornorRF = BoundingBox(
            (box.maxx - recessRight, box.miny + offSetY, box.minz),
            (recessRight, height, recessFront))
        cornorRB = BoundingBox((middle.maxx, box.miny + offSetY, middle.maxz),
                               (recessRight, height, recessBack))

        self.left = leftBar
        self.right = rightBar
        self.front = frontBar
        self.back = backBar
        self.cornorLF = cornorLF
        self.cornorLB = cornorLB
        self.cornorRF = cornorRF
        self.cornorRB = cornorRB
        self.middle = middle
Esempio n. 7
0
 def translate_floor(self):
     # translates the floor into minecraft blocks. Doors get two conditions, one for the door itself, and one for the wall above it
     for y in range(1, utilityFunctions.getBoxSize(self.box)[1]):
         for x in range(0, self.floor.shape[0]):
             for z in range(0, self.floor.shape[1]):
                 if self.floor[x, z] == 0 or self.floor[x, z] == -1:
                     utilityFunctions.setBlock(
                         self.level, (self.options["Wall_Material"].ID, 0),
                         self.box.minx + x, self.box.miny + y,
                         self.box.minz + z)
                 elif self.floor[x, z] == -2 and y < 3:
                     # this is a door, figure out which direction it goes
                     self.translate_door((x, z), y)
                 elif self.floor[x, z] == -2 and y >= 3:
                     utilityFunctions.setBlock(
                         self.level, (self.options["Wall_Material"].ID, 0),
                         self.box.minx + x, self.box.miny + y,
                         self.box.minz + z)
def makeFloorPlan(level, box):
    #we have to first figure out where in the box this is going to be
    #find the box dimensions
    (width, height, depth) = utilityFunctions.getBoxSize(box)

    #get sixths
    fractionWidth = width / 6
    fractionDepth = depth / 6
    #create the box boundaries
    randFracx = random.randint(0,fractionWidth+1)
    randFracz = random.randint(0, fractionDepth+1)
    xstart = box.minx + randFracx + 2
    zstart = box.minz + randFracz + 2
    xsize = width * 0.6 - randFracx
    zsize = depth * 0.6 - randFracz

    floorplan = BoundingBox((xstart, box.miny, zstart),(xsize,box.maxy,zsize))
    return floorplan
Esempio n. 9
0
    def __init__(self,
                 box,
                 addLeft,
                 addRight,
                 addFront,
                 addBack,
                 height=1,
                 offSetY=0):
        boxSize = utilityFunctions.getBoxSize(box)
        fullBox = BoundingBox(
            (box.minx - addLeft, box.miny + offSetY, box.minz - addBack),
            (boxSize[0] + addLeft + addRight, height,
             boxSize[2] + addFront + addBack))
        leftBar = BoundingBox((fullBox.minx, box.miny + offSetY, fullBox.minz),
                              (addLeft, height, boxSize[2] + addFront))
        rightBar = BoundingBox((box.maxx, box.miny + offSetY, box.minz),
                               (addRight, height, boxSize[2] + addBack))
        backBar = BoundingBox(
            (fullBox.minx, box.miny + offSetY, box.maxz + addFront),
            (boxSize[0] + addLeft, height, addBack))
        frontBar = BoundingBox((box.minx, box.miny + offSetY, fullBox.minz),
                               (boxSize[0] + addRight, height, addFront))

        cornorLF = BoundingBox(
            (fullBox.minx, box.miny + offSetY, fullBox.minz),
            (addLeft, height, addFront))
        cornorLB = BoundingBox((fullBox.minx, box.miny + offSetY, box.maxz),
                               (addLeft, height, addBack))
        cornorRF = BoundingBox((box.maxx, box.miny + offSetY, fullBox.minz),
                               (addRight, height, addFront))
        cornorRB = BoundingBox((box.maxx, box.miny + offSetY, box.maxz),
                               (addRight, height, addBack))

        self.left = leftBar
        self.right = rightBar
        self.front = frontBar
        self.back = backBar
        self.full = fullBox

        self.cornorLF = cornorLF
        self.cornorLB = cornorLB
        self.cornorRF = cornorRF
        self.cornorRB = cornorRB
Esempio n. 10
0
    boxSize = utilityFunctions.getBoxSize(box)
    if min(boxSize[0],boxSize[1]) < 2:
        return box,box,box,box
    fenceLeft  =  CutBar(box, 1,1,0,0,buildFenceHightRange).left
    fenceRight =  CutBar(box, 1,1,0,0,buildFenceHightRange).right
    fenceFront =  CutBar(box, 0,0,1,1,buildFenceHightRange).front
    fenceBack  =  CutBar(box, 0,0,1,1,buildFenceHightRange).back

    utilityFunctions.fillLayerEmpty(level,fenceLeft,0,(85,0))
    utilityFunctions.fillLayerEmpty(level,fenceRight,0,(85,0))
    utilityFunctions.fillLayerEmpty(level,fenceFront,0,(85,0))
    utilityFunctions.fillLayerEmpty(level,fenceBack,0,(85,0))
    return fenceLeft, fenceRight,fenceFront, fenceBack

def buildBase(level, box, (block,data),height):
    boxSize = utilityFunctions.getBoxSize(box)
    for i in range(0, height):
        layer = BoundingBox((box.minx,box.miny+i,box.minz),(boxSize[0],1,boxSize[2]))
        utilityFunctions.fillBoxEmpty(level,CutBar(layer,i,i,i,i).middle,(block,data))
        #makeFloor(level, CutBar(layer,i,i,i,i).middle, options)
    layer = BoundingBox((box.minx,box.miny+height,box.minz),(boxSize[0],1,boxSize[2]))
    
    return CutBar(layer,height,height,height,height,boxSize[1]-height).middle

def buildWall(level, box, (block,data), height, floorInterVal=5):
    floorBoxes = []
    curBottom = 0
    floorHeight = random.randint(floorInterVal, floorInterVal+3)
    floorBoxes.append(BoundingBox((box.minx, box.miny+curBottom, box.minz),(box.width, floorHeight, box.length)))
    while height - curBottom > floorInterVal:       
        #utilityFunctions.fillLayer(level,AddBar(box,1,1,1,1).full, curBottom, (block,data))
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 =====
    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()
Esempio n. 13
0
 def transform_to_floor(self):
     # changes 3d Minecraft space into 2d numpy array
     box_size = utilityFunctions.getBoxSize(self.box)
     floor = np.zeros((box_size[0], box_size[2]))
     return floor
Esempio n. 14
0
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()