Пример #1
0
def generate(width: int, height: int) -> GameMap:
    ROOMS = {'min_size': 7, 'max_size': 10, 'max': 30}

    gm = GameMap(width, height)
    gm.tiles[...] = WALL
    rooms: List[Room] = []

    for _ in range(ROOMS['max']):
        w = randint(ROOMS['min_size'], ROOMS['max_size'])
        h = randint(ROOMS['min_size'], ROOMS['max_size'])
        x = randint(0, width - w - 1)
        y = randint(0, height - h - 1)

        new_room = Room(x, y, w, h)
        if any(new_room.intersects(other) for other in rooms):
            continue

        gm.tiles[new_room.inner] = FLOOR
        if rooms:
            other_room = rooms[-1]
            t_start = new_room.center
            t_end = other_room.center
            t_middle = t_start[0], t_end[1]

            gm.tiles[tcod.line_where(*t_start, *t_middle)] = FLOOR
            gm.tiles[tcod.line_where(*t_middle, *t_end)] = FLOOR
        rooms.append(new_room)

    for room in rooms:
        room.place_entities(gm)

    gm.player = spawn_entity(entities_db.player(), gm[rooms[0].center])
    gm.entities.append(gm.player)
    gm.update_fov()
    return gm
Пример #2
0
def generate(width: int, height: int) -> gamemap.GameMap:
    """Return a randomly generated GameMap."""
    room_max_size = 10
    room_min_size = 6
    max_rooms = 30
    AREA_BORDER = 20

    gm = gamemap.GameMap(width, height)
    gm.tiles[...] = FLOOR
    rooms: List[Room] = []

    for i in range(max_rooms):
        # random width and height
        w = random.randint(room_min_size, room_max_size)
        h = random.randint(room_min_size, room_max_size)
        # random position without going out of the boundaries of the map
        x = random.randint(AREA_BORDER, width - AREA_BORDER - w)
        y = random.randint(AREA_BORDER, height - AREA_BORDER - h)
        new_room = Room(x, y, w, h)
        if any(new_room.intersects(other) for other in rooms):
            continue  # This room intersects with a previous room.

        # Mark room inner area as open.
        gm.tiles[new_room.outer] = WALL
        gm.tiles[new_room.inner] = FLOOR
        if rooms:
            # Open a tunnel between rooms.
            if random.randint(0, 99) < 80:
                # 80% of tunnels are to the nearest room.
                other_room = min(rooms, key=new_room.distance_to)
            else:
                # 20% of tunnels are to the previous generated room.
                other_room = rooms[-1]
            t_start = new_room.center
            t_end = other_room.center
            if random.randint(0, 1):
                t_middle = t_start[0], t_end[1]
            else:
                t_middle = t_end[0], t_start[1]
            gm.tiles[tcod.line_where(*t_start, *t_middle)] = FLOOR
            gm.tiles[tcod.line_where(*t_middle, *t_end)] = FLOOR
        rooms.append(new_room)

    # Add player to the first room.
    gm.player = fighter.Player.spawn(gm[5, height - 5],
                                     ai_cls=ai.PlayerControl)
    gm.actors.append(gm.player)

    for room in rooms:
        room.place_entities(gm)

    gm.update_fov()
    return gm
Пример #3
0
    def build_meta_map(self, build_data):
        if not build_data.rooms:
            print(
                f'Room based spawning only work after rooms have been created.'
            )
            raise ProcessLookupError
        else:
            rooms = deepcopy(build_data.rooms)
            connected = dict()
            corridors = list()

            for i, room in enumerate(rooms):
                room_distance = list()
                room_x, room_y = room.center()
                for j, other_room in enumerate(rooms):
                    if i != j and not connected.get(j):
                        other_x, other_y = other_room.center()
                        distance = distance_to(room_x, room_y, other_x,
                                               other_y)
                        room_distance.append((j, distance))

                if room_distance:
                    room_distance = sorted(
                        room_distance,
                        key=lambda room_to_sort: room_to_sort[1])
                    dest_center_x, dest_center_y = rooms[room_distance[0]
                                                         [0]].center()
                    lines = tcod.line_where(room_x, room_y, dest_center_x,
                                            dest_center_y)
                    cell_x = lines[0]
                    cell_y = lines[1]
                    last_x = cell_x[0]
                    last_y = cell_y[0]

                    corridor = list()
                    for cell in range(0, len(cell_y) - 1):
                        if last_x != cell_x[cell] and last_y != cell_y[cell]:
                            if randint(1, 2) == 1:
                                idx = build_data.map.xy_idx(
                                    cell_x[cell], last_y)
                                build_data.map.tiles[idx] = TileType.FLOOR
                            else:
                                idx = build_data.map.xy_idx(
                                    last_x, cell_y[cell])
                                build_data.map.tiles[idx] = TileType.FLOOR
                        idx = int(
                            build_data.map.xy_idx(cell_x[cell], cell_y[cell]))
                        build_data.map.tiles[idx] = TileType.FLOOR
                        last_x = cell_x[cell]
                        last_y = cell_y[cell]
                        corridor.append(idx)

                    corridors.append(corridor)
                    connected[i] = True
                    build_data.take_snapshot()

            build_data.corridors = corridors
