Esempio n. 1
0
File: fractor.py Progetto: twik/flax
    def generate(self):
        self.map_canvas.clear(Floor)

        # So what I want here is to have a cave system with a room in the
        # middle, then decay the room.
        # Some constraints:
        # - the room must have a wall where the entrance could go, which faces
        # empty space
        # - a wall near the entrance must be destroyed
        # - the player must start in a part of the cave connected to the
        # destroyed entrance
        # - none of the decay applied to the room may block off any of its
        # interesting features

        # TODO it would be nice if i could really write all this without ever
        # having to hardcode a specific direction, so the logic could always be
        # rotated freely
        side = random.choice([Direction.left, Direction.right])

        # TODO assert region is big enough
        room_size = Size(
            random_normal_range(9, int(self.region.width * 0.4)),
            random_normal_range(9, int(self.region.height * 0.4)),
        )

        room_position = self.region.center() - room_size // 2
        room_position += Point(
            random_normal_int(0, self.region.width * 0.1),
            random_normal_int(0, self.region.height * 0.1),
        )

        room_rect = Rectangle(room_position, room_size)
        self.room_region = room_rect

        room = Room(room_rect)

        cave_area = (
            Blob.from_rectangle(self.region)
            - Blob.from_rectangle(room_rect)
        )
        self.cave_region = cave_area
        walls = [point for (point, _) in self.region.iter_border()]
        floors = []
        for point, edge in room_rect.iter_border():
            if edge is side or edge.adjacent_to(side):
                floors.append(point)
                floors.append(point + side)
        generate_caves(
            self.map_canvas, cave_area, CaveWall,
            force_walls=walls, force_floors=floors,
        )

        room.draw_to_canvas(self.map_canvas)

        # OK, now draw a gate in the middle of the side wall
        if side is Direction.left:
            x = room_rect.left
        else:
            x = room_rect.right
        mid_y = room_rect.top + room_rect.height // 2
        if room_rect.height % 2 == 1:
            min_y = mid_y - 1
            max_y = mid_y + 1
        else:
            min_y = mid_y - 2
            max_y = mid_y + 1
        for y in range(min_y, max_y + 1):
            self.map_canvas.set_architecture(Point(x, y), KadathGate)

        # Beat up the border of the room near the gate
        y = random.choice(
            tuple(range(room_rect.top, min_y))
            + tuple(range(max_y + 1, room_rect.bottom))
        )
        for dx in range(-2, 3):
            for dy in range(-2, 3):
                point = Point(x + dx, y + dy)
                # TODO i think what i may want is to have the cave be a
                # "Feature", where i can check whether it has already claimed a
                # tile, or draw it later, or whatever.
                if self.map_canvas._arch_grid[point] is not CaveWall:
                    distance = abs(dx) + abs(dy)
                    ruination = random_normal_range(0, 0.2) + distance * 0.2
                    self.map_canvas.set_architecture(
                        point, e.Rubble(Breakable(ruination)))

        # And apply some light ruination to the inside of the room
        border = list(room_rect.iter_border())
        # TODO don't do this infinitely; give up after x tries
        while True:
            point, edge = random.choice(border)
            if self.map_canvas._arch_grid[point + edge] is CaveWall:
                break
        self.map_canvas.set_architecture(point, CaveWall)
        self.map_canvas.set_architecture(point - edge, CaveWall)
        # TODO this would be neater if it were a slightly more random pattern
        for direction in (
                Direction.up, Direction.down, Direction.left, Direction.right):
            self.map_canvas.set_architecture(
                point - edge + direction, CaveWall)