Esempio n. 1
0
    def place_stairs(self):
        exit = find(lambda room: room.name == 'exit', self.current_level.rooms)

        if (exit):
            x, y = exit.center

            self.down_stairs = Entity(Point(x, y),
                                      '>',
                                      'Stairs',
                                      COLORS.get('stairs'),
                                      render_order=RenderOrder.STAIRS,
                                      always_visible=True)
            self.down_stairs.add_component(Stairs(self.dungeon_level + 1),
                                           "stairs")

            self.current_level.add_entity(self.down_stairs)

        entrance = find(lambda room: room.name == 'entrance',
                        self.current_level.rooms)

        if (entrance):
            x, y = entrance.center

            self.up_stairs = Entity(Point(x, y),
                                    '<',
                                    'Stairs',
                                    COLORS.get('stairs'),
                                    render_order=RenderOrder.STAIRS,
                                    always_visible=True)
            self.up_stairs.add_component(Stairs(self.dungeon_level - 1),
                                         "stairs")

            self.current_level.add_entity(self.up_stairs)
Esempio n. 2
0
 def find_empty_space(self, distance: int) -> Point:
     for x in range(distance, self.width - distance):
         for y in range(distance, self.height - distance):
             touching = 0
             for xi in range(-distance, distance):
                 for yi in range(-distance, distance):
                     if self.dungeon.label(Point(x + xi, y + yi)):
                         touching += 1
             if touching == 0:
                 print(f"returning {Point(x, y)}")
                 return Point(x, y)
     print("returning no point")
     return Point(-1, -1)
Esempio n. 3
0
class Direction(CallableEnum):
    NW = Point(-1, 1)
    N = Point(0, 1)
    NE = Point(1, 1)
    W = Point(-1, 0)
    E = Point(1, 0)
    SW = Point(-1, -1)
    S = Point(0, -1)
    SE = Point(1, -1)

    @classmethod
    def cardinal(cls):
        """
        Yields Point for the cardinal directions (N, E, S, W)
        :return: generator object of Point for each cardinal directions
        """
        for direction in [cls.N, cls.E, cls.S, cls.W]:
            yield direction.value

    @classmethod
    def every(cls):
        for direction in cls:
            yield direction.value

    @staticmethod
    def self():
        return Point(0, 0)
Esempio n. 4
0
    def tile(self, x: int, y: int) -> Tile:
        """

        :param x: x-coordinate of tile
        :type x: int
        :param y: y-coordinate of tile
        :type y: int
        :return: Tile at coordinate (x, y)
        :rtype: Tile
        """

        grids = self.dungeon.grids(Point(x, y))
        tile = Tile.from_grid(Point(x, y), grids)

        return tile
Esempio n. 5
0
    def tick(self, owner, game_map):
        super().tick(owner, game_map)
        if not self.target_position or (self.target_position == owner.point):
            self.target_position = random_walkable_position(game_map, owner)

        path = self.namespace.get("path")

        blocking_entity = None
        if path and len(path) > 1:
            if not game_map.current_level.blocked[path[1][0], path[1][1]]:
                path.pop(0)
                return TreeStates.SUCCESS, [{
                    ResultTypes.MOVE_WITH_PATH: (owner, path)
                }]
            else:
                if self.target_position == Point(path[1][0], path[1][1]):
                    self.target_position = None
                    return TreeStates.SUCCESS, []
                else:
                    blocking_entity = (path[1][0], path[1][1])

        path = get_path_to(game_map, (owner.x, owner.y),
                           (self.target_position.x, self.target_position.y),
                           routing_avoid=owner.movement.routing_avoid,
                           blocking_entity=blocking_entity)

        self.namespace["path"] = path

        if len(path) < 1:
            self.target_position = None
            return TreeStates.SUCCESS, []

        return TreeStates.SUCCESS, [{
            ResultTypes.MOVE_WITH_PATH: (owner, path)
        }]