Пример #4
0
 def draw(self, pad):
     line = np.array(
         tcod.line_where(round(self.pos[0]), round(self.pos[1]),
                         round(self.pos[0] + self.speed[0]),
                         round(self.pos[1] + self.speed[1]))).T[:-1].T
     line = line.T[line[0] < HEIGHT * 2].T
     line = line.T[line[1] < WIDTH * 2].T
     line = line.T[line[0] >= 0].T
     line = line.T[line[1] >= 0].T
     if not line.size:
         return
     vis = 255
     pad[tuple(line)] |= np.linspace(vis // 2,
                                     vis,
                                     line.shape[1],
                                     dtype=np.uint8)[:, np.newaxis]
Пример #5
0
    def render(self, console):
        if not self.render_next:
            return

        self.target_tiles = []

        if self.mode == MapMode.TARGETING:
            if self.target_mode == AbilityTargeting.LOS:
                line = line_where(self.player.entity.x, self.player.entity.y,
                                  self.target_x, self.target_y, False)
                for _ in range(len(line[0])):
                    self.target_tiles.append(
                        self.game_map.field[line[0][_]][line[1][_]])

        dx = -(self.player.entity.x - int(field_console_width / 2))
        dy = -(self.player.entity.y - int(field_console_height / 2))

        if self.fov_recompute:
            recompute_fov(self.game_map.fov_map, self.player.entity.x,
                          self.player.entity.y, 10)

            for x in range(self.game_map.width):
                for y in range(self.game_map.height):
                    if x < self.player.entity.x - int(field_console_width / 2) \
                            or x > self.player.entity.x + int(field_console_width / 2) \
                            or y < self.player.entity.y - int(field_console_height / 2) \
                            or y > self.player.entity.y + int(field_console_height / 2):
                        continue
                    visible = tcod.map_is_in_fov(self.game_map.fov_map, x, y)

                    if visible:
                        tcod.console_set_char_background(
                            self.field_console, x + dx, y + dy,
                            self.game_map.field[x][y].background_color,
                            tcod.BKGND_SET)
                        if self.mode == MapMode.TARGETING:
                            if abs(x - self.player.entity.x) > self.target_distance \
                                    or abs(y - self.player.entity.y) > self.target_distance:
                                tcod.console_set_char_background(
                                    self.field_console, x + dx, y + dy,
                                    (60, 60, 60), tcod.BKGND_DARKEN)
                            if self.game_map.field[x][y] in self.target_tiles:
                                tcod.console_set_char_background(
                                    self.field_console, x + dx, y + dy,
                                    (60, 40, 40), tcod.BKGND_ADD)
                            if x == self.target_x and y == self.target_y:
                                tcod.console_set_char_background(
                                    self.field_console, x + dx, y + dy,
                                    (60, 40, 20), tcod.BKGND_ADD)
                        self.game_map.field[x][y].explored = True
                    elif self.game_map.field[x][y].explored:
                        tcod.console_set_char_background(
                            self.field_console, x + dx, y + dy,
                            self.game_map.field[x][y].background_color_dark,
                            tcod.BKGND_SET)
                    else:
                        tcod.console_set_char_background(
                            self.field_console, x + dx, y + dy, tcod.black,
                            tcod.BKGND_SET)
                    if (visible or self.game_map.field[x][y].explored
                        ) and self.game_map.field[x][y].stairs:
                        tcod.console_put_char(self.field_console, x + dx,
                                              y + dy, '>', tcod.BKGND_NONE)

        for x in range(field_console_width):
            for y in range(field_console_height):
                if x < (int(field_console_width / 2) - self.player.entity.x) \
                        or x > (self.game_map.width - 1 - self.player.entity.x + int(field_console_width / 2)) \
                        or y < (int(field_console_height / 2) - self.player.entity.y) \
                        or y > (self.game_map.height - 1 - self.player.entity.y + int(field_console_height / 2)):
                    tcod.console_set_char_background(self.field_console, x, y,
                                                     tcod.black,
                                                     tcod.BKGND_SET)

        for entity in self.game_map.entities:
            if entity.x < self.player.entity.x - int(field_console_width / 2) \
                    or entity.x > self.player.entity.x + int(field_console_width / 2) \
                    or entity.y < self.player.entity.y - int(field_console_height / 2) \
                    or entity.y > self.player.entity.y + int(field_console_height / 2):
                continue
            if not tcod.map_is_in_fov(self.game_map.fov_map, entity.x,
                                      entity.y):
                continue
            # Don't render an item entity if there's already one on this tile
            if isinstance(entity, ItemEntity) and self.game_map.get_monster_at(
                    entity.x, entity.y) is not None:
                continue
            # Don't render a dead entity if there's already one on this tile
            if isinstance(entity, MonsterEntity) \
                    and entity.dead \
                    and self.game_map.get_monster_at(entity.x, entity.y) is not None:
                continue
            tcod.console_set_default_foreground(self.field_console,
                                                entity.get_color())
            tcod.console_put_char(self.field_console,
                                  entity.x + dx, entity.y + dy,
                                  entity.get_char(), tcod.BKGND_NONE)

        tcod.console_blit(self.field_console, 0, 0, field_console_width,
                          field_console_height, 0, 0, 0)
        self.render_stats()
        self.render_log()
