def placeLighting(level): # Place lights around the exterior of the dwelling. Find external corners and attach to them y = 3 AIR = (0, 0) TORCH_EAST = (50, 1) TORCH_WEST = (50, 2) TORCH_SOUTH = (50, 3) TORCH_NORTH = (50, 4) TORCH_UP = (50, 5) torchLocations = [] for z in xrange(0, level.Length): for x in xrange(0, level.Width): blockHere = getBlock(level, x, y, z) if blockHere != AIR: blockEast = getBlock(level, x + 1, y, z) blockWest = getBlock(level, x - 1, y, z) blockSouth = getBlock(level, x, y, z + 1) blockNorth = getBlock(level, x, y, z - 1) if blockEast != AIR and blockSouth != AIR and blockWest == AIR and blockNorth == AIR: torchLocations.append((x - 1, y, z, TORCH_WEST)) torchLocations.append((x, y, z - 1, TORCH_NORTH)) elif blockEast == AIR and blockSouth != AIR and blockWest != AIR and blockNorth == AIR: torchLocations.append((x + 1, y, z, TORCH_EAST)) torchLocations.append((x, y, z - 1, TORCH_NORTH)) elif blockEast == AIR and blockSouth == AIR and blockWest != AIR and blockNorth != AIR: torchLocations.append((x + 1, y, z, TORCH_EAST)) torchLocations.append((x, y, z + 1, TORCH_SOUTH)) elif blockEast != AIR and blockSouth == AIR and blockWest == AIR and blockNorth != AIR: torchLocations.append((x - 1, y, z, TORCH_WEST)) torchLocations.append((x, y, z + 1, TORCH_SOUTH)) for (x, y, z, block) in torchLocations: setBlock(level, x, y, z, block)
def placeWindows(level): # This is at the HOUSE level because the windows are on exterior walls only # Punch through the level placing glass if the current block is an exterior wall facing the right way AIR = (0, 0) GLASS = (20, 0) y = 2 # Window height DOUBLEHEIGHTWINDOWS = False if randint(1, 10) == 10: DOUBLEHEIGHTWINDOWS = True # tunnel width-wise z = randint(3, 4) while z < level.Length: for x in xrange(1, level.Width - 1): if getBlock(level, x, y, z) != AIR: if getBlock(level, x - 1, y, z) == AIR: if getBlock(level, x + 1, y, z) == AIR: # Behind and in front are air floorInFront = getBlock(level, x - 1, 0, z) floorBehind = getBlock(level, x + 1, 0, z) if (floorInFront == AIR and floorBehind != AIR) or ( floorInFront != AIR and floorBehind == AIR): setBlock(level, x, y, z, GLASS) if DOUBLEHEIGHTWINDOWS: setBlock(level, x, y + 1, z, GLASS) z += 2 # Tunnel depth-wise # tunnel width-wise x = randint(3, 4) while x < level.Width: for z in xrange(1, level.Length - 1): if getBlock(level, x, y, z) != AIR: if getBlock(level, x, y, z - 1) == AIR: if getBlock(level, x, y, z + 1) == AIR: # Behind and in front are air floorInFront = getBlock(level, x, 0, z - 1) floorBehind = getBlock(level, x, 0, z + 1) if (floorInFront == AIR and floorBehind != AIR) or ( floorInFront != AIR and floorBehind == AIR): setBlock(level, x, y, z, GLASS) if DOUBLEHEIGHTWINDOWS: setBlock(level, x, y + 1, z, GLASS) x += 2
def create(generatorName, level, areas): # This module creates a settlement in the selection based on the availableAreas. SMALL = 8 MEDIUM = 16 LARGE = 32 settlementA = [ "House", "FarmLand", "House", "TownSquare", "Tower" ] #["TownSquare","TownHall","Farm","House"] # Add any generator types here for i in xrange(0, randint(30, 100)): randval = randint(1, 10) if randval == 1: settlementA.append("Tower") if randval == 2: settlementA.append("House") else: settlementA.append("FarmLand") settlements = [ settlementA ] # In reality you'll mix this up with different blueprints, probably based on biome type # Optional: Check bounds and whether we can do anything chosenVariant = settlements[randint(0, len(settlements) - 1)] # Pick one at random BADFOUNDATIONBLOCKS = [8, 9, 10, 11] plotAreas = [] for (box, flag) in areas: (heightMap, minHeight, maxHeight, layerMap, blocks, blockIDs) = profileCell(level, (box.minx, box.miny, box.minz), (box.maxx, box.maxy, box.maxz)) edgeMap = mapEdges(heightMap, 1) cells = identifyContiguousAreas(edgeMap) print cells # The cells list is (posx,posy,size). So we are going to build a new set of boxes and use them to generate the settlement for (x, y, size) in cells: if False: # Debug col = randint(0, 15) for ix in xrange(box.minx + x, box.minx + x + size): for iz in xrange(box.minz + y, box.minz + y + size): setBlock(level, ix, box.maxy - 3, iz, (35, col)) # print ix,box.maxy-3,iz if size >= SMALL: # Minimum size to generate against # Check if this area has water or lava in it, in which case we can't build here okToBuild = True badFoundationCount = 0 width, depth, dim = layerMap.shape px = x + 1 py = y + 1 while py < y + 1 + size: if px < width - 1 and py < depth - 1: if layerMap[px][py][0] in BADFOUNDATIONBLOCKS: badFoundationCount += 1 print "Badfoundations :", badFoundationCount if badFoundationCount > 9: # is a problem for us print "Badfoundations:", badFoundationCount okToBuild = False # Can't build on quicksand (or lava and water) py = y + 1 + size # exit loop px += 1 if px >= x + 1 + size: px = x + 1 py += 1 if okToBuild == True: # what is the height to use? Try for average... avgHeight = 0 for ppx in xrange(x, x + size): for ppy in xrange(y, y + size): avgHeight += heightMap[ppx][ppy] avgHeight = int(avgHeight / (size * size)) print avgHeight plotArea = BoundingBox( (box.minx + x, avgHeight, box.minz + y), (size, box.maxy - (avgHeight), size)) # Save this plot, discard all others plotAreas.append((plotArea, True)) print "Viable area", plotArea else: print "Bad foundations at", x, y, size resultAreas = [] keepGoing = True blueprintCounter = 0 while keepGoing == True and len(plotAreas) > 0 and blueprintCounter < len( chosenVariant): # Bounds checking shuffle(plotAreas) (box, availableFlag) = plotAreas.pop() # Get an area if availableFlag == True: # Chop up the box to allocate space to the child. We'll use a 2D centre segmentation method width, height, depth = getDimensionsFromBox(box) size = -1 if width >= LARGE and height >= LARGE and depth >= LARGE: size = LARGE elif width >= MEDIUM and height >= MEDIUM and depth >= MEDIUM: size = MEDIUM elif width >= SMALL and height > SMALL and depth > SMALL: size = SMALL if size != -1: # -1 is invalid - selection too small # Carve up the area, allocate the central portion to the delegate generator, and return the free ones to the area stack for re-use chopXPos1 = ((box.maxx + box.minx) >> 1) - (size >> 1) chopXPos2 = ((box.maxx + box.minx) >> 1) + (size >> 1) chopZPos1 = ((box.maxz + box.minz) >> 1) - (size >> 1) chopZPos2 = ((box.maxz + box.minz) >> 1) + (size >> 1) # These are the free areas areas.append((BoundingBox( (box.minx, box.miny, box.minz), (chopXPos1 - box.minx, height, chopZPos2 - box.minz)), True)) areas.append((BoundingBox( (box.minx, box.miny, chopZPos2), (chopXPos2 - box.minx, height, box.maxz - 1 - chopZPos2)), True)) areas.append((BoundingBox((chopXPos2, box.miny, chopZPos1), (box.maxx - 1 - chopXPos2, height, box.maxz - 1 - chopZPos1)), True)) areas.append((BoundingBox( (chopXPos1, box.miny, box.minz), (box.maxx - 1 - chopXPos1, height, chopZPos1 - box.minz)), True)) # This is the new building location newBox = BoundingBox((0, 0, 0), (size, size, size)) # Create a new level to generate the building within and, once built, copy it back over onto the level # scratchpadHouse = makeBlankAreaOfSizeWHD(size,height,size) # Clear out all the nuisance blocks AIR = (0, 0) for y in xrange(box.miny, box.miny + size): for z in xrange(chopZPos1, chopZPos1 + size): for x in xrange(chopXPos1, chopXPos1 + size): (theBlockID, theBlockData) = getBlock(level, x, y, z) if theBlockID in IGNOREBLOCKIDS: setBlock(level, x, y, z, AIR) scratchpadLand = copyAreaOfSizeWHDFromSchematicAtPosXYZ( level, size, height, size, chopXPos1, box.miny, chopZPos1) newGeneratedAreas = delegateGeneration( chosenVariant[blueprintCounter], scratchpadLand, [(newBox, True)]) # scratchpadLand.copyBlocksFrom(scratchpadHouse,BoundingBox((0,0,0),(size,height,size)),(0,0,0)) pasteAreaOfSizeWHDToSchematicAtPosXYZ(scratchpadLand, level, scratchpadLand.Width, scratchpadLand.Height, scratchpadLand.Length, chopXPos1, box.miny, chopZPos1) # Put in some support pylons if there are parts of the house suspended... log("Placing building supports") for iz in xrange(chopZPos1, chopZPos1 + scratchpadLand.Length): for ix in xrange(chopXPos1, chopXPos1 + scratchpadLand.Width): iy = box.miny + scratchpadLand.Height - 1 drawPylon = False while (iy >= 0 and drawPylon == True) or (drawPylon == False and iy >= box.miny): (theBlockID, theBlockData) = getBlock(level, ix, iy, iz) if drawPylon == True and ( theBlockID == 0 or theBlockID in IGNOREBLOCKIDS or theBlockID in [8, 9, 10, 11]): # + Liquids setBlock(level, ix, iy, iz, (4, 0)) # Cobblestone elif theBlockID == 4: drawPylon = True elif drawPylon == True: drawPylon = False # Turn it off iy = 0 # Break out iy -= 1 blueprintCounter += 1 # Move onto the next building type resultAreas.append((box, True)) else: log("Unable to find space for generation within area " + str(box)) # Discard this area, it's too small a fragment and cannot be effectively used at this time # This causes the areas list to tend to empty # TODO: consider putting micro-details into tiny areas # Segmentation of the village - low walls and lines of trees/shrubs # Voronoi cells log("Creating yards and walls") minx = 1000000000 minz = 1000000000 maxx = -1000000000 maxz = -1000000000 points = [] for (box, flag) in resultAreas: box1centrex = (box.maxx + box.minx) >> 1 box1centrez = (box.maxz + box.minz) >> 1 points.append((box1centrex, box1centrez)) if box1centrex < minx: minx = box1centrex if box1centrex > maxx: maxx = box1centrex if box1centrez < minz: minz = box1centrez if box1centrez > maxz: maxz = box1centrez log(str(points)) v = zeros((maxx - minx, maxz - minz, 4)) for z in xrange(minz, maxz): for x in xrange(minx, maxx): px = x - minx pz = z - minz if v[px][pz][3] == 0: v[px][pz][2] = 1000000000 for X, Z in points: dx = x - X dz = z - Z dist = dx * dx + dz * dz if dist < v[px][pz][2]: v[px][pz][0] = X # Which point we're associated with v[px][pz][1] = Z v[px][pz][2] = dist # Store a distance v[px][pz][3] = 1 # Mark processed print v edgePoints = [] # Find edgePoints - those points which are adjacent to a different zone by (X,Z) for z in xrange(0, maxz - minz - 1): for x in xrange(0, maxx - minx - 1): if v[x][z][3] == 1 and v[x][z + 1][3] == 1 and v[x + 1][z][3] == 1: if v[x][z][0] != v[x + 1][z][0] or v[x][z][1] != v[ x + 1][z][1] or v[x][z][0] != v[x][ z + 1][0] or v[x][z][1] != v[x][z + 1][ 1]: # If any of the rightmost/nextmost points are different, this is an edge edgePoints.append((x + minx, z + minz)) log("Making walls") log(str(len(edgePoints))) COBBLESTONE = 4 MOSSCOBBLESTONE = 48 COBBLESTONEWALL = 139 TORCH_UP = (50, 5) for x, z in edgePoints: if randint(1, 10) > 5: y = level.Height while y >= 0: theBlockID, theBlockData = getBlock(level, x, y, z) if theBlockID == 2: # Grass if randint(1, 10) < 0: # Shrubs and trees DISABLED LEAVES = (18, randint(0, 11)) LOG = (17, randint(0, 3)) ht = randint(1, 6) for y1 in xrange(y, y + ht): setBlock(level, x, y1, z, LOG) for dx in range(-1, 2): setBlock(level, x + dx, y1, z, LEAVES) for dz in range(-1, 2): setBlock(level, x, y1, dz + dz, LEAVES) for y1 in xrange(y + ht, y + ht + (ht >> 1)): setBlock(level, x, y1, z, LEAVES) else: setBlock(level, x, y, z, (MOSSCOBBLESTONE, 0)) if randint(1, 10) > 2: setBlock(level, x, y + 1, z, (COBBLESTONE, 0)) if randint(1, 10) > 5: setBlock(level, x, y + 2, z, (COBBLESTONEWALL, randint(0, 1))) if randint(1, 10) > 8: setBlock(level, x, y + 3, z, TORCH_UP) y = 0 # Break. Job done y -= 1 # Paths in the grass through resultAreas log("Making paths") heightW, heightD = heightMap.shape PATH = (208, 0) pathCount = 20 while pathCount > 0 and len(resultAreas) > pathCount: (box, flag) = resultAreas[randint(0, len(resultAreas) - 1)] (box2, flag1) = resultAreas[randint(0, len(resultAreas) - 1)] if flag and flag1 and box != box2: pathCount -= 1 log("Pathing... " + str(pathCount)) box1centrex = (box.maxx + box.minx) >> 1 box1centrez = (box.maxz + box.minz) >> 1 box2centrex = (box2.maxx + box2.minx) >> 1 box2centrez = (box2.maxz + box2.minz) >> 1 # Calculate the line from box1 to box 2 P = [] P.append((box1centrex, 0, box1centrez)) P.append(P[0]) P.append( (((box1centrex + box2centrex) >> 1) + randint(-100, 100), 0, ((box1centrez + box2centrez) >> 1) + randint(-100, 100))) P.append((box2centrex, 0, box2centrez)) P.append(P[len(P) - 1]) Q = calcLinesSmooth(4, P) for (x, y, z) in Q: x = x + randint(-2, 2) z = z + randint(-2, 2) if randint(1, 10) > 3: y = level.Height while y >= 0: theBlockID, theBlockData = getBlock(level, x, y, z) if theBlockID == 2: # Grass setBlock(level, x, y, z, PATH) y = 0 # Break. Job done y -= 1 return resultAreas # Tell the parent generator what we've done
def Farmland(level, box): crops = [ (0, 0), (59, 0), (59, 1), (59, 2), (59, 3), (59, 4), (59, 5), (59, 6), (59, 7), (142, 0), (142, 1), (142, 2), (142, 3), (142, 4), (142, 5), (142, 6), (142, 7), (141, 0), (141, 1), (141, 2), (141, 3), (141, 4), (141, 5), (141, 6), (141, 7), # (207,0),(207,1),(207,2),(207,3), # <- This block is ICE on PE and so cannot be used (31, 1) ] CROPS = "RANDOM" CROPS_MAT = crops[randint(0, len(crops) - 1)] FARM_MAT = (60, 7) EDGE_MAT = (3, 0) WATER_MAT = (9, 0) WATERCOVER_MAT = (111, 0) FENCE_MAT = (85, 0) SURFACE_MAT = (2, 0) AIR = (0, 0) (midx, midz) = ((box.minx + box.maxx) >> 1, (box.minz + box.maxz) >> 1) # Find the surface blocks (surfid, surfdata) = SURFACE_MAT surfaceBlocks = [] for z in xrange(box.minz, box.maxz): if z % 100 == 0: print "Processing Row: ", z for x in xrange(box.minx, box.maxx): for y1 in xrange(0, box.maxy - box.miny): y = box.maxy - y1 - 1 (bid, bdata) = getBlock(level, x, y, z) if bid == surfid: blockAbove = getBlock(level, x, y + 1, z) if blockAbove == AIR: surfaceBlocks.append((x, y, z)) break # Found the top of this column, move on if bid == 31 and CROPS == "RANDOM": setBlock(level, x, y, z, AIR) # Now, for each of the locations we found, flip to farmland and put the crop on top print "Found ", len(surfaceBlocks), " blocks. Springtime planting underway" for (x, y, z) in surfaceBlocks: if x == box.minx or x == box.maxx - 1 or z == box.minz or z == box.maxz - 1: if random() > 0.4: setBlock(level, x, y + 1, z, FENCE_MAT) if random() > 0.7: setBlock(level, x, y, z, EDGE_MAT) else: setBlock(level, x, y, z, FARM_MAT) if (x - midx) % 5 == 0 and (z - midz) % 5 == 0: # Place water? bw = getBlock(level, x - 1, y, z) be = getBlock(level, x + 1, y, z) bn = getBlock(level, x, y, z - 1) bs = getBlock(level, x, y, z + 1) if bw != AIR and be != AIR and bn != AIR and bs != AIR: setBlock(level, x, y, z, WATER_MAT) if getBlock(level, x, y + 1, z) == AIR: setBlock(level, x, y + 1, z, WATERCOVER_MAT) else: setBlock(level, x, y + 1, z, CROPS_MAT) print "Complete"
def create(generatorName, level, areas): ''' We are passed: - a string naming this method as 'generatorName', - a pymclevel "level" or MCSchematic object as 'level', - and a list of (BoundingBox,flag) tuples as 'areas' ''' log("Generating a " + generatorName) # Dump a message to the console # Some useful material definitions AIR = (0, 0) STONEBRICKS = (98, 1) COBBLESTONE = (4, 0) BRICKS = (45, 0) WOODPLANKS = (5, 0) FLOORHEIGHT = 5 while len( areas ) > 0: # Iterate through the possible build plot areas we were passed. (box, availableFlag) = areas.pop() # Select the first area BoundingBox if availableFlag == True: # Confirm we're allowed to use it log("Generating a " + generatorName + " at " + str(box)) # Informational to show we found a plot to build in width, height, depth = getDimensionsFromBox( box) # Find out how much space we've been given if width >= 16 and depth >= 16: # Minimum viable generation space cx = width >> 1 # Pre-calculate the centre via halving through a bit shift cz = depth >> 1 # Pre-calculate the centre via halving through a bit shift # A tower is a cylinder with a hat on it. towerHeight = height # This is a normal tower with a flat roof if randint(1, 10) > 7: towerHeight = int( height / 3 * 2) # Leave 33% room for the roof otherwise radius = cx - (cx >> 1) # Push the tower wall into the box r2 = radius * radius # Square of the radius. We'll use this a little later to work out if we are in or outside the tower wall for y in xrange(0, towerHeight): for z in xrange(0, depth): dz = z - cz # distance to centre on z axis ddz = dz * dz # pre-calculate the distance squared for x in xrange(0, width): dx = x - cx # distance to centre on x axis ddx = dx * dx # pre-calculate the distance squared dist2 = ddx + ddz # square of the distance. No need to square-root this if dist2 <= r2: # We're within the tower material = AIR # Default to overwriting the tower space with air if dist2 > r2 - 16: # This is the wall thickness material = STONEBRICKS # Wall else: # Inside the wall within a room. Put a floor at this offset if y % FLOORHEIGHT == 1: material = WOODPLANKS if y == 0 or (material != AIR and width > 16 and randint(1, 10) == 1): material = COBBLESTONE # Bottom layer cobblestone which is allows us to pack in empty space below setBlock( level, box.minx + x, box.miny + y, box.minz + z, material ) # Clear the block from this position regardless of what it is # Draw the roof, if this tower has one for y in xrange(towerHeight, height): scalingRatio = 1.0 - float(y - towerHeight) / float( height - towerHeight ) # this works out how much to taper the radius rad = (cx / 3 * 2) * scalingRatio r2 = int(rad * rad) # The radius gets smaller the higher we go for z in xrange(0, depth): dz = z - cz # distance to centre on z axis ddz = dz * dz # pre-calculate the distance squared for x in xrange(0, width): dx = x - cx # distance to centre on x axis ddx = dx * dx # pre-calculate the distance squared dist2 = ddx + ddz # square of the distance. No need to square-root this if dist2 <= r2: # We're within the roof material = BRICKS setBlock(level, box.minx + x, box.miny + y, box.minz + z, material) # Draw the roof # Window features and doorways towerRadius = radius >> 1 for y in xrange(0, towerHeight): # Randomly punch windows through if y % FLOORHEIGHT == 3 or y == 2: # y == 2 for ground floor access for x in xrange(cx - towerRadius + 1, cx + towerRadius): if x != cx: if randint(1, 10) == 1: hitWall = False for z in xrange(0, depth): # Drill through theBlock = getBlock( level, box.minx + x, box.miny + y, box.minz + z) if theBlock != AIR and hitWall == False: hitWall = False setBlock(level, box.minx + x, box.miny + y, box.minz + z, AIR) setBlock(level, box.minx + x, box.miny + y + 1, box.minz + z, AIR) z = depth for z in xrange(cz - towerRadius + 1, cz + towerRadius): if z != cz: if randint(1, 10) == 1: hitWall = False for x in xrange(0, width): # Drill through theBlock = getBlock( level, box.minx + x, box.miny + y, box.minz + z) if theBlock != AIR and hitWall == False: hitWall = False setBlock(level, box.minx + x, box.miny + y, box.minz + z, AIR) setBlock(level, box.minx + x, box.miny + y + 1, box.minz + z, AIR) x = width
def placeDoors(level): # This is at the "HOUSE" level because the doors are common to rooms, and exterior walls # Punch through the level placing door if the current block is an exterior wall facing the right way AIR = (0, 0) DOOREAST = (64, 0) # bitwise or with 0x8 for the top DOOREASTTOP = (64, 8) # bitwise or with 0x8 for the top DOORWEST = (64, 2) # bitwise or with 0x8 for the top DOORWESTTOP = (64, 10) # bitwise or with 0x8 for the top DOORSOUTH = (64, 1) # bitwise or with 0x8 for the top DOORSOUTHTOP = (64, 9) # bitwise or with 0x8 for the top DOORNORTH = (64, 3) # bitwise or with 0x8 for the top DOORNORTHTOP = (64, 11) # bitwise or with 0x8 for the top doorsPlaced = 0 iterations = 0 # Iteration cap while doorsPlaced == 0 and iterations <= 3: y = 1 # Door height # tunnel width-wise z = randint(4 - iterations, 5) while z < level.Length: for x in xrange(1, level.Width - 1): if getBlock(level, x, y, z) != AIR: if getBlock(level, x - 1, y, z) == AIR: if getBlock(level, x + 1, y, z) == AIR: # Behind and in front are air floorInFront = getBlock(level, x - 1, 0, z) floorBehind = getBlock(level, x + 1, 0, z) if floorBehind != AIR or floorInFront != AIR and getBlock( level, x - 2, y, z) != DOOREAST: material = DOOREAST materialtop = DOOREASTTOP if randint(1, 2) == 1: material = DOORWEST materialtop = DOORWESTTOP setBlock(level, x, y, z, material) setBlock(level, x, y + 1, z, materialtop) doorsPlaced += 1 z += randint(4 - iterations, 5 - iterations) # Tunnel depth-wise # tunnel width-wise x = randint(4 - iterations, 5) while x < level.Width: for z in xrange(1, level.Length - 1): if getBlock(level, x, y, z) != AIR: if getBlock(level, x, y, z - 1) == AIR: if getBlock(level, x, y, z + 1) == AIR: # Behind and in front are air floorInFront = getBlock(level, x, 0, z - 1) floorBehind = getBlock(level, x, 0, z + 1) if floorBehind != AIR or floorInFront != AIR and getBlock( level, x - 2, y, z) != DOORSOUTH: material = DOORSOUTH materialtop = DOORSOUTHTOP if randint(1, 2) == 1: material = DOORNORTH materialtop = DOORNORTHTOP setBlock(level, x, y, z, material) setBlock(level, x, y + 1, z, materialtop) doorsPlaced += 1 x += randint(4 - iterations, 5 - iterations) iterations += 1
def furnish(self, level): # Based on the type of room, place things around. log("Furnishing...") AIR = (0, 0) DOORS = [64] (ox, oy, oz) = self.pos width, height, depth = self.size colortheme = randint(0, 15) if self.type == "Bedroom": # Place a bed # Bed. Location shouldn't be adjacent to a door. Find a spot with the head to a wall. Fair share of orientations BEDFOOTNORTH = (26, 0) BEDFOOTEAST = (26, 1) BEDFOOTSOUTH = (26, 2) BEDFOOTWEST = (26, 3) BEDHEADNORTH = (26, 8) BEDHEADEAST = (26, 9) BEDHEADSOUTH = (26, 10) BEDHEADWEST = (26, 11) # Walk the floor looking for a safe place to put a bed y = oy + 1 attempts = 100 while attempts > 0: attempts -= 1 x = randint(ox + 1, ox + width - 1) z = randint(oz + 1, oz + depth - 1) thisSpot = getBlock(level, x, y, z) if thisSpot == AIR: wid, wdata = westSpot = getBlock(level, x - 1, y, z) eid, edata = eastSpot = getBlock(level, x + 1, y, z) sid, sdata = southSpot = getBlock(level, x, y, z + 1) nid, ndata = northSpot = getBlock(level, x, y, z - 1) if westSpot != AIR and eastSpot == AIR and wid not in DOORS and nid not in DOORS and sid not in DOORS: eid, edata = eastSpot = getBlock(level, x + 2, y, z) sid, sdata = southSpot = getBlock( level, x + 1, y, z + 1) nid, ndata = northSpot = getBlock( level, x + 1, y, z - 1) if eid not in DOORS and sid not in DOORS and nid not in DOORS: setBlock(level, x, y, z, BEDHEADEAST) setBlock(level, x + 1, y, z, BEDFOOTEAST) attempts = 0 elif eastSpot != AIR and westSpot == AIR and eid not in DOORS and nid not in DOORS and sid not in DOORS: wid, edata = westSpot = getBlock(level, x - 2, y, z) sid, sdata = southSpot = getBlock( level, x - 1, y, z + 1) nid, ndata = northSpot = getBlock( level, x - 1, y, z - 1) if wid not in DOORS and sid not in DOORS and nid not in DOORS: setBlock(level, x, y, z, BEDHEADWEST) setBlock(level, x - 1, y, z, BEDFOOTWEST) attempts = 0 elif northSpot != AIR and southSpot == AIR and eid not in DOORS and wid not in DOORS and nid not in DOORS: wid, edata = westSpot = getBlock( level, x - 1, y, z + 1) eid, sdata = southSpot = getBlock( level, x + 1, y, z + 1) sid, ndata = northSpot = getBlock(level, x, y, z + 2) if wid not in DOORS and sid not in DOORS and eid not in DOORS: setBlock(level, x, y, z, BEDHEADSOUTH) setBlock(level, x, y, z + 1, BEDFOOTSOUTH) attempts = 0 elif northSpot == AIR and southSpot != AIR and eid not in DOORS and wid not in DOORS and sid not in DOORS: wid, edata = westSpot = getBlock( level, x - 1, y, z - 1) eid, sdata = southSpot = getBlock( level, x + 1, y, z - 1) nid, ndata = northSpot = getBlock(level, x, y, z - 2) if wid not in DOORS and eid not in DOORS and nid not in DOORS: setBlock(level, x, y, z, BEDHEADNORTH) setBlock(level, x, y, z - 1, BEDFOOTNORTH) attempts = 0 if self.type == "LivingRoom": STAIRCHAIR = 53 # 0,1,2,3 log("Chairs") placements = [] for i in xrange(0, randint(2, 8)): placements.append(STAIRCHAIR) y = oy + 1 attempts = 100 while attempts > 0 and len(placements) > 0: attempts -= 1 x = randint(ox + 1, ox + width - 1) z = randint(oz + 1, oz + depth - 1) thisSpot = getBlock(level, x, y, z) if thisSpot == AIR: wid, wdata = westSpot = getBlock(level, x - 1, y, z) eid, edata = eastSpot = getBlock(level, x + 1, y, z) sid, sdata = southSpot = getBlock(level, x, y, z + 1) nid, ndata = northSpot = getBlock(level, x, y, z - 1) if westSpot == AIR and eastSpot == AIR and southSpot == AIR and northSpot == AIR: block = placements.pop() setBlock(level, x, y, z, (block, randint(0, 3))) if self.type == "Kitchen": CRAFTINGTABLE = 58 FURNACE = 61 # 2,3,4,5 CAULDRON = 118 # 0,1,2,3 log("Kitchen") placements = [CAULDRON, FURNACE, CRAFTINGTABLE] # Walk the floor looking for a safe place to put a crafting table y = oy + 1 attempts = 100 while attempts > 0 and len(placements) > 0: attempts -= 1 x = randint(ox + 1, ox + width - 1) z = randint(oz + 1, oz + depth - 1) thisSpot = getBlock(level, x, y, z) if thisSpot == AIR: wid, wdata = westSpot = getBlock(level, x - 1, y, z) eid, edata = eastSpot = getBlock(level, x + 1, y, z) sid, sdata = southSpot = getBlock(level, x, y, z + 1) nid, ndata = northSpot = getBlock(level, x, y, z - 1) if westSpot != AIR and eastSpot == AIR and wid not in DOORS and nid not in DOORS and sid not in DOORS: block = placements.pop() blockID = 0 if block == CAULDRON: blockID = randint(0, 3) elif block == FURNACE: blockID = 4 setBlock(level, x, y, z, (block, blockID)) elif eastSpot != AIR and westSpot == AIR and eid not in DOORS and nid not in DOORS and sid not in DOORS: block = placements.pop() blockID = 0 if block == CAULDRON: blockID = randint(0, 3) elif block == FURNACE: blockID = 5 setBlock(level, x, y, z, (block, blockID)) elif northSpot != AIR and southSpot == AIR and eid not in DOORS and wid not in DOORS and nid not in DOORS: block = placements.pop() blockID = 0 if block == CAULDRON: blockID = randint(0, 3) elif block == FURNACE: blockID = 3 setBlock(level, x, y, z, (block, blockID)) elif northSpot == AIR and southSpot != AIR and eid not in DOORS and wid not in DOORS and sid not in DOORS: block = placements.pop() blockID = 0 if block == CAULDRON: blockID = randint(0, 3) elif block == FURNACE: blockID = 2 setBlock(level, x, y, z, (block, blockID)) # All rooms - table and torch log("Chest") CHEST = 54 y = oy + 1 attempts = 100 while attempts > 0: attempts -= 1 x = randint(ox + 1, ox + width - 1) z = randint(oz + 1, oz + depth - 1) thisSpot = getBlock(level, x, y, z) if thisSpot == AIR: wid, wdata = westSpot = getBlock(level, x - 1, y, z) eid, edata = eastSpot = getBlock(level, x + 1, y, z) sid, sdata = southSpot = getBlock(level, x, y, z + 1) nid, ndata = northSpot = getBlock(level, x, y, z - 1) if westSpot == AIR and eastSpot == AIR and southSpot == AIR and northSpot == AIR: setBlock(level, x, y, z, (CHEST, randint(2, 5))) attempts = 0 log("Light") TORCH_UP = (50, 5) #TABLE = (85,0) # Fence y = oy + 1 attempts = 100 while attempts > 0: attempts -= 1 x = randint(ox + 1, ox + width - 1) z = randint(oz + 1, oz + depth - 1) thisSpot = getBlock(level, x, y, z) if thisSpot == AIR: wid, wdata = westSpot = getBlock(level, x - 1, y, z) eid, edata = eastSpot = getBlock(level, x + 1, y, z) sid, sdata = southSpot = getBlock(level, x, y, z + 1) nid, ndata = northSpot = getBlock(level, x, y, z - 1) if westSpot == AIR and eastSpot == AIR and southSpot == AIR and northSpot == AIR: setBlock(level, x, y, z, (35, colortheme)) setBlock(level, x, y + 1, z, TORCH_UP) attempts = 0 log("Carpet") # All rooms - Carpet CARPET = 171 if randint(1, 10) < 10: # Add carpet log("Adding carpet") offset = randint(1, 3) fill(level, (ox + offset, oy + 1, oz + offset), (ox + width - offset, oy + 2, oz + depth - offset), (CARPET, colortheme))