Esempio n. 6
0
    def tick(self, owner, game_map):
        super().tick(owner, game_map)
        self.current_time += 1
        if self.current_time < self.min_time:
            return TreeStates.FAILURE, []

        if owner.children and not owner.children.can_have_children:
            return TreeStates.FAILURE, []

        if self.current_time > self.max_time or (uniform(
                0, 1), (self.current_time / self.max_time)):
            x, y = random_adjacent((owner.x, owner.y))

            if (game_map.current_level.walkable[x, y]
                    and not game_map.current_level.blocked[x, y]):
                entity = self.maker(Point(x, y))
                target = self.namespace.get("target")
                if target:
                    entity.ai.set_target(target)

                results = [{ResultTypes.ADD_ENTITY: entity}]
                if self.hatch:
                    results.append({ResultTypes.REMOVE_ENTITY: owner})

                if owner.children:
                    owner.children.addChild(entity)

                self.current_time = 0
                return TreeStates.SUCCESS, results
            else:
                logging.info(f"{owner} can't spawn {self.maker} as no room.")
        return TreeStates.FAILURE, []
Esempio n. 7
0
    def tick(self, owner, game_map):
        super().tick(owner, game_map)
        if not self.namespace.get(self.name):
            raise ValueError(f"{self.name} is not in tree namespace!")
        point = self.namespace.get(self.name)
        path = self.namespace.get("path")

        if path and len(path) > 1 and (Point(path[0][0], path[0][1])
                                       == owner.point):
            path.pop(0)

            if not game_map.current_level.blocked[path[0][0], path[0][1]]:
                return TreeStates.SUCCESS, [{
                    ResultTypes.MOVE_WITH_PATH: (owner, path)
                }]

        path = get_path_to(game_map, (owner.x, owner.y), (point.x, point.y),
                           routing_avoid=owner.movement.routing_avoid)
        self.namespace["path"] = path

        if len(path) < 1:
            self.target_position = None
            return TreeStates.SUCCESS, []

        return TreeStates.SUCCESS, [{
            ResultTypes.MOVE_WITH_PATH: (owner, path)
        }]
Esempio n. 8
0
    def place_entities(self, player: Entity) -> List[Entity]:
        max_monsters_per_room = self.map_settings["max_monsters_per_room"]

        self.entities = [player]

        for room in self.rooms[1:]:
            number_of_monsters = randint(0, max_monsters_per_room)

            for i in range(number_of_monsters):
                x = randint(room.left, room.right)
                y = randint(room.top, room.bottom)
                point = Point(x, y)

                if not any([
                        entity
                        for entity in self.entities if entity.position == point
                ]):
                    if randint(0, 100) < 80:
                        monster = Entity(name="goblin",
                                         position=point,
                                         char=Tiles.GOBLIN,
                                         blocks=True)
                    else:
                        monster = Entity(name="orc",
                                         position=point,
                                         char=Tiles.ORC,
                                         blocks=True)

                    self.entities.append(monster)

        return self.entities
Esempio n. 9
0
    def from_center(cls, center: Point, width: int, height: int):
        width_offset = (width + 1) // 2 - 1
        height_offset = (height + 1) // 2 - 1

        top_left = Point(center.x - width_offset, center.y - height_offset)

        return Rect(position=top_left, width=width, height=height)
Esempio n. 10
0
def menu(
    camera_width: int, header: str, options: List[str], width: int, panel_y: int = None, camera: Camera = None
):
    if len(options) > 26:
        raise ValueError("Cannot have a menu with more than 26 options.")

    # Calculate total height for the header (after auto-wrap) and one line per option
    wrapped_header = textwrap.wrap(text=header, width=width * 2)
    height = len(options) + len(wrapped_header)
    if panel_y is None:
        panel_y = 2
    panel = Menu(
        position=Point(x=2, y=panel_y),
        width=camera_width * 2,
        height=height,
        header=wrapped_header,
        options=options,
    )

    if camera:
        camera.clear_view()

    for i, text_line in enumerate(panel.header):
        blt.printf(x=panel.x, y=panel.y + i * 2, s=f"{text_line}")

    letter_index = ord("a")
    for i, option_text in enumerate(options):
        text = f"({chr(letter_index + i)}) {option_text}"
        blt.puts(
            x=panel.x, y=panel.options_y + i * 2, s=f"{text}", align=blt.TK_ALIGN_LEFT
        )
