def build_leg (rooms_tall=2, rooms_wide=2, make_corridor=True, do_cleanup=True): """ Create and return a "leg" to be used with add_leg. :``rooms_tall``: How many rooms tall to make the leg. *Default 2*. :``rooms_wide``: How many rooms wide to make the leg. *Max 2. Default 2*. :``make_corridor``: Include a corridor when building. *Default True*. :``do_cleanup``: Perform corridor, etc, clean-up when built. *Default True*. """ assert rooms_wide >= 1 and rooms_wide <= 2 assert rooms_tall >= 1 new_rooms = collection.ShapeCollection() for row in xrange(rooms_tall): rooms = [] for room in xrange(rooms_wide): rooms.append(Room().as_shape()) this_row = collection.ShapeCollection() this_row = shape.adjoin(rooms.pop(), this_row, overlap=-1, collect=True) for room in rooms: this_row = shape.adjoin(this_row, room, overlap=-1, collect=True) new_rooms = shape.underneath(this_row, new_rooms, overlap=1, collect=True) return new_rooms
def build_leg (rooms_tall=2, rooms_wide=2, width_left=12, width_right=12, make_corridor=True, do_cleanup=True): """ Create and return a "leg" to be used with add_leg. :``rooms_tall``: How many rooms tall to make the leg. *Default 2*. :``rooms_wide``: How many rooms wide to make the leg. *Max 2. Default 2*. :``width_left``: The width of the leftmost rooms. *Default 12*. :``width_right``: The width of the rightmost rooms. *Default 12*. :``make_corridor``: Include a corridor when building. *Default True*. :``do_cleanup``: Perform corridor, etc, clean-up when built. *Default True*. """ assert rooms_wide >= 1 and rooms_wide <= 2 assert rooms_tall >= 1 leg_rooms = collection.ShapeCollection() if width_left == None: width_left = random.choice(ROOM_WIDTH_LIST) if width_right == None: width_right = random.choice(ROOM_WIDTH_LIST) heights = [] for r in xrange(rooms_tall): heights.append(7) for column in xrange(rooms_wide): this_col = collection.ShapeCollection() width = width_left if column > 0: width = width_right height_list = heights[:] if len(heights) > 1 and one_chance_in(5): indices = range(len(height_list)) small = random.choice(indices) indices.remove(small) large = random.choice(indices) height_list[small] -= 1 height_list[large] += 2 else: large = random.choice(xrange(len(height_list))) height_list[large] += 1 for row in xrange(rooms_tall): new_room = room.Room(width=width,height=height_list[row]).as_shape() # print "new_room height: %s, this_col height: %s" % (new_room.height(), this_col.height()) this_col = shape.underneath(new_room, this_col, offset_second=False, overlap=1, collect=True) # print "leg_rooms width: %s, this_col width: %s" % (leg_rooms.width(), this_col.width()) leg_rooms = shape.adjoin(leg_rooms, this_col, overlap=-1, collect=True) return leg_rooms
def attach_leg (base, leg, side=SIDE_LEFT, placement=PLACE_TOP, corr_offset = None, x_offset = None): """ Take a result of base_builder() and attach a leg. :``base``: The base shape collection. :``leg``: The leg shape collection. :``side``: Which side the leg should be placed on. *Default ``SIDE_LEFT``*. :``placement``: Whether the leg should be placed above or below. *Default ``PLACE_TOP``*. :``corr_offset``: A number by which to vertically offset the corridor placement. If none, uses the default room height. *Default None*. :``x_offset``: A number by which to horizontally offset the corridor placement. *Default None*. """ assert not base.leg_at(side, placement) old_leg = leg.copy() no_vert_offset = False vert_offset = 0 if base.leg_at(side.opposite(), placement): l = base.get_leg(side.opposite(), placement) vert_offset = base.height() - l.height no_vert_offset = True else: vert_offset = base.height() - 1 # Find the corridor corridor, start = base.corridor(base.main_corridor) assert corridor is not None # Find the corridor's end point stop = coord.Coord(start) stop.x = corridor.width() if side == SIDE_RIGHT: offs = leg[0].width() - start.x leg.offset(coord.Coord(stop.x-offs-1, 0)) if x_offset == None: x_offset = stop.x + start.x elif side == SIDE_LEFT and x_offset == None: x_offset = start.x print "vert_offset: %s, x_offset: %s, no_vert_offset: %s" % (vert_offset, x_offset, no_vert_offset) if corr_offset == None: corr_offset = room.Room().height ncorr_height = leg.height() + corr_offset - 1 new_corridor = Corridor(shape.Column(height=ncorr_height, fill=".")) corridor_offset = None if placement == PLACE_BOTTOM: if no_vert_offset: base.place_on(leg, offset=coord.Coord(0, vert_offset)) else: left_offset = 0 if side == SIDE_RIGHT: left_offset = base.width()-leg.width() base = shape.underneath(base, leg, left_offset=left_offset, overlap=1, collect=True) new_corridor[coord.Coord(0, new_corridor.height()-1)] = "#" corridor_offset = coord.Coord(x_offset, vert_offset - corr_offset + 1) base.append(new_corridor, corridor_offset) elif placement == PLACE_TOP: if no_vert_offset: base.place_on(leg) else: left_offset = 0 if side == SIDE_RIGHT: left_offset = leg.width()-base.width() # print "leg width (%s) - base width (%s) = left_offset (%s)" % (leg.width(), base.width(), left_offset) base = shape.underneath(leg, base, left_offset=left_offset, overlap=1, collect=True) new_corridor[POS_ORIGIN] = "#" corridor_offset = coord.Coord(x_offset, 0) base.append(new_corridor, corridor_offset) if placement == PLACE_TOP: start = coord.Coord(corridor_offset.x - 1, leg.height() - 1) elif placement == PLACE_BOTTOM: start = coord.Coord(corridor_offset.x - 1, vert_offset - corr_offset + 1) base = BuilderCollection(base) base.mark_leg(Leg(side, placement, leg=old_leg)) return base
def base_builder (min_rooms=0, top_left=None, top_right=None, bottom_left=None, bottom_right=None, tl_corr=False, tr_corr=False, bl_corr=False, br_corr=False,top_height=None, bottom_height=None): """ Attempts to build a basic rectangular manor. It returns ShapeCollection and a list of Room objects. :``min_rooms``: The minimum number of rooms. *Default None*. :``top_left``: The width of the top left room. Random, if none. *Default None*. :``top_right``: The width of the top right room. Random, if none. *Default None*. :``bottom_left``: The width of the bottom left room. Random, if none. *Default None*. :``bottom_right``: The width of the bottom right room. Random, if none. *Default None*. :``tl_corr``: If true, leaves a gap for a corridor between the top-left two rooms. *Default False*. :``tr_corr``: If true, leaves a gap for a corridor between the top-right two rooms. *Default False*. :``bl_corr``: If true, leaves a gap for a corridor between the bottom-left two rooms. *Default False*. :``br_corr``: If true, leaves a gap for a corridor between the bottom-right two rooms. *Default False*. :``top_height``: The height of the top row rooms. Random, if none. *Default None*. :``bottom_height``: The height of the bottom row rooms. Random, if none. *Default None*. """ if top_left == None: top_left = random.choice(ROOM_WIDTH_LIST) if top_right == None: top_right = random.choice(ROOM_WIDTH_LIST) if bottom_left == None: bottom_left = random.choice(ROOM_WIDTH_LIST) if bottom_right == None: bottom_right = random.choice(ROOM_WIDTH_LIST) # tl_corr = True # tr_corr = True # bl_corr = True # br_corr = True print "tl: %s, tr: %s, bl: %s, br: %s" % (top_left, top_right, bottom_left, bottom_right) print "tl: %s, tr: %s, bl: %s, br: %s" % (tl_corr, tr_corr, bl_corr, br_corr) # Top row of rooms row1 = [] # Corridor, then bottom row of rooms row2 = [] max_length = 6*12 # currently unused # manor_width = random.randint(max_length/2, max_length) # Decide the row heights. if top_height == None: top_height = random_room_height() if bottom_height == None: bottom_height = random_room_height() print "top_height: %s, bottom_height: %s" % (top_height, bottom_height) # first rooms on either row height1 = top_height height2 = bottom_height check_overlap = False if top_left < bottom_left or top_left == bottom_left and coinflip(): height1 += 2 else: height2 += 2 check_overlap = True first = room.Room(width=top_left, height=height1) row1.append(first) first = room.Room(width=bottom_left, height=height2) row2.append(first) # print "first rooms: height1=%s, height2=%s" % (height1, height2) length1 = top_left + top_right - 2 if tl_corr: length1 += 2 if tr_corr: length1 += 2 length2 = bottom_left + bottom_right - 2 if bl_corr: length2 += 2 if br_corr: length2 += 2 print "Row 1:" print "room 1: w=%s, length1: %s" % (top_left, length1) while len(row1) <= 5: # If we have four rooms, one in three chance of not adding any more # rooms. if len(row1) > 3 and one_chance_in(3): break new_room = room.Room(width=random.choice(ROOM_WIDTH_LIST), height=top_height) row1.append(new_room) length1 += new_room.width - 1 print "room %s: w=%s, length1: %s" % (len(row1), new_room.width, length1) print "room %s: w=%s" % (len(row1)+1, top_right) manor_width = length1 print "\nRow 2:" print "room 1: w=%s, length2: %s" % (bottom_left, length2) while length2 < manor_width: dist_left = manor_width - length2 + 1 if dist_left < 14: new_width = dist_left else: new_width = random.choice(ROOM_WIDTH_LIST) next_width = dist_left - new_width if next_width < 7: new_width = random.choice((6,7,8)) new_room = room.Room(width=new_width, height=bottom_height) row2.append(new_room) length2 += new_width - 1 print "room %s: w=%s, length2: %s" % (len(row2), new_width, length2) print "room %s: w=%s" % (len(row2)+1, bottom_right) # last rooms on either row height1 = top_height height2 = bottom_height if top_right < bottom_right or top_right == bottom_right and coinflip(): height1 += 2 check_overlap = False else: height2 += 2 # check_overlap = True # print "last rooms: height1=%s, height2=%s" % (height1, height2) last = room.Room(width=top_right, height=height1) row1.append(last) last = room.Room(width=bottom_right, height=height2) row2.append(last) print "\nrow1: %s rooms, row2: %s rooms, manor width: %s" % (len(row1), len(row2), manor_width) # Try to get the minimum number of rooms. if len(row1) + len(row2) < min_rooms: return base_builder(min_rooms - 1) # Now, start drawing it! YAY! # First row row1_collection = join_row_rooms(row1, tl_corr, tr_corr) # second row row2_collection = join_row_rooms(row2, bl_corr, br_corr, True) # Finally, make a corridor! overlap = 3 if check_overlap: overlap = 1 my_collection = shape.underneath(row1_collection, row2_collection, overlap=overlap, collect=True) m = BuilderCollection(my_collection) noncorr_left = min(top_left, bottom_left) noncorr_right = min(top_right, bottom_right) corridor_length = my_collection.width() - noncorr_left - noncorr_right # print "noncorr_left: %s, noncorr_right: %s, corridor_length: %s" % (noncorr_left, noncorr_right, corridor_length) corridor = MainCorridor(shape.Row(width=corridor_length, fill=".")) m.append(collection.ShapeCoord(corridor, coord.Coord(noncorr_left, top_height))) return m
def base_builder (): """ Attempts to build a manor based on the style provided. It returns ShapeCollection and a list of Room objects. :``style``: One of ``ONE_CORRIDOR``, ``L_CORRIDOR`` or ``Z_CORRIDOR``. Currently on ``ONE_CORRIDOR`` is supported. *Default ONE_CORRIDOR*. """ # Top row of rooms row1 = [] # Corridor, then bottom row of rooms row2 = [] # We start with the entrance hall and add rooms on either side of it # until we have a minimum of six and a maximum of ten entrance_hall = Room() left = 0 right = 0 row2.append(entrance_hall) while len(row2) <= 5: # If we have six rooms, one in three chance of not adding any more # rooms. if len(row2) > 4 and random.randint(1, 4) == 1: break new_room = Room() if left > right: row2.append(new_room) right += 1 elif left < right: row2.insert(0, new_room) left += 1 else: side = random.randint(-1, 0) if side == -1: right += 1 else: left += 1 row2.insert(side, new_room) while len(row1) < len(row2): new_room = Room() row1.append(new_room) # Now, adjust the rooms at either end to compensate for the corridor: # 1. We can adjust two rooms on the bottom level for height, 2 on the # top for width. # 2. We can adjust one on the bottom and one on the top for height, and # the opposites for width. # 3. We can adjust two rooms on the top level for height, 2 on the # bottom for width. adjust_bottom = random.randint(0, 2) top_offset = 2 overlap = 3 if adjust_bottom == 2: overlap = 1 row2[0].height += 2 row2[-1].height += 2 row1[0].width += 2 row1[-1].width += 2 row2[1].width += 2 row2[-2].width += 2 elif adjust_bottom == 1: side_adjusted = random.randint(-1, 0) side_not_adjusted = -side_adjusted-1 row2[side_adjusted].height += 2 row1[side_not_adjusted].height += 2 row2[side_not_adjusted].width += 2 row1[side_adjusted].width += 2 elif adjust_bottom == 0: overlap = 3 row1[0].height += 2 row1[-1].height += 2 row2[0].width += 2 row2[-1].width += 2 row1[1].width += 2 row1[-2].width += 2 # Now, start drawing it! YAY! # First row first_room = row1[0].as_shape() second_room = row1[1].as_shape() row1_collection = shape.adjoin(first_room, second_room, overlap=1, collect=True) for room in row1[2:]: row1_collection = shape.adjoin(row1_collection, room.as_shape(), overlap=1, collect=True) # second row first_room = row2[0].as_shape() second_room = row2[1].as_shape() # Does some weird stuff to offset everything offset_both = False if first_room.height() == second_room.height(): offset_both = True row2_collection = shape.adjoin(first_room, second_room, top_offset=top_offset, overlap=1, collect=True, offset_both=offset_both) for room in row2[2:]: to = top_offset room_shape = room.as_shape() if room_shape.height() == first_room.height() and not offset_both or room_shape.height() > first_room.height(): to = 0 row2_collection = shape.adjoin(row2_collection, room_shape, top_offset=to, overlap=1, collect=True) # Finally, make a corridor! room_width = Room().width room_height = Room().height my_collection = shape.underneath(row1_collection, row2_collection, overlap=overlap, collect=True) manor = ManorCollection(my_collection) corridor_length = my_collection.width() - room_width * 2 corridor = MainCorridor(shape.Row(width=corridor_length, fill=".")) manor.append(collection.ShapeCoord(corridor, coord.Coord(room_width, room_height))) return manor
def attach_leg (base, leg, side=SIDE_LEFT, placement=PLACE_TOP): """ Take a result of base_builder() and attach a leg. :``base``: The base shape collection. :``leg``: The leg shape collection. :``side``: Which side the leg should be placed on. *Default SIDE_LEFT*. :``placement``: Whether the leg should be placed above or below. *Default PLACE_TOP*. """ assert not base.leg_at(side, placement) no_vert_offset = False if base.leg_at(side.opposite(), placement): no_vert_offset = True # Find the corridor corridor, start = base.corridor(base.main_corridor) assert corridor is not None # Find the corridor's starting point stop = coord.Coord(start) stop.x = corridor.width() if side == SIDE_LEFT: leg.offset(coord.Coord(stop.x-1, 0)) y_offset = stop.x + (Room().width - 1) elif side == SIDE_RIGHT: y_offset = start.x new_corridor = shape.Column(height=leg.height() + Room().height, fill=".") corridor_offset = None if placement == PLACE_BOTTOM: if no_vert_offset: base.place_on(leg) else: base = shape.underneath(base, leg, overlap=1, collect=True) new_corridor[coord.Coord(0, new_corridor.height()-1)] = "#" corridor_offset = coord.Coord(y_offset, Room().height) base.append(new_corridor, corridor_offset) elif placement == PLACE_TOP: if no_vert_offset: base.place_on(leg) else: base = shape.underneath(leg, base, overlap=1, collect=True) new_corridor[coord.Coord(0, 0)] = "#" corridor_offset = coord.Coord(y_offset, 0) base.append(new_corridor, corridor_offset) if placement == PLACE_TOP: start = coord.Coord(corridor_offset.x - 1, leg.height() - 1) elif placement == PLACE_BOTTOM: start = coord.Coord(corridor_offset.x - 1, Room().height + 1) new_shape = shape.Shape(width=3, height=Room().height, fill="#") new_shape.draw_on(shape.Shape(width=1, height=Room().height, fill="."), offset=coord.Coord(1, 0), check_conflict=False) base = ManorCollection(base) base.append(new_shape, start) base.mark_leg(side, placement) return base