예제 #1
0
파일: manor.py 프로젝트: rjweir/murderrl
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
예제 #2
0
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
예제 #3
0
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
예제 #4
0
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
예제 #5
0
파일: manor.py 프로젝트: rjweir/murderrl
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
예제 #6
0
파일: manor.py 프로젝트: rjweir/murderrl
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