def create(generatorName, level, areas): log("Generating a " + generatorName) while len(areas) > 0: (box, availableFlag) = areas.pop() width, height, depth = getDimensionsFromBox(box) log("Generating a " + generatorName + " at " + str(box)) MINW = width - 2 MIND = depth - 2 SEED = randint(1000000000, 9999999999) R = Random(SEED) # Seed goes here firstBox = (box.minx, box.minz, box.maxx - box.minx, box.maxz - box.minz) h = box.maxy - box.miny boxes = [firstBox] for i in xrange(0, randint(1, 5)): boxes = chopUpBoxes2D(R, boxes, MINW, MIND) for (x, z, w, d) in boxes: Farmland(level, BoundingBox((x, box.miny, z), (w, h, d)))
def create(generatorName, level, areas): # NOTE: Assumption is that this level and box object starts from 0,0,0 # i.e. we're working with a fresh scratchpad schematic and not directly against the world level # simplifies calculation of where to put rooms log("Generating a " + generatorName) while len(areas) > 0: (box, availableFlag) = areas.pop() width, height, depth = getDimensionsFromBox(box) log("Generating a " + generatorName + " at " + str(box)) # A house is a collection of rooms. # Start with a floorplan to determine the room layout # - each room is a box-like thing with a pitched roof # - once assembled doors can be punched through # - Windows projected from the exterior faces of the box # - Chimney blueprint = [ "Bedroom", "Kitchen", "LivingRoom", "Bedroom", "Tower", "Bedroom", "LivingRoom", "Bedroom", "Bedroom", "LivingRoom", "Bedroom", "Bedroom", "Tower" ] log("Making a floor plan") plan = makeFloorPlan(box, blueprint) log("Placing the rooms") for room in plan.rooms: room.placeRoom(level) # Floor, walls, ceilings #furnishRoom(level,room) placeWindows(level) placeDoors(level) placeLighting(level) for room in plan.rooms: room.furnish(level)
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 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 add(self, room): # This is an efficient packing problem # Try to place the new room in the floorplan # Rooms can overlap by one block for a shared wall # For this method we don't care much if there's a gap between rooms. Consider fixing this by growing a blobby room plan later. width, height, depth = self.size roomWidth, roomHeight, roomDepth = room.size # precheck - can it fit the available dimensions? widthGap = width - roomWidth - 2 heightGap = height - roomHeight depthGap = depth - roomDepth - 2 if widthGap < 1 or heightGap < 0 or depthGap < 1: return False # I cannot place this room in this plan because it is too big # Ok, now we can check if there's a spot to place the new room. Don't be too aggressive. We want interesting, not optimal attempts = 100 while attempts >= 0: attempts -= 1 xpos = randint(1, widthGap) zpos = randint(1, depthGap) collides = False i = 0 while i < len(self.rooms): eachRoom = self.rooms[i] x, y, z = eachRoom.pos dx, dy, dz = eachRoom.size # Remember a 1 block overlap is legal when placing rooms so the adjustment is made to the calculation below if checkBoundingBoxIntersect( (xpos + 1, zpos + 1, xpos + roomWidth - 2, zpos + roomDepth - 2), (x, z, x + dx, z + dz)) == True: # Fail - overlap collides = True i = len(self.rooms) # Found an exception, stop looping i += 1 if collides == False: # We didn't hit anything so we can use this position room.pos = ( xpos, 0, zpos ) # Base condition - just put it where it doesn't collide log("Trying to shuffle the room " + str(room.pos) + " " + str(room.size)) # Now shuffle it into the centre until it collides with another room so it is adjacent to an existing room cx = width >> 1 # Centre x cz = depth >> 1 # Centre z keepGoing = True newPosx = xpos newPosz = zpos dx = newPosx - cx # Distance to centre dz = newPosz - cz # Distance to centre dirx = 0 dirz = 0 if dx < 0: dirx = 1 if dx > 0: dirx = -1 if dz < 0: dirz = 1 if dz > 0: dirz = -1 if dirz != 0 or dirx != 0: # We have some wiggle room counter = 100 while keepGoing and counter > 0: counter -= 1 newPosx -= dirx newPosz -= dirz if newPosx > 1 and newPosz > 1 and newPosx + roomWidth < width and newPosz + roomDepth < depth: while i < len(self.rooms): eachRoom = self.rooms[i] x, y, z = eachRoom.pos dx, dy, dz = eachRoom.size if checkBoundingBoxIntersect( (newPosx + 1, newPosz + 1, newPosx + roomWidth - 1, newPosz + roomDepth - 1), (x, z, x + dx, z + dz)) == True: # Overlap # Smash! keepGoing = False i = len(self.rooms) room.pos = (newPosx, 0, newPosz) else: keepGoing = False # Could collide anywhere. Just put it where we first wanted to. self.rooms.append(room) attempts = -1 # Break out of the loop return True # Successful addition return False # We couldn't find a place to pop this room
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))