def arrange_contents(self, gb):
        # Run a road along one edge of the map. Stick everything else in a
        # sub-rect to arrange there. Keep track of the civilized areas.
        self.wilds = rooms.Room(width=self.width - 10,
                                height=self.height,
                                anchor=anchors.west,
                                parent=self)
        self.wilds.area = pygame.Rect(0, 0, self.wilds.width,
                                      self.wilds.height)
        self.wilds.FUZZY_FILL_TERRAIN = maps.LOGROUND
        self.wilds.GAPFILL = gapfiller.MonsterFiller(spacing=16)
        self.wilds.DEFAULT_ROOM = self.DEFAULT_ROOM

        self.civilized_bits = list()
        for r in self.contents[:]:
            if hasattr(r, "area") and r is not self.wilds:
                self.contents.remove(r)
                self.wilds.contents.append(r)
                if context.CIVILIZED in r.tags:
                    self.civilized_bits.append(r)

        # Create the road.
        self.road = pygame.Rect(self.area.x + self.area.width - 10,
                                self.area.y, 7, self.area.height)

        self.roadbits = list()
        for y in range(10):
            x = self.area.x + self.area.width - 10 + random.randint(0, 2)
            roadseg = rooms.Room(width=5,
                                 height=self.height // 10,
                                 parent=self)
            roadseg.area = pygame.Rect(x, y * roadseg.height, roadseg.width,
                                       roadseg.height)
            self.roadbits.append(roadseg)
class WalledForestScene(RandomScene):
    # Like a cave, but replace certain True walls with trees.
    GAPFILL = gapfiller.MonsterFiller()
    MUTATE = mutator.CellMutator(noise_throttle=100)
    WALL_FILTER = converter.EdgyConverter()
class ForestScene(RandomScene):
    GAPFILL = gapfiller.MonsterFiller()
    WALL_FILTER = converter.ForestConverter(treeline=0.95)
    MUTATE = mutator.CellMutator()
    PREPARE = prep.HeightfieldPrep(loground=0.05, higround=0.85)
class CaveScene(RandomScene):
    GAPFILL = gapfiller.MonsterFiller()
    MUTATE = mutator.CellMutator(noise_throttle=100)
    def arrange_contents(self, gb):
        # Divide the map into two segments.
        if random.randint(1, 2) == 1:
            horizontal_river = True
            subzone_height = (self.height - 10) // 2
            # Horizontal river
            z1 = rooms.Room()
            z1.area = pygame.Rect(0, 0, self.width, subzone_height)
            z1.special_c["bridge_anchor"] = anchors.south
            z2 = rooms.Room()
            z2.area = pygame.Rect(0, 0, self.width, subzone_height)
            z2.area.bottomleft = self.area.bottomleft
            z2.special_c["bridge_anchor"] = anchors.north
            river = pygame.Rect(0, 0, self.width, 7)
        else:
            horizontal_river = False
            subzone_width = (self.width - 10) // 2
            # Vertical river
            z1 = rooms.Room()
            z1.area = pygame.Rect(0, 0, subzone_width, self.height)
            z1.special_c["bridge_anchor"] = anchors.east
            z2 = rooms.Room()
            z2.area = pygame.Rect(0, 0, subzone_width, self.height)
            z2.area.topright = self.area.topright
            z2.special_c["bridge_anchor"] = anchors.west
            river = pygame.Rect(0, 0, 7, self.height)
        if random.randint(1, 2) == 1:
            z1, z2 = z2, z1
        z1.GAPFILL = gapfiller.MonsterFiller()
        z1.DEFAULT_ROOM = self.DEFAULT_ROOM
        z2.GAPFILL = gapfiller.MonsterFiller()
        z2.DEFAULT_ROOM = self.DEFAULT_ROOM
        river.center = self.area.center
        self.fill(gb, river, floor=maps.WATER, wall=None)
        self.fill(gb, river.inflate(3, 3), wall=None)

        # Locate the bridge, before_bridge, and after_bridge rooms, creating them
        # if none currently exist.
        bridge = self.special_c.get("bridge") or self.special_c.setdefault(
            "bridge", rooms.FuzzyRoom(parent=self))
        before_bridge = self.special_c.get(
            "before_bridge") or self.special_c.setdefault(
                "before_bridge", self.DEFAULT_ROOM(parent=self))
        after_bridge = self.special_c.get(
            "after_bridge") or self.special_c.setdefault(
                "after_bridge", self.DEFAULT_ROOM(parent=self))
        before_bridge.anchor = z1.special_c["bridge_anchor"]
        after_bridge.anchor = z2.special_c["bridge_anchor"]

        # Go through the remaining rooms, sorting each into either z1 or z2
        z1_turn = True
        for r in self.contents[:]:
            if isinstance(r, Room):
                if r is bridge:
                    r.area = pygame.Rect(0, 0, r.width, r.height)
                    r.area.center = self.area.center
                elif r is before_bridge:
                    self.contents.remove(r)
                    z1.contents.append(r)
                elif r is after_bridge:
                    self.contents.remove(r)
                    z2.contents.append(r)
                elif context.ENTRANCE in r.tags:
                    self.contents.remove(r)
                    z1.contents.append(r)
                elif context.GOAL in r.tags:
                    self.contents.remove(r)
                    z2.contents.append(r)
                elif z1_turn:
                    self.contents.remove(r)
                    z1.contents.append(r)
                    z1_turn = False
                else:
                    self.contents.remove(r)
                    z2.contents.append(r)
                    z1_turn = True

        self.contents += (z1, z2)