Esempio n. 11
0
    def take_turn(
        self,
        target: Entity,
        fov_map: tcod.map.Map,
        game_map: GameMap,
        entities: List[Entity],
    ):
        results = []

        if self.number_of_turns > 0:
            random_x = self.owner.x + random.randint(0, 2) - 1
            random_y = self.owner.y + random.randint(0, 2) - 1

            if random_x != self.owner.x and random_y != self.owner.y:
                self.owner.move_towards(
                    target_position=Point(random_x, random_y),
                    game_map=game_map,
                    entities=entities,
                )

            self.number_of_turns -= 1
        else:
            self.owner.ai = self.previous_ai
            results.append({
                "message":
                Message(f"The {self.owner.name} is no longer confused!",
                        Colors.RED)
            })

        return results
Esempio n. 12
0
 def move_to_random_adjacent(self, game_map):
     """Move the owner to a random adjacent tile."""
     dx, dy = choice([
         (-1, 1), (0, 1), (1, 1),
         (-1, 0),         (1, 0),
         (-1, -1), (0, -1), (1, -1)])
     self.attempt_move(Point(self.owner.x + dx, self.owner.y + dy), game_map)
Esempio n. 13
0
    def grow_maze(self, start: Point, label: TileType = None):
        """

        :param start:
        :type start: Point
        :param label:
        :type label: map_objects.tile.TileType
        """

        if label is None:
            label = TileType.CORRIDOR
        tiles = []  # tiles to check
        last_direction = Point(0, 0)

        if not self.can_place(start, last_direction):
            return
        region = self.new_region()

        self.place_tile(start, region=region, label=label)
        self.corridors.append(start)

        tiles.append(start)

        while len(tiles) > 0:

            tile = tiles[-1]  # grab last tile

            # see which neighboring tiles can be carved
            open_tiles = []

            for d in Direction.cardinal():

                if self.can_place(tile, d):

                    open_tiles.append(d)

            if len(open_tiles) > 0:

                if (last_direction in open_tiles
                        and randint(1, 101) > self.winding_percent):

                    current_direction = last_direction

                else:
                    # TODO: refactor for random.choice()
                    current_direction = open_tiles[randint(
                        0,
                        len(open_tiles) - 1)]

                self.place_tile(tile + current_direction,
                                region=region,
                                label=label)
                self.corridors.append(tile + current_direction)

                tiles.append(tile + current_direction)  # * 2)
                last_direction = current_direction
            else:
                tiles.remove(tile)
                last_direction = None
Esempio n. 14
0
 def __init__(self, x: int, y: int, width: int, height: int):
     super(Room, self).__init__(Point(x, y), width, height)
     # self.x: int = x
     # self.y: int = y
     # self.width: int = width
     # self.height: int = height
     self.region: int = None
     self.connections: list = []
Esempio n. 15
0
    def place_doors(self):
        doors_tiles = self.current_level.doors

        current_door_tuples = tuple(zip(doors_tiles[0], doors_tiles[1]))

        for x, y in current_door_tuples:
            door = buildings.door(Point(x, y))
            self.current_level.add_entity(door)
Esempio n. 16
0
 def get_extents(self, point: Point, direction: Point):
     if direction == Point(0, 0):
         return point.NW, point.SE
     # north
     elif direction == Point(0, 1):
         return point.N.NW, point.NE
     # east
     elif direction == Point(1, 0):
         return point.NE, point.E.SE
     # west
     elif direction == Point(-1, 0):
         return point.W.NW, point.SW
     # south
     elif direction == Point(0, -1):
         return point.SW, point.S.SE
     else:
         print("get_extents else statement")
         print(f"Direction not valid: point={point}, direction={direction}")
Esempio n. 17
0
    def test_popluate_map(self, player):
        point = self.current_level.find_random_open_position()
        item = equipment.healing_potion(Point(27, 27))
        self.current_level.add_entity(item)

        item2 = equipment.healing_potion(player.point)
        self.current_level.add_entity(item2)

        #cube = bestiary.gelatinous_cube(item.point)
        #self.current_level.add_entity(cube)

        #npc = bestiary.generate_npc(Species.TROLL, self.dungeon_level)
        #npc.set_point(Point(26,26))
        #self.current_level.add_entity(npc)

        npc = bestiary.spawn_point(Point(26, 26), Species.TROLL)
        self.current_level.add_entity(npc)
        self.place_doors()