Пример #6
0
    def build_initial_map(self, build_data):
        # starting point
        x, y = build_data.map.width // 2, build_data.map.height // 2
        start_idx = build_data.map.xy_idx(x, y)
        build_data.take_snapshot()

        build_data.map.tiles[start_idx] = TileType.FLOOR
        build_data.map.tiles[start_idx - 1] = TileType.FLOOR
        build_data.map.tiles[start_idx + 1] = TileType.FLOOR
        build_data.map.tiles[start_idx - build_data.map.width] = TileType.FLOOR
        build_data.map.tiles[start_idx + build_data.map.width] = TileType.FLOOR
        build_data.take_snapshot()

        # random walker
        total_tiles = build_data.map.width * build_data.map.height
        desired_floor_tiles = int(self.floor_percent * total_tiles)
        floor_tile_count = build_data.map.tiles.count(TileType.FLOOR)

        while floor_tile_count < desired_floor_tiles:
            if self.algorithm == DLAAlgorithm.WALK_INWARDS:
                digger_x = randint(1, build_data.map.width - 3) + 1
                digger_y = randint(1, build_data.map.height - 3) + 1
                digger_idx = build_data.map.xy_idx(digger_x, digger_y)
                prev_x = digger_x
                prev_y = digger_y

                while build_data.map.tiles[digger_idx] == TileType.WALL:
                    prev_x = digger_x
                    prev_y = digger_y
                    stagger_direction = randint(1, 4)
                    if stagger_direction == 1 and digger_x > 2:
                        digger_x -= 1
                    elif stagger_direction == 2 and digger_x < build_data.map.width - 2:
                        digger_x += 1
                    elif stagger_direction == 3 and digger_y > 2:
                        digger_y -= 1
                    elif stagger_direction == 4 and digger_y < build_data.map.height - 2:
                        digger_y += 1
                    digger_idx = build_data.map.xy_idx(digger_x, digger_y)
                paint(prev_x, prev_y, build_data.map, self.symmetry,
                      self.brush_size)
            elif self.algorithm == DLAAlgorithm.WALK_OUTWARDS:
                digger_x = x
                digger_y = y
                digger_idx = build_data.map.xy_idx(digger_x, digger_y)
                while build_data.map.tiles[digger_idx] == TileType.FLOOR:
                    stagger_direction = randint(1, 4)
                    if stagger_direction == 1 and digger_x > 2:
                        digger_x -= 1
                    elif stagger_direction == 2 and digger_x < build_data.map.width - 2:
                        digger_x += 1
                    elif stagger_direction == 3 and digger_y > 2:
                        digger_y -= 1
                    elif stagger_direction == 4 and digger_y < build_data.map.height - 2:
                        digger_y += 1
                    digger_idx = build_data.map.xy_idx(digger_x, digger_y)
                paint(digger_x, digger_y, build_data.map, self.symmetry,
                      self.brush_size)
            elif self.algorithm == DLAAlgorithm.CENTRAL_ATTRACTOR:
                digger_x = randint(1, build_data.map.width - 3) + 1
                digger_y = randint(1, build_data.map.height - 3) + 1
                digger_idx = build_data.map.xy_idx(digger_x, digger_y)
                prev_x = digger_x
                prev_y = digger_y

                where = tcod.line_where(digger_x,
                                        digger_y,
                                        x,
                                        y,
                                        inclusive=False)
                count = 0
                while build_data.map.tiles[
                        digger_idx] == TileType.WALL and where:
                    prev_x = digger_x
                    prev_y = digger_y
                    digger_x = where[0][count]
                    digger_y = where[1][count]
                    digger_idx = build_data.map.xy_idx(digger_x, digger_y)
                    count += 1
                paint(prev_x, prev_y, build_data.map, self.symmetry,
                      self.brush_size)
            else:
                print(f'Algorithm {self.algorithm} not implemented.')
                raise NotImplementedError
            floor_tile_count = build_data.map.tiles.count(TileType.FLOOR)
            if randint(0, 10) == 1:
                build_data.take_snapshot()