class OpenTunnelScene(SubtleMonkeyTunnelScene):
    GAPFILL = gapfiller.MonsterFiller()
    PREPARE = prep.HeightfieldPrep(loground=0.15, higround=0.7)
class SubtleMonkeyTunnelScene(RandomScene):
    GAPFILL = gapfiller.MonsterFiller()
    DEFAULT_ROOM = rooms.SharpRoom

    def arrange_contents(self, gb):
        # Step Two: Arrange subcomponents within this area.
        closed_area = list()
        # Add already placed rooms to the closed_area list.
        for r in self.contents:
            if hasattr(r, "area") and r.area:
                closed_area.append(r.area)
        # Add rooms with defined anchors next
        for r in self.contents:
            if hasattr(r, "anchor") and r.anchor and hasattr(r, "area"):
                myrect = pygame.Rect(0, 0, r.width, r.height)
                r.anchor(self.area, myrect)
                if myrect.collidelist(closed_area) == -1:
                    r.area = myrect
                    closed_area.append(myrect)
        # Assign areas for unplaced rooms.
        for r in self.contents:
            if hasattr(r, "area") and not r.area:
                myrect = pygame.Rect(0, 0, r.width, r.height)
                count = 0
                while (count < 1000) and not r.area:
                    myrect.x = random.choice(
                        range(self.area.x,
                              self.area.x + self.area.width - r.width))
                    myrect.y = random.choice(
                        range(self.area.y,
                              self.area.y + self.area.height - r.height))
                    if myrect.inflate(8, 8).collidelist(closed_area) == -1:
                        r.area = myrect
                        closed_area.append(myrect)
                    count += 1
                if not r.area:
                    raise RoomError("ROOM ERROR: {}:{} cannot place {}".format(
                        self, str(self.__class__), r))

    def monkey_L_connection(self, gb, x1, y1, x2, y2):
        # Draw an L-connection between these two points, returning list of
        # joined points.
        if random.randint(1, 2) == 1:
            cx, cy = x1, y2
        else:
            cx, cy = x2, y1
        self.draw_direct_connection(gb, x1, y1, cx, cy)
        self.draw_direct_connection(gb, x2, y2, cx, cy)
        return ((cx, cy), )

    def get_monkey_points(self, area):
        # Return list of points where x,y both equal to 2 mod 5.
        mp = list()
        for x in range(area.x, area.x + area.width):
            for y in range(area.y, area.y + area.height):
                if (x % 5 == 2) and (y % 5 == 2):
                    mp.append((x, y))
        return mp

    def connect_contents(self, gb):
        # Step Three: Connect all rooms in contents, making trails on map.
        # For this one, I'm just gonna straight line connect the contents in
        # a circle.
        # Generate list of rooms.
        myrooms = list()
        for r in self.contents:
            if hasattr(r, "area") and r.area:
                myrooms.append(r)

        # Start the list of connected points.
        connected_points = list()
        x0 = random.randint(1, self.gb.width // 5) * 5 - 3
        y0 = random.randint(1, self.gb.height // 5) * 5 - 3
        connected_points.append((x0, y0))

        # Process them
        if myrooms:
            for r in myrooms:
                # Connect r to a random connected point.
                r_points = self.get_monkey_points(r.area)
                in_point = random.choice(r_points)
                dest_point = random.choice(connected_points)
                connected_points += r_points

                self.draw_direct_connection(gb, r.area.centerx, r.area.centery,
                                            in_point[0], in_point[1])
                hall_points = self.monkey_L_connection(gb, in_point[0],
                                                       in_point[1],
                                                       dest_point[0],
                                                       dest_point[1])
                connected_points += hall_points