Esempio n. 18
0
def fireball(**kwargs):
    '''Cast a fireball.

    Does FIRE damage to all damagable entities in a circle centered on the
    target point.

    Parameters
    ----------
    kwargs:
       caster (Entity): Entity that initiated the spell.
       game_map (GameMap): Current game map.
       number_of_dice (int): number of die to roll.
       radius (int): radius of the spell effect.
       target_x (int): x co-ordinate.
       target_y (int): y co-ordinate.
       type_of_dice (int): Type of die to roll.

    Returns
    -------
    results (list)
        Results of casting the spell.
    '''
    caster = kwargs.get('caster')
    game_map = kwargs.get('game_map')
    number_of_dice = kwargs.get('number_of_dice')
    radius = kwargs.get('radius')
    target_x = kwargs.get('target_x')
    target_y = kwargs.get('target_y')
    type_of_dice = kwargs.get('type_of_dice')

    results = []

    if not game_map.current_level.fov[target_x, target_y]:
        results.append({
            ResultTypes.MESSAGE:
            Message('You cannot target a tile outside your field of view.',
                    COLORS.get('neutral_text'))
        })
        return results

    results.append({
        ResultTypes.MESSAGE:
        Message(
            'The fireball explodes, burning everything within {0} tiles!'.
            format(radius), COLORS.get('effect_text'))
    })

    #TODO: refactor, this is probably horribly inefficent
    for entity in game_map.current_level.entities:
        if entity.point.distance_to(Point(
                target_x, target_y)) <= radius and entity.health:
            damage = die_roll(number_of_dice, type_of_dice)
            damage_results, total_damage = entity.health.take_damage(
                damage, caster, DamageType.FIRE)
            results.extend(damage_results)

    return results
Esempio n. 19
0
 def empty(cls, point=Point(-1, -1)):
     """
     creates an empty Tile that is not passable
     :param point: x- and y-coordinates for the tile, defaults to -1, -1 if no point is provided
     :type point: Point
     :return: returns a tile at x and y of point with the label "EMPTY" and not passable
     :rtype Tile
     """
     return Tile(point.x, point.y, label=TileType.EMPTY)
Esempio n. 20
0
 def __init__(self,
              x: int,
              y: int,
              *,
              label: TileType = TileType.EMPTY,
              passable: bool = False):
     self.position: Point = Point(x, y)
     self.label: TileType = label
     self.passable: bool = passable
Esempio n. 21
0
def random_walkable_position(game_map, entity):
    walkable_array = game_map.current_level.make_walkable_array(
        entity.movement.routing_avoid)
    walkable_array[entity.x, entity.y] = True
    open_tiles = np.where(walkable_array == True)
    listOfCoordinates = list(zip(open_tiles[0], open_tiles[1]))

    target = random.choice(listOfCoordinates)
    return Point(target[0], target[1])
Esempio n. 22
0
class Constants:
    screen_width: int = 120 * 2
    screen_height: int = 45 * 2
    window_title: str = "Rogue Trader"

    map_font: str = "map font: mplus-1p-bold.ttf, size=12, spacing=2x2"
    ui_font: str = "ui_font font: mplus-1p-bold.ttf, size=10"
    bar_font: str = "bar font: mplus-1p-bold.ttf, size=6, spacing=2x2"
    hover_font: str = "hover font: mplus-1p-bold.ttf, size=6"

    map_width: int = 80
    map_height: int = 80
    camera_width: int = 65
    camera_height: int = 33

    bar_width: int = 20
    panel_height: int = 12
    ui_panel: Rect = Rect(position=Point(x=0, y=68), width=240, height=24)

    room_min_size: int = 10
    room_max_size: int = 6
    max_rooms: int = 30
    max_monsters: int = 10
    min_monsters: int = 5
    max_items: int = 50

    fov_algorithm: int = 0
    fov_light_walls: bool = True
    fov_radius: int = 10

    player_hp: int = 100
    player_defense: int = 1
    player_power: int = 2

    level_up_base: int = 200
    level_up_factor: int = 150

    @property
    def message_x(self) -> int:
        message_x: int = (self.bar_width + 2) * 2
        return message_x

    @property
    def message_width(self) -> int:
        message_width: int = self.screen_width - ((self.bar_width - 2) * 2)
        return message_width

    @property
    def panel_y(self) -> int:
        panel_y: int = self.screen_height - (self.panel_height * 2)
        return panel_y

    @property
    def message_height(self) -> int:
        panel_height: int = self.panel_height - 1
        return panel_height
Esempio n. 23
0
def handle_mouse(key: int) -> Dict[str, Point]:
    mouse_position: Point = Point(x=blt.state(blt.TK_MOUSE_X) // 2,
                                  y=blt.state(blt.TK_MOUSE_Y) // 2)

    if key == blt.TK_MOUSE_LEFT:
        return {"left_click": mouse_position}
    elif key == blt.TK_MOUSE_RIGHT:
        return {"right_click": mouse_position}

    return {}
Esempio n. 24
0
def translate_point(point, x, y):

    offsets = [[(-1, -1), (0, -1), (-1, 1)], [(1, 0), (0, 0), (-1, 0)],
               [(1, -1), (0, 1), (1, 1)]]

    (a, b) = offsets[x][y]

    change = Point(point.x + a, point.y + b)

    return change
Esempio n. 25
0
 def tiles(self) -> Iterator[Tile]:
     for i in range(self.height):
         for j in range(self.width):
             point = Point(x=j, y=i)
             if self.cave_map[j, i]:
                 label = TileType.CAVE
             else:
                 label = TileType.FLOOR
             tile = Tile.from_label(point=point, label=label)
             yield tile
Esempio n. 26
0
 def display(self):
     """
     iterator that begins at bottom left of the dungeon to display properly
     :rtype: List[int, int, Point]
     """
     for i in range(self.height - 1, 0, -1):
         for j in range(self.width):
             # yield i, j - 1, self.grid[i][j - 1]
             yield j, i, self.dungeon.tile(Point(j, i))
     """
Esempio n. 27
0
 def remove_small_walls(self, cave: List[Point]) -> List[Point]:
     for i in range(1, self.map_height - 1):
         for j in range(1, self.map_width - 1):
             point = Point(x=j, y=i)
             wall = self.game_map.is_blocked(point)
             if not wall:
                 continue
             if self.game_map.count_one_step_neighbors(point) == 1:
                 cave.append(point)
                 self.game_map.place_tile(point=point,
                                          tile=Tile.floor(point=point))
     return cave
Esempio n. 28
0
    def tile(self, x: int, y: int) -> Tile:
        """

        :param x: x-coordinate of tile
        :type x: int
        :param y: y-coordinate of tile
        :type y: int
        :return: Tile at coordinate (x, y)
        :rtype: Tile
        """
        tile = self.dungeon.tile(Point(x, y))
        return tile
Esempio n. 29
0
    def build_corridors(self, start_point: Point = None):
        cells = []
        if start_point is None:
            start_point = Point(
                x=randint(1, self.width - 2),
                y=randint(1, self.height - 2),
            )
            # TODO: refactor can_carve
        attempts = 0
        while not self.can_carve(start_point, Direction.self()):
            attempts += 1
            start_point = Point(
                x=randint(1, self.width - 2),
                y=randint(1, self.height - 2),
            )
            # TODO: need to remove this hard stop once everything is combined
            if attempts > 100:
                break

        self.carve(point=start_point,
                   region=self.new_region(),
                   label=TileType.CORRIDOR)
        # add point to corridor list
        self.corridors.append(start_point)
        # add point to open cell list
        cells.append(start_point)

        while cells:
            middle = len(cells) // 2
            start_point = cells[-1]
            possible_moves = self.possible_moves(start_point)
            if possible_moves:
                point = choice(possible_moves)
                self.carve(point=point,
                           region=self.current_region,
                           label=TileType.CORRIDOR)
                self.corridors.append(point)
                cells.append(point)
            else:
                cells.remove(start_point)
Esempio n. 30
0
    def count_one_step_neighbors(self, center: Point) -> int:
        # TODO: refactor to make more generic
        # combine with two_step to take a steps parameter and returns multiple values
        count = 0
        for i in [-1, 0, 1]:
            for j in [-1, 0, 1]:
                point = Point(x=center.x + j, y=center.y + i)
                if not self.in_bounds(point=point):
                    continue
                if self.cave_map[point.x, point.y]:
                    count += 1

        return count