예제 #1
0
    def next_floor(self, player: Entity,
                   message_log: MessageLog,
                   constants: Type['constants']) -> List[Entity]:
        self.dungeon_level += 1
        entities = [player]

        self.tiles = self.initialize_tiles()
        self.make_map(
            constants.max_rooms, constants.room_min_size,
            constants.room_max_size, player, entities)

        player.fighter.heal(player.fighter.max_hp // 2)

        message_log.add_message(
            Message('You take a moment to rest, and recover your strength.',
                    tcod.light_violet))

        return entities
예제 #2
0
def get_game_variables(constants):
    player = Fighter(0, 0, '@', None, constants['player_max_hp'], constants['player_max_mp'], constants['player_start_power'], 'player', constants['default_fov_radius'])
    entities = [player]

    # initializes variables to track when a player regenerates hp and mp
    hp_regen_tick = 0
    mp_regen_tick = 0

    # initializes a blank map
    game_map = GameMap(constants['map_width'], constants['map_height'])
    # chooses algorithm at random to make a map
    game_map.make_map(player, entities)

    # sets up fov map and initializes value telling game whether or not it needs to redraw the players fov
    fov_recompute = True
    fov_map = initialize_fov(game_map)

    # sets up message log and prints start-up messages
    message_log = MessageLog(constants['message_x'], constants['message_width'], constants['message_height'])
    message_log.add_message(Message('Welcome to Ex Oblivione', tcod.yellow))
    message_log.add_message(Message('Reach floor 4 to win'))

    return player, entities, game_map, fov_recompute, fov_map, message_log, hp_regen_tick, mp_regen_tick
예제 #3
0
class EventHandler:
    def __init__(self, game):
        self.events = []
        self.game = game
        self.message_log = MessageLog()

    def add_event(self, event):
        self.events.append(event)

    def resolve_events(self):
        for event in self.events:
            message = event.get("message")
            color = event.get("color")
            victory = event.get("victory")  # True
            level_up = event.get("level_up")  # Entity
            quit_target_mode = event.get("quit_target_mode")  # True

            if not color:
                color = color_config.NEUTRAL_INFO_COLOR

            if message:
                self.message_log.add_message(message, color)

            if victory:
                self.game.current_menu = VictoryMenu()

            if level_up:
                self.game.current_menu = LevelUpMenu(level_up)

            if quit_target_mode:
                self.game.quit_target_mode()

        self.reset_event_list()

    def reset_event_list(self):
        self.events = []
예제 #4
0
    def take_stairs(self, player: Entity, message_log: MessageLog, constants: Dict, dungeon: Dict,
                    direction: int) -> None:
        assert (direction == -1 or direction == 1), "Invalid Direction"
        if direction == 1:
            self.dungeon_level += 1
            self.entities = [player]

            self.fov_map = tcod.map.Map(self.width, self.height, order="F")
            self.explored = np.zeros((self.width, self.height), dtype=bool)

            self.fov_map.walkable[:] = False
            self.fov_map.transparent[:] = False

            self.make_map(constants["max_rooms"], constants["room_min_size"], constants["room_max_size"],
                          constants["map_width"], constants["map_height"], player)

            player.fighter.heal(player.fighter.max_hp // 2)

            dungeon.update({self.dungeon_level: self})

            message_log.add_message(Message('You take a moment to rest, and recover your strength.', tcod.light_violet))

        else:
            pass
예제 #5
0
def main():
    # Initiate important variables
    screen_width = 80
    screen_height = 50

    bar_width = 20
    panel_height = 7
    panel_y = screen_height - panel_height

    message_x = bar_width + 2
    message_width = screen_width - bar_width - 2
    message_height = panel_height - 1

    map_width = 80
    map_height = 43

    room_max_size = 10
    room_min_size = 6
    max_rooms = 30

    fov_algorithm = 0
    fov_light_walls = True
    fov_radius = 10

    max_monsters_per_room = 3
    max_items_per_room = 2

    colors = {
        'dark_wall': libtcod.Color(0, 0, 100),
        'dark_ground': libtcod.Color(50, 50, 150),
        'light_wall': libtcod.Color(130, 110, 50),
        'light_ground': libtcod.Color(200, 180, 50),
    }

    # Initiate the objects that will be important in rendering and the map
    fighter_component = Fighter(hp=30, defense=2, power=5)
    inventory_component = Inventory(26)
    player = Entity(0, 0, '@', libtcod.white, 'Player', blocks=True, render_order=RenderOrder.ACTOR, fighter=fighter_component, inventory=inventory_component)
    entities = [player]

    libtcod.console_set_custom_font('arial10x10.png', libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD)

    libtcod.console_init_root(screen_width, screen_height, 'Cardinal Code', False) #boolean is fullscreen or not

    con = libtcod.console_new(screen_width, screen_height)
    panel = libtcod.console_new(screen_width, panel_height)

    game_map = GameMap(map_width, map_height)
    game_map.make_map(max_rooms, room_min_size, room_max_size, map_width, map_height, player, entities, max_monsters_per_room, max_items_per_room)

    fov_recompute = True

    fov_map = initialize_fov(game_map)

    message_log = MessageLog(message_x, message_width, message_height)

    key = libtcod.Key()
    mouse = libtcod.Mouse()

    game_state = GameStates.PLAYERS_TURN

    # Main game loop
    while not libtcod.console_is_window_closed():
        libtcod.sys_check_for_event(libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, key, mouse)

        # fov_recompute tells if the render function should recompute the FOV
        # recompute_fov will recompute the FOV from render_functions.py based on the initialized variables
        if(fov_recompute):
            recompute_fov(fov_map, player.x, player.y, fov_radius, fov_light_walls, fov_algorithm)

        # Renders the map and the screens
        render_all(con, panel, entities, player, game_map, fov_map, fov_recompute, message_log, screen_width, screen_height, bar_width, panel_height, panel_y, mouse, colors)

        libtcod.console_flush()

        # Clears entities whose position changed
        clear_all(con, entities)

        # Get what key was pressed, from sets of dictionaries
        action = handle_keys(key)

        # Then get the action from the sets of dictionaries established in input_handlers.py
        move = action.get('move')
        pickup = action.get('pickup')
        exit = action.get('exit')
        fullscreen = action.get('fullscreen')

        player_turn_results = []

        # If move has a value and the game_state is the player's state
        if move and game_state == GameStates.PLAYERS_TURN:
            dx, dy = move
            destination_x = player.x + dx
            destination_y = player.y + dy

            # If the player's destination is not blocked, do something
            if not game_map.is_blocked(destination_x, destination_y):
                target = get_blocking_entities_at_location(entities, destination_x, destination_y)

                # If there is an entity at the destination, do this
                if target:
                    player.fighter.attack(target)
                    attack_results = player.fighter.attack(target)
                    player_turn_results.extend(attack_results)
                else:
                    player.move(dx, dy)

                    fov_recompute = True

                    game_state = GameStates.ENEMY_TURN

        elif pickup and game_state == GameStates.PLAYERS_TURN:
            for entity in entities:
                if entity.item and entity.x == player.x and entity.y == player.y:
                    pickup_results = player.inventory.add_item(entity)
                    player_turn_results.extend(pickup_results)

                    break
            else:
                message_log.add_message(Message('There is nothing here to pickup.', libtcod.yellow))

        if exit:
            return True

        if fullscreen:
            libtcod.console_set_fullscreen(not libtcod.console_is_fullscreen)

        for player_turn_result in player_turn_results:
            message = player_turn_result.get('message')
            dead_entity = player_turn_result.get('dead')
            item_added = player_turn_result.get('item_added')

            if message:
                message_log.add_message(message)
            if dead_entity:
                if dead_entity == player:
                    message, game_state = kill_player(dead_entity)
                else:
                    message = kill_monster(dead_entity)

                message_log.add_message(message)

            if item_added:
                entities.remove(item_added)

                game_state = GameStates.ENEMY_TURN

        if game_state == GameStates.ENEMY_TURN:
            for entity in entities:
                if entity.ai:
                    entity.ai.take_turn(player, fov_map, game_map, entities)
                    enemy_turn_results = entity.ai.take_turn(player,fov_map, game_map, entities)

                    for enemy_turn_result in enemy_turn_results:
                        message = enemy_turn_result.get('message')
                        dead_entity = enemy_turn_result.get('dead')

                        if message:
                            message_log.add_message(message)
                        if dead_entity:
                            if dead_entity == player:
                                message, game_state = kill_player(dead_entity)
                            else:
                                message = kill_monster(dead_entity)

                            message_log.add_message(message)

                            if game_state == GameStates.PLAYER_DEAD:
                                break
                        if game_state == GameStates.PLAYER_DEAD:
                            break
            else:
                game_state = GameStates.PLAYERS_TURN
def main():  # Adding the main function for Python 3 compatibility

    # Setting constants and global variables
    screen_width = 80
    screen_height = 50
    bar_width = 20
    panel_height = 7
    panel_y = screen_height - panel_height
    # Adding variables Message log display to show events.
    message_x = bar_width + 2
    message_width = screen_width - bar_width - 2
    message_height = panel_height - 1

    map_width = 80
    map_height = 43
    room_max_size = 10
    room_min_size = 6
    max_rooms = 30
    fov_algorithm = 0
    fov_light_walls = True
    fov_radius = 10
    max_monsters_per_room = 3
    brown_color = libtcod.flame * libtcod.light_blue
    colors = {
        'dark_wall': brown_color,  # Color(0, 0, 100),
        'dark_ground': libtcod.desaturated_orange,  # Color(50, 50, 150)
        'light_wall': libtcod.dark_flame,
        'light_ground': libtcod.light_orange
    }  # Coloring our tiles
    # LIMIT_FPS = 20 # Unused for now
    # Setting player coordinate starting point at center of console
    fighter_component = Fighter(hp=30, defense=2,
                                power=5)  # Setting player attributes
    player = Entity(0,
                    0,
                    '@',
                    libtcod.white,
                    'Player',
                    blocks=True,
                    render_order=RenderOrder.ACTOR,
                    fighter=fighter_component)
    entities = [player]

    # Initializing the library font
    libtcod.console_set_custom_font(
        'arial10x10.png',
        libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD)
    # Now creating the window with size constants, title, and whether fullscreen
    libtcod.console_init_root(screen_width, screen_height,
                              'python/libtcod tutorial', False)
    con = libtcod.console_new(
        screen_width,
        screen_height)  # Allows the ability to create new consoles
    panel = libtcod.console_new(
        screen_width, panel_height)  # New console to hold HP and Messages
    game_map = GameMap(map_width, map_height)  # Initialize the game map
    game_map.make_map(max_rooms, room_min_size, room_max_size, map_width,
                      map_height, player, entities, max_monsters_per_room)
    fov_recompute = True  # Whether to reset the Field of View, True for start of game
    fov_map = initialize_fov(game_map)  #Initialize the Field of View
    message_log = MessageLog(message_x, message_width, message_height)
    key = libtcod.Key()  # Setting keyboard variable for input
    mouse = libtcod.Mouse()  # Setting mouse variable for input
    game_state = GameStates.PLAYERS_TURN  # Sets initial game_state to players turn

    # Next is the main game loop.  We basically print the @ character to the screen in white
    while not libtcod.console_is_window_closed():
        libtcod.sys_check_for_event(
            libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, key, mouse)
        #libtcod.console_set_default_foreground(0, libtcod.white)
        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, fov_radius,
                          fov_light_walls, fov_algorithm)
# Changing the way the console is initialized so we can reference different consoles later

        render_all(con, panel, entities, player, game_map, fov_map,
                   fov_recompute, message_log, screen_width, screen_height,
                   bar_width, panel_height, panel_y, mouse, colors)

        fov_recompute = False

        libtcod.console_flush(
        )  # Flush the console which writes any changes to the screen

        clear_all(con, entities)

        # New setup to call handle_keys() function from input_handlers.py
        action = handle_keys(key)

        move = action.get('move')
        exit = action.get('exit')
        fullscreen = action.get('fullscreen')

        player_turn_results = []  # new dictionary

        if move and game_state == GameStates.PLAYERS_TURN:
            dx, dy = move
            destination_x = player.x + dx
            destination_y = player.y + dy

            if not game_map.is_blocked(destination_x, destination_y):
                target = get_blocking_entities_at_location(
                    entities, destination_x, destination_y)

                if target:  # Are you running into a monster?
                    attack_results = player.fighter.attack(
                        target)  # Attack monster
                    player_turn_results.extend(
                        attack_results)  # Get results of attack
                else:
                    player.move(dx, dy)

                    fov_recompute = True  # Recompute the FOV upon movement

                game_state = GameStates.ENEMY_TURN  # Sets state to players turn.

        if exit:
            return True

        if fullscreen:
            libtcod.console_set_fullscreen(not libtcod.console_is_fullscreen())


# Iterate through the results
# Player Results Loop
        for player_turn_result in player_turn_results:
            message = player_turn_result.get('message')  # Get the message part
            dead_entity = player_turn_result.get(
                'dead')  # Get the part as to whether dead or not

            if message:
                message_log.add_message(
                    message)  # Prints any messages for the player turn

            if dead_entity:  # Check is something dead this turn
                if dead_entity == player:  # Is the dead thing the player?
                    message, game_state = kill_player(
                        dead_entity)  # Run kill_player function
                else:
                    message = kill_monster(
                        dead_entity)  # Run kill_monster function

                message_log.add_message(message)
        # Enemy Results Loop
        if game_state == GameStates.ENEMY_TURN:  # Checks to see if enemy turn
            for entity in entities:  # Cycles through entities looking for monsters
                if entity.ai:  # If entity is not the player and has ai.
                    # Set a list that calls the take_turn function for the ai
                    enemy_turn_results = entity.ai.take_turn(
                        player, fov_map, game_map, entities)

                    for enemy_turn_result in enemy_turn_results:  # Iterate through the list
                        message = enemy_turn_result.get(
                            'message')  # Gather any messages for that ai
                        dead_entity = enemy_turn_result.get(
                            'dead')  # get and dead comments

                        if message:
                            message_log.add_message(
                                message
                            )  # Print any messages for the turn of the ai

                        if dead_entity:  # Check if dead entity this turn
                            if dead_entity == player:  # Is it the player?
                                message, game_state = kill_player(
                                    dead_entity
                                )  # If yes then run kill_player and show message from results
                            else:
                                message = kill_monster(
                                    dead_entity
                                )  # If it's the monster, then kill it.

                            message_log.add_message(message)

                            if game_state == GameStates.PLAYER_DEAD:  # Did the player die?
                                break  # If dead player then end game.

                    if game_state == GameStates.PLAYER_DEAD:
                        break  # Ends game if player dies and monster has died at same time.

            else:
                # Set the game_state back to players turn
                game_state = GameStates.PLAYERS_TURN
예제 #7
0
def main():
    screen_width = 80
    screen_height = 50

    bar_width = 20
    panel_height = 7
    panel_y = screen_height - panel_height

    message_x = bar_width + 2
    message_width = screen_width - bar_width - 2
    message_height = panel_height - 1

    map_width = 80
    map_height = 43

    room_max_size = 10
    room_min_size = 6
    max_rooms = 30

    fov_algorithm = 0
    fov_light_walls = True
    fov_radius = 10

    max_challenges_per_room = 3

    colors = {
        'dark_wall': libtcod.Color(0, 0, 100),
        'dark_ground': libtcod.Color(50, 50, 150),
        'light_wall': libtcod.Color(130, 110, 50),
        'light_ground': libtcod.Color(200, 180, 50)
    }

    player = Entity(0, 0, '@', libtcod.white, 'Player', blocks=True)
    entities = [player]

    entities = [player]

    libtcod.console_set_custom_font(
        'img01.png', libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD)

    libtcod.console_init_root(screen_width, screen_height, 'trabalho de RV',
                              False)

    con = libtcod.console_new(screen_width, screen_height)
    panel = libtcod.console_new(screen_width, panel_height)

    game_map = GameMap(map_width, map_height)
    game_map.make_map(max_rooms, room_min_size, room_max_size, map_width,
                      map_height, player, entities, max_challenges_per_room)

    fov_recompute = True
    fov_map = initialize_fov(game_map)

    message_log = MessageLog(message_x, message_width, message_height)

    key = libtcod.Key()
    mouse = libtcod.Mouse()

    while not libtcod.console_is_window_closed():
        libtcod.sys_check_for_event(libtcod.EVENT_KEY_PRESS, key, mouse)

        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, fov_radius,
                          fov_light_walls, fov_algorithm)

        render_all(con, panel, entities, player, game_map, fov_map,
                   fov_recompute, message_log, screen_width, screen_height,
                   bar_width, panel_height, panel_y, colors)

        fov_recompute = False

        libtcod.console_flush()

        clear_all(con, entities)

        action = handle_keys(key)

        move = action.get('move')
        exit = action.get('exit')
        fullscreen = action.get('fullscreen')

        if move:
            dx, dy = move

            destination_x = player.x + dx
            destination_y = player.y + dy

            if not game_map.is_blocked(destination_x, destination_y):
                target = get_blocking_entities_at_location(
                    entities, destination_x, destination_y)

                if target:
                    message_log.add_message(Message(target.question.text))
                else:
                    player.move(dx, dy)

                    fov_recompute = True

        if exit:
            return True

        if fullscreen:
            libtcod.console_set_fullscreen(not libtcod.console_is_fullscreen())
예제 #8
0
def main():

    # Screen Params
    screen_width = 80
    screen_height = 50

    # UI Params
    bar_width = 20
    panel_height = 7
    panel_y = screen_height - panel_height

    # Message Log Params
    message_x = bar_width + 2
    message_width = screen_height - bar_width - 2
    message_height = panel_height - 1

    # Map Params
    map_width = 80
    map_height = 43

    # Room Params
    room_max_size = 10
    room_min_size = 6
    max_rooms = 30

    # Field of View Params
    fov_algorithm = 0
    fov_light_walls = True
    fov_radius = 10

    # Monsters & Items Params
    max_monsters_per_room = 3
    max_items_per_room = 2

    # Colors for tiles
    colors = {
        'dark_wall': tcod.Color(0, 0, 100),
        'dark_ground': tcod.Color(50, 50, 150),
        'light_wall': tcod.Color(130, 110, 50),
        'light_ground': tcod.Color(200, 180, 50)
    }

    # Entities initialization
    fighter_component = Fighter(hp=30, defense=2, power=5)
    player = Entity(0,
                    0,
                    '@',
                    tcod.white,
                    'Player',
                    blocks=True,
                    render_order=RenderOrder.ACTOR,
                    fighter=fighter_component)
    entities = [player]

    # Game Window initialization
    tcod.console_set_custom_font(
        'arial10x10.png', tcod.FONT_TYPE_GREYSCALE | tcod.FONT_LAYOUT_TCOD)
    tcod.console_init_root(screen_width, screen_height,
                           'Move Fast & Kill Things', False)
    con = tcod.console_new(screen_width, screen_height)

    # UI Panel initialization
    panel = tcod.console_new(screen_width, panel_height)

    # Map initialization
    game_map = GameMap(map_width, map_height)
    game_map.make_map(max_rooms, room_min_size, room_max_size, map_width,
                      map_height, player, entities, max_monsters_per_room,
                      max_items_per_room)

    # Field of View Map Computation
    fov_recompute = True
    fov_map = initialize_fov(game_map)

    # Message log initialization
    message_log = MessageLog(message_x, message_width, message_height)

    # Keyboard & Mouse initialization
    key = tcod.Key()
    mouse = tcod.Mouse()

    # Game State initialized to player's turn
    game_state = GameStates.PLAYERS_TURN

    # GAME LOOP
    while not tcod.console_is_window_closed():
        tcod.sys_check_for_event(tcod.EVENT_KEY_PRESS | tcod.EVENT_MOUSE, key,
                                 mouse)

        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, fov_radius,
                          fov_light_walls, fov_algorithm)

        render_all(con, panel, entities, player, game_map, fov_map,
                   fov_recompute, message_log, screen_width, screen_height,
                   bar_width, panel_height, panel_y, mouse, colors)

        fov_recompute = False

        tcod.console_flush()

        clear_all(con, entities)

        action = handle_keys(key)

        move = action.get('move')
        exit = action.get('exit')
        fullscreen = action.get('fullscreen')

        player_turn_results = []

        if move and game_state == GameStates.PLAYERS_TURN:
            dx, dy = move
            destination_x = player.x + dx
            destination_y = player.y + dy
            if not game_map.is_blocked(destination_x, destination_y):
                target = get_blocking_entities_at_location(
                    entities, destination_x, destination_y)

                if target:
                    # Attack enemy
                    attack_results = player.fighter.attack(target)
                    player_turn_results.extend(attack_results)
                else:
                    # Move player
                    player.move(dx, dy)
                    # Recompute field of vision
                    fov_recompute = True

                game_state = GameStates.ENEMY_TURN

        if exit:
            return True

        if fullscreen:
            tcod.console_set_fullscreen(not tcod.console_is_fullscreen())

        # Handling action results log for player
        for player_turn_result in player_turn_results:
            message = player_turn_result.get('message')
            dead_entity = player_turn_result.get('dead')

            if message:
                message_log.add_message(message)

            if dead_entity:
                if dead_entity == player:
                    message, game_state = kill_player(dead_entity)
                else:
                    message = kill_monster(dead_entity)

                message_log.add_message(message)

        # Handling enemy movement & actions
        if game_state == GameStates.ENEMY_TURN:
            for entity in entities:
                if entity.ai:
                    enemy_turn_results = entity.ai.take_turn(
                        player, fov_map, game_map, entities)

                    for enemy_turn_result in enemy_turn_results:
                        message = enemy_turn_result.get('message')
                        dead_entity = enemy_turn_result.get('dead')

                        if message:
                            message_log.add_message(message)

                        if dead_entity:
                            if dead_entity == player:
                                message, game_state = kill_player(dead_entity)
                            else:
                                message = kill_monster(dead_entity)

                            message_log.add_message(message)

                    if game_state == GameStates.PLAYER_DEAD:
                        break
            else:
                game_state = GameStates.PLAYERS_TURN
예제 #9
0
def main():
    #initilize main variables
    screen_width = 80
    screen_height = 50

    bar_width = 20
    panel_height = 7
    panel_y = screen_height - panel_height

    message_x = bar_width + 2
    message_width = screen_width - bar_width - 2
    message_height = panel_height - 1

    map_width = 80
    map_height = 43

    room_max_size = 10
    room_min_size = 6
    max_rooms = 30

    fov_algorithm = 0
    fov_light_walls = True
    fov_radius = 10

    max_monsters_per_room = 3
    max_items_per_room = 2

    #define color palette
    colors = {
        'dark_wall': libtcod.Color(55, 50, 45),
        'dark_ground': libtcod.Color(15, 15, 15),
        'light_wall': libtcod.Color(70, 55, 40),
        'light_ground': libtcod.Color(30, 20, 15)
    }

    #Create Player
    fighter_component = Fighter(hp=30, defense=2, power=5)
    inventory_component = Inventory(26)
    player = Entity(0,
                    0,
                    '@',
                    libtcod.white,
                    'Player',
                    blocks=True,
                    render_order=RenderOrder.ACTOR,
                    fighter=fighter_component,
                    inventory=inventory_component)
    entities = [player]
    player_won = False

    #set up screen
    libtcod.console_set_custom_font(
        'arial12x12.png',
        libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD)
    libtcod.console_init_root(screen_width, screen_height, 'SimpleRogue',
                              False)
    con = libtcod.console_new(screen_width, screen_height)
    panel = libtcod.console_new(screen_width, panel_height)

    key = libtcod.Key()
    mouse = libtcod.Mouse()

    #Generate map with entities
    game_map = GameMap(map_width, map_height)
    game_map.make_map(max_rooms, room_min_size, room_max_size, map_width,
                      map_height, player, entities, max_monsters_per_room,
                      max_items_per_room)

    fov_recompute = True
    fov_map = initializ_fov(game_map)
    game_state = GameStates.PLAYERS_TURN
    previous_game_state = game_state

    message_log = MessageLog(message_x, message_width, message_height)

    # main game loop
    while not libtcod.console_is_window_closed():
        libtcod.sys_check_for_event(
            libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, key, mouse)

        #Update Display
        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, fov_radius,
                          fov_light_walls, fov_algorithm)

        render_all(con, panel, entities, player, game_map, fov_map,
                   fov_recompute, message_log, screen_width, screen_height,
                   bar_width, panel_height, panel_y, mouse, colors, game_state)
        fov_recompute = False
        libtcod.console_flush()
        clear_all(con, entities)

        #Define possible actions
        action = handle_keys(key, game_state)

        move = action.get('move')
        pickup = action.get('pickup')
        show_inventory = action.get('show_inventory')
        inventory_index = action.get('inventory_index')
        exit = action.get('exit')
        fullscreen = action.get('fullscreen')

        #Clear the last set of results from actions
        player_turn_results = []

        #Handle actions

        #move the player
        if move and game_state == GameStates.PLAYERS_TURN:
            dx, dy = move
            destination_x = player.x + dx
            destination_y = player.y + dy

            if not game_map.is_blocked(destination_x, destination_y):
                target = get_blocking_entities_at_location(
                    entities, destination_x, destination_y)

                if target:
                    player.fighter.attack(target)
                    attack_results = player.fighter.attack(target)
                    player_turn_results.extend(attack_results)
                else:
                    player.move(dx, dy)
                    fov_recompute = True

            game_state = GameStates.ENEMY_TURN

        #try to pick up something
        elif pickup and game_state == GameStates.PLAYERS_TURN:
            for entity in entities:
                if entity.item and entity.x == player.x and entity.y == player.y:
                    pickup_results = player.inventory.add_item(entity)
                    player_turn_results.extend(pickup_results)

                    break
            else:
                message_log.add_message(
                    Message('There is nothing here to pick up.',
                            libtcod.yellow))

        #display the inventory screen
        if show_inventory:
            if game_state != GameStates.SHOW_INVENTORY:
                previous_game_state = game_state
            game_state = GameStates.SHOW_INVENTORY

        #use an item in the inventory
        if inventory_index is not None and previous_game_state != GameStates.PLAYER_DEAD and inventory_index < len(
                player.inventory.items):
            item = player.inventory.items[inventory_index]
            player_turn_results.extend(player.inventory.use(item))

        #exit screen or close game
        if exit:
            if game_state == GameStates.SHOW_INVENTORY:
                game_state = previous_game_state
            else:
                return True

        #toggle full screen view
        if fullscreen:
            libtcod.console_set_fullscreen(not libtcod.console_is_fullscreen())

        #Display results of player actions
        for player_turn_result in player_turn_results:
            message = player_turn_result.get('message')
            dead_entity = player_turn_result.get('dead')
            item_added = player_turn_result.get('item_added')
            item_consumed = player_turn_result.get('consumed')

            if message:
                message_log.add_message(message)

            if dead_entity:
                if dead_entity == player:
                    message, game_states = kill_player(dead_entity)
                else:
                    message = kill_monster(dead_entity)

                message_log.add_message(message)

            if item_added:
                entities.remove(item_added)
                game_state = GameStates.ENEMY_TURN

            if item_consumed:
                game_state = GameStates.ENEMY_TURN

        #check for win (player killed everything)
        fighter_count = 0
        for entity in entities:
            if entity.fighter is not None and entity.name != 'Player':
                fighter_count += 1
        if fighter_count == 0 and player_won != True:
            player_won = True
            message_log.add_message(
                Message("I hope you're proud of yourself...", libtcod.yellow))
            message_log.add_message(Message("You monster!", libtcod.red))

        #Handle enemy actions and display results
        if game_state == GameStates.ENEMY_TURN:
            for entity in entities:
                if entity.ai:
                    enemy_turn_results = entity.ai.take_turn(
                        player, fov_map, game_map, entities)

                    for enemy_turn_result in enemy_turn_results:
                        message = enemy_turn_result.get('message')
                        dead_entity = enemy_turn_result.get('dead')

                        if message:
                            message_log.add_message(message)

                        if dead_entity:
                            if dead_entity == player:
                                message, game_state = kill_player(dead_entity)
                            else:
                                message = kill_monster(dead_entity)

                            message_log.add_message(message)

                            if game_state == GameStates.PLAYER_DEAD:
                                break
            else:
                game_state = GameStates.PLAYERS_TURN
예제 #10
0
def play_game(player, entities, game_map, message_log, game_state, con, panel,
              constants, turns, poison_turns, burned_turns, frozen_turns):

    fov_recompute = True
    pet = 0
    boss = None
    for entity in entities:
        if entity.name == 'Pet':
            pet = entity
            break
    for entity in entities:
        if entity.name == 'Dragonlord':
            boss = entity
            break

    fov_map = initialize_fov(game_map)

    key = libtcod.Key()
    mouse = libtcod.Mouse()

    game_state = GameStates.PLAYERS_TURN
    previous_game_state = game_state

    targeting_item = None
    arrow_targeting_item = None

    while not libtcod.console_is_window_closed():
        libtcod.sys_check_for_event(
            libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, key, mouse)

        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, constants['fov_radius'],
                          constants['fov_light_walls'],
                          constants['fov_algorithm'])

        if game_map.biome == 'The Dungeon':
            colors = {
                'dark_wall': libtcod.darkest_grey,
                'dark_ground': libtcod.darker_grey,
                'light_wall': libtcod.grey,
                'light_ground': libtcod.white,
                'dark_water': libtcod.blue,
                'light_water': libtcod.light_blue
            }
        elif game_map.biome == 'The Icebleak Cavern':
            colors = {
                'dark_wall': libtcod.darkest_cyan,
                'dark_ground': libtcod.darker_cyan,
                'light_wall': libtcod.dark_cyan,
                'light_ground': libtcod.white,
                'dark_water': libtcod.blue,
                'light_water': libtcod.light_blue
            }
        elif game_map.biome == 'The Underglade':
            colors = {
                'dark_wall': libtcod.darker_green,
                'dark_ground': libtcod.darkest_green,
                'light_wall': libtcod.desaturated_green,
                'light_ground': libtcod.brass,
                'dark_water': libtcod.blue,
                'light_water': libtcod.light_blue
            }
        elif game_map.biome == 'The Hadalrealm':
            colors = {
                'dark_wall': libtcod.darkest_red,
                'dark_ground': libtcod.darker_red,
                'light_wall': libtcod.dark_red,
                'light_ground': libtcod.white,
                'dark_water': libtcod.blue,
                'light_water': libtcod.light_blue
            }
        elif game_map.biome == 'Dragonroost':
            colors = {
                'dark_wall': libtcod.darkest_grey,
                'dark_ground': libtcod.darker_grey,
                'light_wall': libtcod.dark_grey,
                'light_ground': libtcod.grey,
                'dark_water': libtcod.blue,
                'light_water': libtcod.light_blue
            }
        elif game_map.biome == 'Oblivion\'s Gate':
            colors = {
                'dark_wall': libtcod.darkest_grey,
                'dark_ground': libtcod.darker_grey,
                'light_wall': libtcod.dark_grey,
                'light_ground': libtcod.white,
                'dark_water': libtcod.blue,
                'light_water': libtcod.light_blue
            }
        elif game_map.biome == 'The Vault':
            colors = {
                'dark_wall': libtcod.darker_yellow,
                'dark_ground': libtcod.dark_yellow,
                'light_wall': libtcod.yellow,
                'light_ground': libtcod.white,
                'dark_water': libtcod.blue,
                'light_water': libtcod.light_blue
            }

        render_all(turns, con, panel, entities, player, game_map, fov_map,
                   fov_recompute, message_log, constants['screen_width'],
                   constants['screen_height'], constants['bar_width'],
                   constants['panel_height'], constants['panel_y'], mouse,
                   colors, game_state)

        fov_recompute = False

        libtcod.console_flush()

        clear_all(con, entities)

        action = handle_keys(key, game_state)
        mouse_action = handle_mouse(mouse)

        player.sound = 0
        Scent.set_scent(game_map, player.x, player.y, turns)

        move = action.get('move')
        pickup = action.get('pickup')
        show_inventory = action.get('show_inventory')
        drop_inventory = action.get('drop_inventory')
        inventory_index = action.get('inventory_index')
        exit = action.get('exit')
        fullscreen = action.get('fullscreen')
        wait = action.get('wait')
        take_up_stairs = action.get('take_up_stairs')
        take_down_stairs = action.get('take_down_stairs')
        level_up = action.get('level_up')
        show_character_screen = action.get('show_character_screen')
        show_help_screen = action.get('show_help_screen')

        left_click = mouse_action.get('left_click')
        right_click = mouse_action.get('right_click')

        up = action.get('up')
        down = action.get('down')
        left = action.get('left')
        right = action.get('right')

        player_turn_results = []

        if player.frozen and frozen_turns > 0:
            game_state = GameStates.ENEMY_TURN

        if player.frozen == False:
            frozen_turns = -42

        if player.burned == False:
            burned_turns = -42

        if player.poisoned == False:
            poison_turns = -42

        if poison_turns == 0:
            player_turn_results.append({
                'message':
                Message('You feel a lot better', libtcod.light_cyan)
            })
            poison_turns = -42
            player.poisoned = False

        if burned_turns == 0:
            player_turn_results.append({
                'message':
                Message('Your burn feels a lot better', libtcod.light_cyan)
            })
            burned_turns = -42
            player.burned = False

        if frozen_turns == 0:
            player_turn_results.append(
                {'message': Message('You defrost', libtcod.light_cyan)})
            frozen_turns = -42
            player.frozen = False

        if wait:
            game_state = GameStates.ENEMY_TURN
            d = randint(0, 100)
            if d < 25:
                message_log.add_message(
                    Message('You stand around doing nothing', libtcod.brass))
            elif d < 50:
                message_log.add_message(
                    Message('You lean on your sword', libtcod.brass))
            elif d < 75:
                message_log.add_message(
                    Message('You stand around looking like a lemon',
                            libtcod.brass))
            else:
                message_log.add_message(
                    Message('You examine your surroundings intensely',
                            libtcod.light_amber))

        if move and game_state == GameStates.PLAYERS_TURN:
            dx, dy = move
            destination_x = player.x + dx
            destination_y = player.y + dy

            if not game_map.is_blocked(destination_x, destination_y):
                target = get_blocking_entities_at_location(
                    entities, destination_x, destination_y)
                if target:
                    if target.name == 'Pet':
                        target = None
                if target:
                    attack_results = player.fighter.attack(target)
                    player_turn_results.extend(attack_results)
                else:

                    if game_map.tiles[player.x][player.y].water == True:
                        if randint(0, 10) == 1:
                            game_map.tiles[destination_x][
                                destination_y].water = True
                            player_turn_results.append({
                                'message':
                                Message(
                                    'You splash water all over the dry bit of floor',
                                    libtcod.cyan)
                            })
                    player.move(dx, dy)
                    player.sound = 10

                    if turns % randint(9, 11) == 0:
                        player.fighter.heal(1)

                    levelup = player.level.add_con_xp(1)
                    if levelup:
                        player.fighter.hp += 20
                        player.fighter.base_max_hp += 20
                        player_turn_results.append({
                            'message':
                            Message(
                                'You feel healthy, you must have been very active',
                                libtcod.fuchsia)
                        })

                    fov_recompute = True

                game_state = GameStates.ENEMY_TURN

        elif pickup and game_state == GameStates.PLAYERS_TURN:
            here = 0
            for entity in entities:
                if entity.name != 'Player' and not entity.stairs and not entity.monster_class == '(Pet)':
                    if (entity.item or entity.equippable
                        ) and entity.x == player.x and entity.y == player.y:
                        here = 1
                        player.sound = 5
                        pickup_results = player.inventory.add_item(entity)
                        player_turn_results.extend(pickup_results)
            else:
                if here == 0:
                    message_log.add_message(
                        Message('There is nothing here to pick up.',
                                libtcod.yellow))

        if show_inventory:
            previous_game_state = game_state
            game_state = GameStates.SHOW_INVENTORY

        if drop_inventory:
            previous_game_state = game_state
            player.sound = 5
            game_state = GameStates.DROP_INVENTORY

        if inventory_index is not None and previous_game_state != GameStates.PLAYER_DEAD and inventory_index < len(
                player.items):
            item = player.items[inventory_index]
            if type(item) != str:
                if game_state == GameStates.SHOW_INVENTORY:
                    success = True
                    if item.item_class == '(Scroll)':
                        difficulty = randint(0, 10)
                        if difficulty > player.fighter.intelligence:
                            success = False
                        else:
                            levelup = player.level.add_int_xp(1)
                            if levelup:
                                message_log.add_message(
                                    Message(
                                        'Your reading grows more accurate!',
                                        libtcod.fuchsia))
                                player.fighter.base_intelligence += 1

                    player_turn_results.extend(
                        player.inventory.use(success,
                                             item,
                                             entities=entities,
                                             fov_map=fov_map))
                elif game_state == GameStates.DROP_INVENTORY:
                    player_turn_results.extend(
                        player.inventory.drop_item(item))
            else:
                message_log.add_message(
                    Message('You can\'t use Headers', libtcod.yellow))

        if take_up_stairs and game_state == GameStates.PLAYERS_TURN and not boss:
            for entity in entities:
                if entity.stairs and entity.x == player.x and entity.y == player.y:
                    pet, entities = game_map.next_floor(
                        player, message_log, constants, entities, 'up')
                    fov_map = initialize_fov(game_map)
                    fov_recompute = True
                    player.sound = 10
                    libtcod.console_clear(con)

                    break
            else:
                message_log.add_message(
                    Message('You can\'t go up here.', libtcod.yellow))

        if take_down_stairs and game_state == GameStates.PLAYERS_TURN and not boss:
            for entity in entities:
                if entity.stairs and entity.x == player.x and entity.y == player.y:
                    pet, entities = game_map.next_floor(
                        player, message_log, constants, entities, 'down')
                    fov_map = initialize_fov(game_map)
                    fov_recompute = True
                    player.sound = 10
                    libtcod.console_clear(con)

                    break
            else:
                message_log.add_message(
                    Message('You can\'t go down here.', libtcod.yellow))

        if level_up:
            if level_up == 'hp':
                player.fighter.base_max_hp += 20
                player.fighter.hp += 20
            elif level_up == 'str':
                player.fighter.base_power += 1
            elif level_up == 'def':
                player.fighter.base_defence += 1
            elif level_up == 'int':
                player.fighter.base_intelligence += 1
            elif level_up == 'dex':
                player.fighter.base_dexterity += 1

            game_state = previous_game_state

        if show_character_screen:
            previous_game_state = game_state
            game_state = GameStates.CHARACTER_SCREEN

        if show_help_screen:
            previous_game_state = game_state
            game_state = GameStates.HELP_SCREEN

        if game_state == GameStates.TARGETING:
            if left_click:
                target_x, target_y = left_click
                item_use_results = player.inventory.use(success,
                                                        targeting_item,
                                                        entities=entities,
                                                        fov_map=fov_map,
                                                        target_x=target_x,
                                                        target_y=target_y)
                player_turn_results.extend(item_use_results)
            elif right_click:
                player_turn_results.append({'targeting_cancelled': True})

        if game_state == GameStates.ARROW_TARGETING:
            direction = None
            if up:
                direction = 'up'
            elif down:
                direction = 'down'
            elif left:
                direction = 'left'
            elif right:
                direction = 'right'
            if direction:
                item_use_results = player.inventory.use(success,
                                                        arrow_targeting_item,
                                                        entities=entities,
                                                        fov_map=fov_map,
                                                        direction=direction)

                player_turn_results.extend(item_use_results)

        if exit:
            if game_state in (GameStates.SHOW_INVENTORY,
                              GameStates.DROP_INVENTORY,
                              GameStates.CHARACTER_SCREEN,
                              GameStates.HELP_SCREEN):
                game_state = previous_game_state
            elif game_state == GameStates.TARGETING or game_state == GameStates.ARROW_TARGETING:
                player_turn_results.append({'targeting_cancelled': True})
            else:
                save_game(player, entities, game_map, message_log, game_state,
                          poison_turns, turns, burned_turns, frozen_turns)
                return True

        if fullscreen:
            libtcod.console_set_fullscreen(not libtcod.console_is_fullscreen())

        for player_turn_result in player_turn_results:
            message = player_turn_result.get('message')
            dead_entity = player_turn_result.get('dead')
            item_added = player_turn_result.get('item_added')
            item_consumed = player_turn_result.get('consumed')
            arrow_consumed = player_turn_result.get('arrow_consumed')
            item_dropped = player_turn_result.get('item_dropped')
            equip = player_turn_result.get('equip')
            targeting = player_turn_result.get('targeting')
            arrow_targeting = player_turn_result.get('arrow_targeting')
            targeting_cancelled = player_turn_result.get('targeting_cancelled')
            player_burned = player_turn_result.get('burned')
            enemy_turn = player_turn_result.get('pass')

            if enemy_turn:
                game_state = GameStates.ENEMY_TURN

            if player_burned:
                player_turn_results.append(
                    {'message': Message('You get Burned', libtcod.flame)})
                burned_turns = randint(5, 10)
                message = player_turn_result.get('message')

            if message:
                message_log.add_message(message)

            if dead_entity:
                if dead_entity == player:
                    message, game_state = kill_player(dead_entity)
                else:
                    message = kill_monster(dead_entity, game_map, entities)
                    arrows = 0
                    for i in range(0, dead_entity.arrows):
                        arrow_break = randint(0, 1)
                        if not arrow_break:
                            item_component = Item(use_function=None)
                            arrow = Entity(dead_entity.x,
                                           dead_entity.y,
                                           '|',
                                           libtcod.sepia,
                                           'Arrow',
                                           item=item_component,
                                           item_class='(Arrow)')
                            entities.append(arrow)
                        else:
                            arrows += 1
                    if arrows == 1:
                        MessageLog.add_message(
                            self=message_log,
                            message=Message(
                                'The arrow stuck in the {0} breaks as it falls over'
                                .format(dead_entity.name), libtcod.red))
                    elif arrows:
                        MessageLog.add_message(
                            self=message_log,
                            message=Message(
                                'The {0} arrows stuck in the {1} breaks as it falls over'
                                .format(arrows,
                                        dead_entity.name), libtcod.red))

                message_log.add_message(message)

            if item_added:
                entities.remove(item_added)

                game_state = GameStates.ENEMY_TURN

            if item_consumed:
                game_state = GameStates.ENEMY_TURN

            if arrow_consumed:
                game_state = GameStates.ENEMY_TURN

            if item_dropped:
                entities.append(item_dropped)

                game_state = GameStates.ENEMY_TURN

            if equip:
                player.sound = 10
                equip_results = player.equipment.toggle_equip(equip)

                for equip_result in equip_results:
                    equipped = equip_result.get('equipped')
                    dequipped = equip_result.get('dequipped')

                    if equipped:
                        message_log.add_message(
                            Message('You equipped the {0}'.format(
                                equipped.name)))

                    if dequipped:
                        message_log.add_message(
                            Message('You dequipped the {0}'.format(
                                dequipped.name)))

                game_state = GameStates.ENEMY_TURN

            if targeting:
                previous_game_state = GameStates.PLAYERS_TURN
                game_state = GameStates.TARGETING

                targeting_item = targeting

                message_log.add_message(targeting_item.item.targeting_message)

            if arrow_targeting:
                player.sound = 5
                previous_game_state = GameStates.PLAYERS_TURN
                game_state = GameStates.ARROW_TARGETING

                arrow_targeting_item = arrow_targeting

                message_log.add_message(
                    arrow_targeting_item.item.targeting_message)

            if targeting_cancelled:
                game_state = previous_game_state

                message_log.add_message(Message('Targeting cancelled'))

        if game_state == GameStates.ENEMY_TURN:
            if turns % int(
                (300 - (game_map.dungeon_level * 2)) / 2) == 0 and turns != 0:
                game_map.add_entity(message_log, entities, fov_map)

            if burned_turns >= 0 and player.burned:
                dead_entity = False
                burned_results = player.fighter.take_damage(4)
                for burned_result in burned_results:
                    dead_entity = burned_result.get('dead')
                if dead_entity:
                    if dead_entity.name == 'Player':
                        message, game_state = kill_player(dead_entity)
                        message_log.add_message(message)
                burned_turns -= 1

            if poison_turns >= 0 and player.poisoned:
                dead_entity = False
                poison_results = player.fighter.take_damage(1)
                for poison_result in poison_results:
                    dead_entity = poison_result.get('dead')
                if dead_entity:
                    if dead_entity.name == 'Player':
                        message, game_state = kill_player(dead_entity)
                        message_log.add_message(message)
                poison_turns -= 1

            if frozen_turns >= 0 and player.frozen:
                frozen_turns -= 1
                if frozen_turns == 0:
                    player.frozen = False

            for entity in entities:
                if entity.ai:
                    pet_there = 0
                    if pet:
                        if entity.distance_to(player) >= entity.distance_to(
                                pet) and entity.name != 'Pet':
                            pet_there = 1
                            enemy_turn_results = entity.ai.take_turn(
                                pet, fov_map, game_map, entities, turns)
                        else:
                            enemy_turn_results = entity.ai.take_turn(
                                player, fov_map, game_map, entities, turns)
                    else:
                        enemy_turn_results = entity.ai.take_turn(
                            player, fov_map, game_map, entities, turns)

                    for enemy_turn_result in enemy_turn_results:
                        if burned_turns >= 0:
                            burned_results = entity.fighter.take_damage(4)
                            for burned_result in burned_results:
                                dead_entity = burned_result.get('dead')
                                if dead_entity.name == 'Player':
                                    message, game_state = kill_player(
                                        dead_entity)
                                    message_log.add_message(message)
                            burned_turns -= 1
                        poisoned, player_burned, frozen = False, False, False
                        if not player.fighter.poison_resistance and not pet_there:
                            poisoned = enemy_turn_result.get('poisoned')
                        if not player.fighter.fire_resistance and not pet_there:
                            player_burned = enemy_turn_result.get('burned')
                        if not player.fighter.poison_resistance and not pet_there:
                            frozen = enemy_turn_result.get('frozen')

                        if player_burned:
                            enemy_turn_results.append({
                                'message':
                                Message('You get Burned', libtcod.flame)
                            })
                            burned_turns = randint(5, 10)
                            player.burned = True
                        if poisoned:
                            enemy_turn_results.append({
                                'message':
                                Message('you start to feel ill', libtcod.green)
                            })
                            poison_turns = randint(20, 50)
                            player.poisoned = True
                        if frozen:
                            enemy_turn_results.append({
                                'message':
                                Message('you stop being able to move!',
                                        libtcod.light_blue)
                            })
                            frozen_turns = randint(2, 5)
                            player.frozen = True

                    for enemy_turn_result in enemy_turn_results:
                        message = enemy_turn_result.get('message')
                        dead_entity = enemy_turn_result.get('dead')

                        if message:
                            message_log.add_message(message)

                        if dead_entity:
                            if dead_entity == player:
                                message, game_state = kill_player(dead_entity)
                            elif dead_entity == pet:
                                pet = 0
                                message = kill_pet(dead_entity)
                            elif dead_entity == boss:
                                game_state = GameStates.WINNING
                                message = kill_boss(dead_entity)
                            else:
                                message = kill_monster(dead_entity, pet,
                                                       game_map)

                            message_log.add_message(message)

                            if game_state == GameStates.PLAYER_DEAD:
                                break

                    if game_state == GameStates.PLAYER_DEAD:
                        break
            else:

                turns += 1

                game_state = GameStates.PLAYERS_TURN
예제 #11
0
def main():
    screen_width = 80
    screen_height = 50
    cardtable_width = 18
    cardtable_height = screen_height
    cardtable_x = screen_width - cardtable_width

    panel_height = 10
    panel_y = screen_height - panel_height
    panel_width = screen_width - cardtable_width

    map_width = screen_width - cardtable_width
    map_height = screen_height - panel_height

    message_x = 2
    message_width = panel_width - 2
    message_height = panel_height - 1

    message_log = MessageLog(message_x, message_width, message_height)

    panel = tcod.console.Console(panel_width, panel_height)
    mapcon = tcod.console.Console(map_width, map_height)
    cardtable = tcod.console.Console(cardtable_width, cardtable_height)

    # number of dice, sideness of dice. values used taken from gunslinger pregen, pg88
    player_charactersheet = Character()
    print(player_charactersheet)


    player = Entity(int(screen_width / 2), int(screen_height / 2), '@', tcod.white, 'Player', True, RenderOrder.ACTOR, Fighter(6))
    entities = [player]

    game_map = tcod.map.Map(map_width, map_height)
    generate_map(game_map, player, entities)

    fov_recompute = True


    fate_pot = Counter({'white': 50, 'red': 25, 'blue':10})
    player_fate = Counter()
    player_fate.update(sample(list(fate_pot.elements()), 3))
    fate_pot.subtract(player_fate)



    # FIXME: Currently, this does not include Jokers, which are required
    #        for decks used in Deadlands. The class can be instantiated to
    #        use jokers, but its use of jokers does not differentiate between
    #        red and black jokers (as required in Deadlands) so the issue of
    #        jokers is left to another day.

    # Also probably the suit hierarchy is not the same as Deadlands; that should be easy
    # to fix when I get to it.
    marshal_deck = pydealer.Deck()
    posse_deck = pydealer.Deck()

    marshal_deck.shuffle()
    posse_deck.shuffle()

    player_hand = pydealer.Stack() # pydealer.Stack()
    marshal_hand = pydealer.Stack()

    player_hand.sort()

    posse_discard = pydealer.Stack()
    marshal_discard = pydealer.Stack()

    tcod.console_set_custom_font('cp437_10x10.png', tcod.FONT_TYPE_GREYSCALE | tcod.FONT_LAYOUT_CP437)
    root_console = tcod.console_init_root(screen_width, screen_height, 'Deadlands Duel', False, tcod.RENDERER_SDL2, vsync=True)

    player_round_movement_budget = player_charactersheet.get_movement_budget()
    move_this_action = 0

    active_card = pydealer.Stack() # posse_deck.deal(1)

    colt_army = {'shots': 6,
                 'max_shots': 6,
                 'range': 10,
                 'damage': {'number_of_dice': 3, 'sideness_of_dice': 6}}

    game_state = GameStates.PLAYERS_TURN

    # FIXME: There's probably an elegant solution to be found in generalizing this
    # list to include the player, and sorting it by action cards, or something.
    enemy_combatants = []

    while True:

        if fov_recompute:
            game_map.compute_fov(player.x, player.y, algorithm=tcod.FOV_PERMISSIVE(5))

            if game_state ==GameStates.PLAYERS_TURN:
                for entity in entities:
                    if entity.name == 'Bandit' and game_map.fov[entity.y, entity.x]:
                        game_state = GameStates.BEGIN_DETAILED_COMBAT_ROUND
                        break

            if game_state ==GameStates.ROUNDS_PLAYERS_ACTION:
                enemies_in_view = False
                for entity in entities:
                    if entity.name == 'Bandit' and game_map.fov[entity.y, entity.x]:
                        enemies_in_view = True
                if enemies_in_view == False:
                    message_log.add_message(Message("All visible bandits dead, leaving combat rounds..."))
                    posse_discard.add(active_card.deal(active_card.size))
                    posse_discard.add(player_hand.deal(player_hand.size))
                    game_state =GameStates.PLAYERS_TURN
                    enemy_combatants = []

        if game_state == GameStates.ENEMY_TURN:
            for entity in entities:
                if (entity.name == 'Bandit') and (not game_map.fov[entity.y, entity.x]):
                    if entity.fighter.shots < 6:
                        # When the player ducks behind a wall to reload their revolver,
                        # the bandits also take advantage of the opportunity!
                        entity.fighter.shots += 1
            game_state = GameStates.PLAYERS_TURN


        if game_state == GameStates.BEGIN_DETAILED_COMBAT_ROUND:
            # Let the player know what's going on
            message_log.add_message(Message("Beginning of combat round!"))

            # Deal the player a hand from the posse deck and calc their movement
            player_round_movement_budget = player_charactersheet.get_movement_budget()
            roll_new_round(player_hand, player_charactersheet, posse_deck, posse_discard, message_log)

            # We *should* deal the enemies an action hand, and calc their movement.
            # FIXME: Currently, we use the ultra-simple shortcut for enemies
            # from the Marshal Tricks section of the rules, dealing them a single card.
            # This combat really isn't on a scale where that is justified, at least not until
            # more enemies are clued in to the combat via sound or a vague awareness metric.
            # Also, enemy movement is not yet implemented, so we don't calc their move rate.
            for entity in entities:
                if entity.name == 'Bandit' and game_map.fov[entity.y, entity.x]:
                    entity.fighter.action_hand = marshal_deck.deal(1)
                    enemy_combatants.append(entity)

            game_state = GameStates.MEDIATE_COMBAT_ROUNDS

        if game_state == GameStates.MEDIATE_COMBAT_ROUNDS:
            # FIXME: Should we keep track of a list of combat activated enemies?
            # As a quick hack, right now it's just FOV.
            # (calculated in BEGIN_DETAILED_COMBAT_ROUNDS conditional above)
            remaining_enemy_cards = False
            for combatant in enemy_combatants:
                if combatant.fighter.action_hand.size > 0:
                    # print(combatant.fighter.action_hand.size)
                    remaining_enemy_cards = True

            if remaining_enemy_cards or (player_hand.size > 0): # and (active_card.size > 0)):

                highest_player = None
                if player_hand.size > 0:
                    highest_player = player_hand[player_hand.size - 1]
                # print("highest player card " + str(highest_player))

                highest_combatant = None
                highest_comb_card = None
                if remaining_enemy_cards:
                    for combatant in enemy_combatants:
                        print("combatant card: " + str(combatant.fighter.action_hand[combatant.fighter.action_hand.size - 1]))
                        if highest_comb_card == None:
                            highest_combatant = combatant
                            highest_comb_card =  combatant.fighter.action_hand[combatant.fighter.action_hand.size - 1]
                        elif combatant.fighter.action_hand[combatant.fighter.action_hand.size - 1] > highest_comb_card:
                            highest_combatant = combatant
                            highest_comb_card =  combatant.fighter.action_hand[combatant.fighter.action_hand.size - 1]

                # print("highest combatant card " + str(highest_comb_card))

                if remaining_enemy_cards and ((highest_combatant) and ((highest_player == None)) or (highest_comb_card > highest_player)):
                    # Enemy turn, in combat rounds. Placeholder.
                    message_log.add_message(Message("The " + highest_combatant.name + " acts on a " + str(highest_comb_card) + "!", tcod.orange))
                    if highest_combatant.fighter.shots > 0:
                        tn = 5
                        modifier = 0 - highest_combatant.fighter.get_most_severe_wound()[1]
                        range_increments = (highest_combatant.distance_to(player) / 3) // colt_army['range']
                        tn += range_increments

                        shootin_roll = skill_roll(2, 8, tn, modifier)
                        success = shootin_roll.get('success')
                        if success:
                            vital_hit = False
                            body_part = None
                            hitlocation = unexploding_roll(20)
                            if (hitlocation == 20):
                                vital_hit = True
                                body_part = 'head'
                            elif 15 <= hitlocation <= 19:
                                body_part = 'guts' #upper
                            elif 11 <= hitlocation <= 14:
                                body_part = '_arm'
                                if unexploding_roll(2) == 1:
                                    body_part = 'left' + body_part
                                else:
                                    body_part = 'right' + body_part
                            elif hitlocation == 10:
                                vital_hit = True
                                body_part = 'guts' #gizzards
                            elif 5 <= hitlocation <= 9:
                                body_part = 'guts' #lower
                            else:
                                body_part = '_leg'
                                if unexploding_roll(2) == 1:
                                    body_part = 'left' + body_part
                                else:
                                    body_part = 'right' + body_part


                            message_log.add_message(Message("The bandit takes aim and shoots, hitting you in the " + body_part + "!", tcod.red))
                            dmg = ranged_weapon_damage_roll(colt_army['damage']['sideness_of_dice'], colt_army['damage']['number_of_dice'], vital_bonus = vital_hit)
                            message_log.add_message(player.fighter.take_positional_damage(dmg, body_part, fate_pot, player_fate))
                            if (player.fighter.body_wounds['guts'] >= 5) or (player.fighter.body_wounds['head'] >= 5):
                                message_log.add_message(kill_monster(player))
                                game_state = GameStates.PLAYER_DEAD
                        else:
                            message_log.add_message(Message("The bandit takes aim and shoots! The bullet whizzes past you!", tcod.orange))
                        highest_combatant.fighter.shots -= 1
                    else:
                        message_log.add_message(Message("The bandit loads his revolver..."))
                        highest_combatant.fighter.shots += 1
                    marshal_discard.add(highest_combatant.fighter.action_hand.deal(1))
                    enemy_combatants.remove(highest_combatant)
                else:
                    # FIXME: This erroneously includes tied situations, which the rules say
                    # should result in simultaneous actions.

                    # Player's turn, in combat rounds.
                    game_state = GameStates.ROUNDS_PLAYERS_ACTION
            else:
                game_state = GameStates.BEGIN_DETAILED_COMBAT_ROUND

        if game_state == GameStates.ROUNDS_ENEMY_ACTION:
            print("Shouldn't be possible???")


        render_all(root_console, entities, mapcon, game_map, cardtable, cardtable_x, player_hand, active_card, player_fate, panel, panel_y, message_log, player.fighter.body_wounds)

        tcod.console_flush()

        action = handle_events()

        move = action.get('move')

        activate_card = action.get('activate_card')

        shoot = action.get('shoot')

        pass_turn = action.get('pass_turn')

        reload = action.get('reload')

        if move and (game_state == GameStates.PLAYERS_TURN):
            dx, dy = move
            destination_x = player.x + dx
            destination_y = player.y + dy
            if (0 <= destination_x < game_map.width) and (0 <= destination_y < game_map.height):
                if game_map.walkable[destination_y, destination_x]:
                    target = get_blocking_entities_at_location(entities, destination_x, destination_y)

                    if target:
                        message_log.add_message(Message('You kick the ' + target.name + ' in the shins, much to its annoyance!'))
                    else:
                        player.move(dx, dy)
                        fov_recompute = True
                    game_state = GameStates.ENEMY_TURN


        if pass_turn and (game_state == GameStates.ROUNDS_PLAYERS_ACTION): # pass action would be more accurate, for how i have modified this since creating it
            # if active_card.size == 0:
            #     posse_discard.add(player_hand.deal(player_hand.size))
            #
            #     player_round_movement_budget = player_charactersheet.get_movement_budget()
            #     roll_new_round(player_hand, player_charactersheet, posse_deck, posse_discard, message_log)
            #elif
            if active_card.size > 0:
                posse_discard.add(active_card.deal(active_card.size))
                game_state = GameStates.MEDIATE_COMBAT_ROUNDS
                # The following should be covered by the MEDIATE_COMBAT_ROUNDS

                # if player_hand.size == 0:
                #     posse_discard.add(player_hand.deal(player_hand.size))
                #
                #     player_round_movement_budget = player_charactersheet.get_movement_budget()
                #     roll_new_round(player_hand, player_charactersheet, posse_deck, posse_discard, message_log)

        if activate_card and (active_card.size == 0) and (game_state == GameStates.ROUNDS_PLAYERS_ACTION):

            #nominate new active card. (test-only terminiology)
            if activate_card == -1:
                move_this_action = 0
                if player_hand.size > 0:
                    active_card.add(player_hand.deal(1, 'top'))
                    # player_hand.sort()

        if reload and ((game_state == GameStates.ROUNDS_PLAYERS_ACTION) or (game_state ==GameStates.PLAYERS_TURN)):
            if colt_army['shots'] == colt_army['max_shots']:
                message_log.add_message(Message("Your revolver is fully loaded.", tcod.blue))
            elif (game_state ==GameStates.PLAYERS_TURN) or ((game_state == GameStates.ROUNDS_PLAYERS_ACTION) and (active_card.size > 0)):
                colt_army['shots'] += 1
                message_log.add_message(Message("You load a bullet into your revolver.", tcod.green))
                if (game_state ==GameStates.ROUNDS_PLAYERS_ACTION):
                    posse_discard.add(active_card.deal(active_card.size))
                    game_state = GameStates.MEDIATE_COMBAT_ROUNDS
                    # if player_hand.size == 0:
                    #     player_round_movement_budget = player_charactersheet.get_movement_budget()
                    #     roll_new_round(player_hand, player_charactersheet, posse_deck, posse_discard, message_log)

        if shoot and (game_state == GameStates.ROUNDS_PLAYERS_ACTION):
            if (active_card.size > 0) and (colt_army['shots'] == 0):
                message_log.add_message(Message("You need to reload!", tcod.red))
            elif (active_card.size > 0) and (colt_army['shots'] > 0):
                # Shoot is currently the only "real" action that uses up the active card.
                modifier = 0
                if move_this_action > ((player_charactersheet.pace * 3) // 5):
                    message_log.add_message(Message("You attempt to draw a bead while running...", tcod.orange))
                    modifier = -4
                elif move_this_action > 0:
                    message_log.add_message(Message("You fire while walking...", tcod.yellow))
                    modifier = -2

                wound_modifier = 0 - player.fighter.get_most_severe_wound()[1]
                modifier += wound_modifier

                nearest_target = None
                nearest_distance = 999
                for entity in entities:
                    if game_map.fov[entity.y, entity.x]:
                        if entity.fighter:
                            if not entity.name is 'Player':
                                new_distance = entity.distance_to(player)
                                if new_distance < nearest_distance:
                                    nearest_distance = new_distance
                                    nearest_target = entity
                tn = 5

                range_increments = (nearest_distance / 3) // colt_army['range']
                tn += range_increments

                shootin_roll = skill_roll(player_charactersheet.shootin_pistol['trait'], player_charactersheet.shootin_pistol['aptitude'], tn, modifier)

                bust = shootin_roll.get('bust')
                failure = shootin_roll.get('failure')
                success = shootin_roll.get('success')
                message_log.add_message(Message("BANG!!", tcod.brass))

                colt_army['shots'] -= 1
                if colt_army['shots'] == 0:
                    message_log.add_message(Message("That was your last loaded bullet!", tcod.red))

                if bust:
                    message_log.add_message(Message("You went bust, and narrowly avoided shooting your own foot!", tcod.red))
                else:
                    if not nearest_target:
                        if failure:
                            message_log.add_message(Message("You shoot the broad side of a barn!"))
                        elif success:
                            if success == 1:
                                message_log.add_message(Message("You shoot some bottles for target practice!", tcod.green))
                            else:
                                message_log.add_message(Message("You put a bullet hole in the forehead of a Wanted poster!", tcod.blue))
                    else:
                        if failure:
                            message_log.add_message(Message("The bullet whizzes past your target!"))
                        elif success:
                            vital_hit = False
                            hitlocation = unexploding_roll(20)
                            if (hitlocation == 20) or (hitlocation == 10):
                                vital_hit = True
                            if success == 1:
                                message_log.add_message(Message("You manage to hit your target!", tcod.green))
                            else:
                                if ((20 - hitlocation) <= success) or (0 < (10 - hitlocation) <= success) or (0 < (hitlocation - 10) <= success):
                                    vital_hit = True
                                message_log.add_message(Message("You accurately shoot your target!", tcod.blue))

                            dmg = ranged_weapon_damage_roll(colt_army['damage']['sideness_of_dice'], colt_army['damage']['number_of_dice'], vital_bonus = vital_hit)

                            message_log.add_message(nearest_target.fighter.take_simple_damage(dmg))
                            if nearest_target.fighter.get_most_severe_wound()[1] >= 5:
                                message_log.add_message(kill_monster(nearest_target))
                                marshal_discard.add(nearest_target.fighter.action_hand.deal(nearest_target.fighter.action_hand.size))

                posse_discard.add(active_card.deal(1))

                game_state = GameStates.MEDIATE_COMBAT_ROUNDS
                # if player_hand.size == 0:
                #     player_round_movement_budget = player_charactersheet.get_movement_budget()
                #     roll_new_round(player_hand, player_charactersheet, posse_deck, posse_discard, message_log)

        # FIXME: As currently written, this lets you move both before and after an action card.
        # First, the game lets you move a partial movement,
        #     then, you can use your single card to initate a "new" action and reset the
        #     tracking of movements per action,
        #       which lets you evade potential running penalties in some situations (penalty not implemented yet)
        if (move and (player_round_movement_budget > 0) and (active_card.size > 0) and (game_state ==GameStates.ROUNDS_PLAYERS_ACTION)):
            dx, dy = move
            destination_x = player.x + dx
            destination_y = player.y + dy
            if (0 <= destination_x < game_map.width) and (0 <= destination_y < game_map.height):
                if game_map.walkable[destination_y, destination_x]:
                    target = get_blocking_entities_at_location(entities, destination_x, destination_y)

                    if target:
                        message_log.add_message(Message('You kick the ' + target.name + ' in the shins, much to its annoyance!'))
                    else:
                        player.move(dx, dy)
                        player_round_movement_budget -= 1
                        # We track our movement taking place in this action card.
                        # We can move up to twice our pace the whole round spread across all our actions.
                        # We incur a running penalty on an action where we have also moved more than our pace;
                        # ie, more than half our full movement budget
                        # (which is calculated to a maximum with running in mind)
                        move_this_action += 1
                        #                       pace in yards.         yds->ft   ft->squares
                        if move_this_action > ((player_charactersheet.pace * 3) // 5):
                            message_log.add_message(Message("Running!!!", tcod.orange))
                        else:
                            message_log.add_message(Message("Walking...", tcod.yellow))
                        fov_recompute = True
예제 #12
0
def main():
    # Screen size
    screen_width = 80
    screen_height = 50
    # UI settings
    bar_width = 20
    panel_height = 7
    panel_y = screen_height - panel_height
    message_x = bar_width + 2
    message_width = screen_width - bar_width - 2
    message_height = panel_height - 1
    # Map size
    map_width = 80
    map_height = 43
    # Room definitions
    max_rooms = 30
    room_min_size = 6
    room_max_size = 10
    # FoV configurations
    fov_algorithm = 0  # use defualt algorithm
    fov_light_walls = True  # light up walls we can see
    fov_radius = 10  # radius of view
    fov_recompute = True  # flag to trigger FoV computations
    # Monster spawning settings
    max_monsters_per_room = 3
    # Define colors to be used in FoV
    colors = {
        "dark_wall": libtcod.Color(0, 0, 100),
        "dark_ground": libtcod.Color(50, 50, 150),
        "light_wall": libtcod.Color(130, 110, 50),
        "light_ground": libtcod.Color(200, 180, 50),
    }
    # Font settings
    libtcod.console_set_custom_font(
        "arial10x10.png",
        libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD)

    # Player initialization
    fighter_component = Fighter(
        hp=30, defense=2, power=5)  # define a fighter component for the player
    inventory_component = Inventory(26)  # Inventory component for the player
    player = Entity(
        0,
        0,
        "@",
        libtcod.white,
        "Player",
        blocks=True,
        render_order=RenderOrder.ACTOR,
        fighter=fighter_component,
        inventory=inventory_component,
    )
    # World entity list
    entities = [player]
    # Map object
    game_map = GameMap(map_width, map_height)
    game_map.make_map(
        max_rooms,
        room_min_size,
        room_max_size,
        player,
        entities,
        max_monsters_per_room=max_monsters_per_room,
    )
    # Fov map object
    fov_map = initialize_fov(game_map)
    # Game state
    game_state = GameStates.PLAYERS_TURN
    previous_game_state = game_state

    # For item targeting
    targeting_item = None

    # Creating screen
    libtcod.console_init_root(screen_width, screen_height,
                              "Roguelike using libtcod", False)

    # Console object
    console = libtcod.console.Console(screen_width, screen_height)
    # Panel object
    panel = libtcod.console.Console(screen_width, panel_height)
    # Message Log object
    message_log = MessageLog(message_x, message_width, message_height)

    # input objects
    key = libtcod.Key()
    mouse = libtcod.Mouse()

    # Game loop
    while not libtcod.console_is_window_closed():
        # Capture input events
        libtcod.sys_check_for_event(
            libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, key, mouse)
        # Trigger FoV calculation
        if fov_recompute == True:
            recompute_fov(fov_map, player.x, player.y, fov_radius,
                          fov_light_walls, fov_algorithm)
        # Initial screen config
        render_all(
            con=console,
            panel=panel,
            entities=entities,
            player=player,
            game_map=game_map,
            fov_map=fov_map,
            fov_recompute=fov_recompute,
            message_log=message_log,
            screen_width=screen_width,
            screen_height=screen_height,
            bar_width=bar_width,
            panel_height=panel_height,
            panel_y=panel_y,
            mouse=mouse,
            colors=colors,
            gs=game_state,
        )
        fov_recompute = False
        libtcod.console_flush()

        # Clear all entities
        clear_all(console, entities)

        # Capture action for given input
        action = handle_keys(key, game_state)
        mouse_action = handle_mouse(mouse)
        # Map values for each action
        move = action.get("move")
        pickup = action.get("pickup")
        show_inventory = action.get("show_inventory")
        drop_inventory = action.get("drop_inventory")
        inv_index = action.get("inventory_index")
        left_click = mouse_action.get("left_click")
        right_click = mouse_action.get("right_click")
        _exit = action.get("exit")
        fullscreen = action.get("fullscreen")
        player_turn_results = []

        # Handle movement. Check if this is players turn
        if move and game_state == GameStates.PLAYERS_TURN:
            dx, dy = move
            dest_x, dest_y = player.x + dx, player.y + dy
            if not game_map.is_blocked(dest_x, dest_y):
                target = get_blocking_entities_at_location(
                    entities, dest_x, dest_y)
                if target:
                    attack_results = player.fighter.attack(target)
                    player_turn_results.extend(attack_results)
                else:
                    player.move(dx, dy)
                    fov_recompute = True
                # Now it is enemies turn
                game_state = GameStates.ENEMY_TURN
        elif pickup and game_state == GameStates.PLAYERS_TURN:
            for entity in entities:
                if entity.item and entity.x == player.x and entity.y == player.y:
                    pickup_results = player.inventory.add_item(entity)
                    player_turn_results.extend(pickup_results)
                    break
            else:
                message_log.add_message(
                    Message("There's nothing to pickup", color=libtcod.yellow))
        # Show player inventory
        if show_inventory:
            previous_game_state = game_state
            game_state = GameStates.SHOW_INVENTORY
        # Drop item dialog
        if drop_inventory:
            previous_game_state = game_state
            game_state = GameStates.DROP_INVENTORY
        if (inv_index is not None
                and previous_game_state != GameStates.PLAYER_DEAD
                and inv_index < len(player.inventory.items)):
            item = player.inventory.items[inv_index]
            if game_state == GameStates.SHOW_INVENTORY:
                player_turn_results.extend(
                    player.inventory.use(item,
                                         entities=entities,
                                         fov_map=fov_map))
            elif game_state == GameStates.DROP_INVENTORY:
                player_turn_results.extend(player.inventory.drop_item(item))
        if game_state == GameStates.TARGET_MODE:
            if left_click:
                target_x, target_y = left_click

                item_use_results = player.inventory.use(
                    targeting_item,
                    entities=entities,
                    fov_map=fov_map,
                    target_x=target_x,
                    target_y=target_y,
                )

                player_turn_results.extend(item_use_results)
            elif right_click:
                player_turn_results.append({"targeting_cancelled": True})
        # Handle game exit
        if _exit:
            if game_state in (GameStates.SHOW_INVENTORY,
                              GameStates.DROP_INVENTORY):
                game_state = previous_game_state
            elif game_state == GameStates.TARGET_MODE:
                player_turn_results.append({"targeting_cancelled": True})
            else:
                return True
        # toggle fullscreen
        if fullscreen:
            libtcod.console_set_fullscreen(not libtcod.console_is_fullscreen())

        # Cycle through players action log
        for player_turn_result in player_turn_results:
            message = player_turn_result.get("message")
            dead_entity = player_turn_result.get("dead")
            item_added = player_turn_result.get("item_added")
            item_consumed = player_turn_result.get("consumed")
            item_dropped = player_turn_result.get("item_dropped")
            targeting = player_turn_result.get("targeting")
            cancelled_targeting = player_turn_result.get("targeting_cancelled")

            if message:
                message_log.add_message(message)
            if dead_entity:
                if dead_entity == player:
                    message, game_state = kill_player(player)
                else:
                    message = kill_monster(dead_entity)
                message_log.add_message(message)
            if item_added:
                entities.remove(item_added)
                game_state = GameStates.ENEMY_TURN
            if item_consumed:
                game_state = GameStates.ENEMY_TURN
            if item_dropped:
                entities.append(item_dropped)
                game_state = GameStates.ENEMY_TURN
            if targeting:
                previous_game_state = GameStates.PLAYERS_TURN
                game_state = GameStates.TARGET_MODE
                targeting_item = targeting
                message_log.add_message(targeting_item.item.targeting_message)
            if cancelled_targeting:
                game_state = previous_game_state
                player_turn_result.get("targeting")

        # After all input is handle, check if this is enemies turn
        if game_state == GameStates.ENEMY_TURN:
            for entity in entities:
                if entity.ai:
                    enemy_turn_results = entity.ai.take_turn(
                        player, fov_map, game_map, entities)

                    # Cycle through players action log
                    for enemy_turn_result in enemy_turn_results:
                        message = enemy_turn_result.get("message")
                        dead_entity = enemy_turn_result.get("dead")

                        if message:
                            message_log.add_message(message)
                        if dead_entity:
                            if dead_entity == player:
                                message, game_state = kill_player(player)
                            else:
                                message = kill_monster(dead_entity)
                            message_log.add_message(message)
                    # If player has died, no need to continue with enemies
                    if game_state == GameStates.PLAYER_DEAD:
                        break

            else:
                game_state = GameStates.PLAYERS_TURN
예제 #13
0
def main():
    screen_width = 80
    screen_height = 80

    bar_width = 20
    panel_height = 10
    panel_y = screen_height - panel_height

    map_width = 80
    map_height = 80 - panel_height

    message_x = bar_width + 2
    message_width = screen_width - bar_width - 2
    message_height = panel_height - 1

    fov_algorithm = 0
    fov_light_walls = True
    fov_radius = 10
    fov_recompute = True

    colors = 0

    entities = []
    items = []
    effects = []

    libtcod.console_set_custom_font(
        'arial10x10.png',
        libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD)
    libtcod.console_init_root(screen_width, screen_height,
                              'Project Magic Circle', False)

    con = libtcod.console_new(screen_width, screen_height)
    panel = libtcod.console_new(screen_width, panel_height)

    seed = 1000

    map = GameMap(map_width, map_height)
    map.create_map(seed)
    fov_map = initialize_fov(map)
    nav_map = initialize_fov(map)
    nav_map_recompute = False
    message_log = MessageLog(message_x, message_width, message_height)

    map.place_entities(entities, 5, 5)
    player = entities[0]

    key = libtcod.Key()
    mouse = libtcod.Mouse()

    game_state = GameStates.STANDART
    realtime = False
    action_buffer = None

    message = Message('To get help press "?"', libtcod.white)
    message_log.add_message(message)
    targeting_item = None
    danger_level = 1

    while not libtcod.console_is_window_closed():
        if nav_map_recompute:
            fov_map = initialize_fov(map)
            nav_map = initialize_fov(map)
            fov_recompute = True
            nav_map_recompute = False

        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, fov_radius,
                          fov_light_walls, fov_algorithm)

        render_all(con, panel, entities, effects, map, fov_map, fov_radius,
                   fov_recompute, message_log, screen_width, screen_height,
                   bar_width, panel_height, panel_y, mouse, colors, game_state)
        fov_recompute = False
        libtcod.console_flush()
        clear_all(con, entities + effects)

        for entity in entities:
            try:
                entity.give_energy(int(entity.speed / 5))
            except:
                pass

        for entity in entities:
            if entity == player:

                if action_buffer == None:
                    if realtime:
                        libtcod.sys_check_for_event(
                            libtcod.EVENT_KEY_PRESS or libtcod.EVENT_MOUSE,
                            key, mouse)
                    else:
                        while True:
                            libtcod.sys_check_for_event(
                                libtcod.EVENT_KEY_PRESS or libtcod.EVENT_MOUSE,
                                key, mouse)
                            render_all(con, panel, entities, effects, map,
                                       fov_map, fov_radius, fov_recompute,
                                       message_log, screen_width,
                                       screen_height, bar_width, panel_height,
                                       panel_y, mouse, colors, game_state)
                            libtcod.console_flush()
                            clear_all(con, entities)
                            if is_valid_input(key, mouse):
                                break
                    keys_action = handle_keys(key, game_state)
                    mouse_action = handle_mouse(mouse, game_state)
                    action_buffer = (keys_action, mouse_action)

                if game_state != GameStates.TARGETING:
                    targeting_item = None
                turn_results = entity.ai.take_action(action_buffer[0],
                                                     action_buffer[1], map,
                                                     fov_map, entities,
                                                     game_state,
                                                     targeting_item)

                if turn_results:
                    for turn_result in turn_results:
                        message = turn_result.get('message')
                        dead_entity = turn_result.get('dead')
                        fov_recompute = turn_result.get('fov_recompute')
                        energy = turn_result.get('not_enough_energy')
                        exit = turn_result.get('exit')
                        fullscreen = turn_result.get('fullscreen')
                        effect = turn_result.get('create effect')
                        item_added = turn_result.get('item_added')
                        item_dropped = turn_result.get('item_dropped')
                        show_inventory = turn_result.get('show_inventory')
                        drop_inventory = turn_result.get('drop_inventory')
                        targeting = turn_result.get('targeting')
                        show_help = turn_result.get('show_help')
                        toggle_realtime = turn_result.get('toggle_realtime')
                        go_deeper = turn_result.get('go_deeper')

                        if message:
                            message = Message(message, libtcod.white)
                            message_log.add_message(message)

                        if dead_entity:
                            if dead_entity == player:
                                message, game_state = kill_player(dead_entity)
                                message = Message(message, libtcod.red)
                            else:
                                message = kill_monster(dead_entity)
                                message = Message(message, libtcod.white)
                            message_log.add_message(message)

                        if effect:
                            superimpose_effect(effect, effects)

                        if energy == None:
                            action_buffer = None

                        if fov_recompute == None:
                            fov_recompute = False

                        if item_added:
                            entities.remove(item_added)

                        if show_inventory:
                            previous_game_state = game_state
                            game_state = GameStates.SHOW_INVENTORY

                        if drop_inventory:
                            previous_game_state = game_state
                            game_state = GameStates.DROP_INVENTORY

                        if item_dropped:
                            entities.append(item_dropped)

                        if targeting:
                            targeting_item = targeting
                            message = Message(
                                targeting_item.item_aspect.targeting_message,
                                libtcod.yellow)
                            message_log.add_message(message)
                            previous_game_state = GameStates.STANDART
                            game_state = GameStates.TARGETING

                        if exit:
                            if game_state in {
                                    GameStates.SHOW_INVENTORY,
                                    GameStates.DROP_INVENTORY,
                                    GameStates.TARGETING, GameStates.HELP
                            }:
                                if game_state == GameStates.TARGETING:
                                    message = Message('Exited targeting',
                                                      libtcod.yellow)
                                    message_log.add_message(message)
                                game_state = previous_game_state
                            else:
                                return True

                        if fullscreen:
                            libtcod.console_set_fullscreen(
                                not libtcod.console_is_fullscreen())

                        if show_help:
                            previous_game_state = game_state
                            game_state = GameStates.HELP

                        if toggle_realtime:
                            message = Message('Gamemode changed',
                                              libtcod.green)
                            message_log.add_message(message)
                            realtime = not realtime

                        if go_deeper:
                            '''clear_all(con, entities)
								items = []
								effects = []
								map = GameMap(map_width, map_height)
								map.initialize_tiles()
								map.create_map(seed+danger_level)
								fov_map = initialize_fov(map)
								nav_map = initialize_fov(map)
								map.place_entities(entities, 5+danger_level, 5+danger_level, player = player)
								player = entities[0]
								danger_level += 2'''
                            pass

                else:
                    action_buffer = None

            else:
                if entity.ai:
                    turn_results = entity.ai.take_action(
                        nav_map, entities, game_state)

                    if turn_results:
                        for turn_result in turn_results:
                            message = turn_result.get('message')
                            dead_entity = turn_result.get('dead')
                            exit = turn_result.get('exit')
                            fullscreen = turn_result.get('fullscreen')
                            effect = turn_result.get('create effect')

                            if message:
                                message = Message(message, libtcod.white)
                                message_log.add_message(message)

                            if dead_entity:
                                if dead_entity == player:
                                    message, game_state = kill_player(
                                        dead_entity)
                                    message = Message(message, libtcod.red)
                                else:
                                    message = kill_monster(dead_entity)
                                    message = Message(message, libtcod.white)
                                message_log.add_message(message)

                            if effect:
                                superimpose_effect(effect, effects)

                            if game_state == GameStates.PLAYER_DEAD:
                                break
예제 #14
0
def main():
    # Needed Variables
    screen_width = 80
    screen_height = 50
    map_width = 80
    map_height = 43

    # health bar
    bar_width = 20
    panel_height = 7
    panel_y = screen_height - panel_height

    # rooms
    room_max_size = 10
    room_min_size = 6
    max_rooms = 30

    # fov
    fov_algorithm = 0
    fov_light_walls = True
    fov_radius = 10

    # monsters
    max_monsters_per_room = 3

    # items
    max_items_per_room = 10

    # message log
    message_x = bar_width + 2
    message_width = screen_width - bar_width - 2
    message_height = panel_height - 1

    colors = {
        'dark_wall': libtcod.Color(0, 0, 100),
        'dark_ground': libtcod.Color(50, 50, 150),
        'light_wall': libtcod.Color(130, 110, 50),
        'light_ground': libtcod.Color(200, 180, 50)
    }

    fighter_component = Fighter(hp=30, defense=2, power=5)
    inventory_component = Inventory(26)
    player = Entity(0,
                    0,
                    '@',
                    libtcod.white,
                    'Player',
                    blocks=True,
                    render_order=RenderOrder.ACTOR,
                    fighter=fighter_component,
                    inventory=inventory_component)
    entities = [player]

    libtcod.console_set_custom_font(
        'arial10x10.png',
        libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD)

    # Creates initial console
    libtcod.console_init_root(screen_width, screen_height,
                              'libtcod tutorial revised', False)

    # Sets default console to draw to.
    console = libtcod.console_new(screen_width, screen_height)
    # hp panel console
    panel = libtcod.console_new(screen_width, panel_height)

    # Creates game map, draws rooms, populates them with monsters and items
    game_map = GameMap(map_width, map_height)
    game_map.make_map(max_rooms, room_min_size, room_max_size, map_width,
                      map_height, player, entities, max_monsters_per_room,
                      max_items_per_room)

    fov_recompute = True
    fov_map = initialize_fov(game_map)

    message_log = MessageLog(message_x, message_width, message_height)

    key = libtcod.Key()
    mouse = libtcod.Mouse()

    game_state = GameStates.PLAYERS_TURN
    # Tracks the old game state, used when opening menus
    previous_game_state = game_state

    targeting_item = None

    while not libtcod.console_is_window_closed():
        libtcod.sys_check_for_event(
            libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, key, mouse)

        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, fov_radius,
                          fov_light_walls, fov_algorithm)

        render_all(console, panel, entities, player, game_map, fov_map,
                   fov_recompute, message_log, screen_width, screen_height,
                   bar_width, panel_height, panel_y, mouse, colors, game_state)

        fov_recompute = False

        libtcod.console_flush()

        clear_all(console, entities)

        action = handle_keys(key, game_state)
        mouse_action = handle_mouse(mouse)

        # Player actions
        move = action.get('move')
        pickup = action.get('pickup')
        # Inventory actions
        show_inventory = action.get('show_inventory')
        drop_inventory = action.get('drop_inventory')
        # Used when interacting with inventory
        inventory_index = action.get('inventory_index')
        # Out of game actions, do not take a turn
        exit = action.get('exit')
        fullscreen = action.get('fullscreen')
        # Mouse clicks
        left_click = mouse_action.get('left_click')
        right_click = mouse_action.get('right_click')

        player_turn_results = []

        if move and game_state == GameStates.PLAYERS_TURN:
            dx, dy = move

            destination_x = player.x + dx
            destination_y = player.y + dy

            if not game_map.is_blocked(destination_x, destination_y):
                target = get_blocking_entities_at_location(
                    entities, destination_x, destination_y)

                if target:
                    attack_results = player.fighter.attack(target)
                    player_turn_results.extend(attack_results)
                else:
                    player.move(dx, dy)

                    fov_recompute = True

                game_state = GameStates.ENEMY_TURN

        elif pickup and game_state == GameStates.PLAYERS_TURN:
            for entity in entities:
                if entity.item and entity.x == player.x and entity.y == player.y:
                    pickup_results = player.inventory.add_item(entity)
                    player_turn_results.extend(pickup_results)

                    break
            else:
                message_log.add_message(
                    Message('There is nothing here to pick up.',
                            libtcod.yellow))

        if show_inventory:
            previous_game_state = game_state
            game_state = GameStates.SHOW_INVENTORY

        if drop_inventory:
            previous_game_state = game_state
            game_state = GameStates.DROP_INVENTORY

        if inventory_index is not None and previous_game_state != GameStates.PLAYER_DEAD and inventory_index < len(
                player.inventory.items):
            item = player.inventory.items[inventory_index]
            if game_state == GameStates.SHOW_INVENTORY:
                player_turn_results.extend(
                    player.inventory.use(item,
                                         entities=entities,
                                         fov_map=fov_map))
            elif game_state == GameStates.DROP_INVENTORY:
                player_turn_results.extend(player.inventory.drop_item(item))

        if game_state == GameStates.TARGETING:
            if left_click:
                target_x, target_y = left_click

                item_use_results = player.inventory.use(targeting_item,
                                                        entities=entities,
                                                        fov_map=fov_map,
                                                        target_x=target_x,
                                                        target_y=target_y)
                player_turn_results.extend(item_use_results)
            elif right_click:
                player_turn_results.append({'targeting_cancelled': True})

        if exit:
            if game_state in (GameStates.SHOW_INVENTORY,
                              GameStates.DROP_INVENTORY):
                game_state = previous_game_state
            elif game_state == GameStates.TARGETING:
                player_turn_results.append({'targeting_cancelled': True})
            else:
                return True

        if fullscreen:
            libtcod.console_set_fullscreen(not libtcod.console_is_fullscreen())

        for player_turn_result in player_turn_results:
            message = player_turn_result.get('message')
            dead_entity = player_turn_result.get('dead')
            item_added = player_turn_result.get('item_added')
            item_consumed = player_turn_result.get('consumed')
            item_dropped = player_turn_result.get('item_dropped')
            targeting = player_turn_result.get('targeting')
            targeting_cancelled = player_turn_result.get('targeting_cancelled')

            if message:
                message_log.add_message(message)

            if targeting_cancelled:
                game_state = previous_game_state

                message_log.add_message(Message('Targeting Cancelled'))

            if dead_entity:
                if dead_entity == player:
                    message, game_state = kill_player(dead_entity)
                else:
                    message = kill_monster(dead_entity)

                message_log.add_message(message)

            if item_added:
                entities.remove(item_added)
                game_state = GameStates.ENEMY_TURN

            if item_consumed:
                game_state = GameStates.ENEMY_TURN

            if targeting:
                previous_game_state = GameStates.PLAYERS_TURN
                game_state = GameStates.TARGETING

                targeting_item = targeting

                message_log.add_message(targeting_item.item.targeting_message)

            if item_dropped:
                entities.append(item_dropped)
                game_state = GameStates.ENEMY_TURN

        if game_state == GameStates.ENEMY_TURN:
            for entity in entities:
                if entity.ai:
                    enemy_turn_results = entity.ai.take_turn(
                        player, fov_map, game_map, entities)

                    for enemy_turn_result in enemy_turn_results:
                        message = enemy_turn_result.get('message')
                        dead_entity = enemy_turn_result.get('dead')

                        if message:
                            message_log.add_message(message)

                        if dead_entity:
                            if dead_entity == player:
                                message, game_state = kill_player(dead_entity)
                            else:
                                message = kill_monster(dead_entity)

                            message_log.add_message(message)

                        if game_state == GameStates.PLAYER_DEAD:
                            break

                    if game_state == GameStates.PLAYER_DEAD:
                        break

                    else:
                        game_state = GameStates.PLAYERS_TURN
예제 #15
0
def play_game(player: Entity, entities: List[Entity], game_map: GameMap,
              message_log: MessageLog, game_state: GameStates,
              root_console: tcod.console.Console, con: tcod.console.Console,
              panel: tcod.console.Console) -> None:
    fov_recompute = True

    fov_map = initialize_fov(game_map)

    mouse = tcod.event.Point(-1, -1)

    if player.fighter.hp > 0:
        game_state = GameStates.PLAYERS_TURN
    else:
        game_state = GameStates.PLAYER_DEAD
    previous_game_state = game_state

    targeting_item = None

    while True:
        action: UserAction = {}
        for event in tcod.event.wait(1):
            if event.type == 'QUIT':
                # XXX: what happens if I do this when in the character screen?
                # or inventory? or while targeting?  will the game load fine?
                save_game(player, entities, game_map, message_log, game_state)
                sys.exit()
            elif event.type == 'KEYDOWN':
                action = handle_keys(event, game_state, mouse)
            elif event.type == 'MOUSEMOTION':
                mouse = event.tile
            elif event.type == 'MOUSEBUTTONDOWN':
                mouse = event.tile
                action = handle_mouse(event)
            if action:
                break

        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, constants.fov_radius,
                          constants.fov_light_walls, constants.fov_algorithm)

        target_radius = 0
        if targeting_item and targeting_item.item:
            target_radius = targeting_item.item.function_kwargs.get(
                'radius', 0)

        render_all(
            root_console,
            con,
            panel,
            entities,
            player,
            game_map,
            fov_map,
            fov_recompute,
            message_log,
            constants.screen_width,
            constants.screen_height,
            constants.bar_width,
            constants.panel_height,
            constants.panel_y,
            mouse,
            constants.colors,
            game_state,
            target_radius,
        )

        fov_recompute = False

        tcod.console_flush()

        clear_all(con, entities)

        move = action.get('move')
        wait = action.get('wait')
        pickup = action.get('pickup')
        show_inventory = action.get('show_inventory')
        drop_inventory = action.get('drop_inventory')
        inventory_index = action.get('inventory_index')
        show_character_screen = action.get('show_character_screen')
        take_stairs = action.get('take_stairs')
        level_up = action.get('level_up')
        exit = action.get('exit')
        fullscreen = action.get('fullscreen')

        left_click = action.get('left_click')
        right_click = action.get('right_click')

        player_turn_results: ActionResults = []

        if move and game_state == GameStates.PLAYERS_TURN:
            dx, dy = move
            new_x = player.x + dx
            new_y = player.y + dy
            if not game_map.is_blocked(new_x, new_y):
                target = get_blocking_entities_at_location(
                    entities, new_x, new_y)
                if target:
                    player_turn_results.extend(player.fighter.attack(target))
                else:
                    player.move(dx, dy)
                    fov_recompute = True

                game_state = GameStates.ENEMY_TURN

        if wait and game_state == GameStates.PLAYERS_TURN:
            game_state = GameStates.ENEMY_TURN

        if pickup and game_state == GameStates.PLAYERS_TURN:
            for entity in entities:
                if (entity.x == player.x and entity.y == player.y
                        and entity.item):
                    player_turn_results.extend(
                        player.inventory.add_item(entity))
                    break
            else:
                message_log.add_message(
                    Message('There is nothing here to pick up.', tcod.yellow))

        if show_inventory:
            previous_game_state = game_state
            game_state = GameStates.SHOW_INVENTORY

        if drop_inventory:
            previous_game_state = game_state
            game_state = GameStates.DROP_INVENTORY

        if (inventory_index is not None
                and previous_game_state != GameStates.PLAYER_DEAD
                and inventory_index < len(player.inventory.items)):
            item = player.inventory.items[inventory_index]
            if game_state == GameStates.SHOW_INVENTORY:
                player_turn_results.extend(
                    player.inventory.use(item,
                                         entities=entities,
                                         fov_map=fov_map))
            elif game_state == GameStates.DROP_INVENTORY:
                player_turn_results.extend(player.inventory.drop_item(item))

        if take_stairs and game_state == GameStates.PLAYERS_TURN:
            for entity in entities:
                if (entity.stairs and entity.x == player.x
                        and entity.y == player.y):
                    save_game(player, entities, game_map, message_log,
                              game_state)
                    entities = game_map.next_floor(player, message_log,
                                                   constants)
                    fov_map = initialize_fov(game_map)
                    fov_recompute = True
                    con.clear()
                    break
            else:
                message_log.add_message(
                    Message('There are no stairs here.', tcod.yellow))

        if level_up:
            if level_up == 'hp':
                player.fighter.base_max_hp += 20
                player.fighter.hp += 20
            elif level_up == 'str':
                player.fighter.base_power += 1
            elif level_up == 'def':
                player.fighter.base_defense += 1
            game_state = previous_game_state

        if show_character_screen:
            previous_game_state = game_state
            game_state = GameStates.CHARACTER_SCREEN

        if game_state == GameStates.TARGETING:
            if left_click:
                target_x, target_y = left_click
                player_turn_results.extend(
                    player.inventory.use(targeting_item,
                                         entities=entities,
                                         fov_map=fov_map,
                                         target_x=target_x,
                                         target_y=target_y))
            elif right_click:
                player_turn_results.append({
                    'targeting_cancelled': True,
                })

        if exit:
            if game_state in (GameStates.SHOW_INVENTORY,
                              GameStates.DROP_INVENTORY,
                              GameStates.CHARACTER_SCREEN):
                game_state = previous_game_state
            elif game_state == GameStates.TARGETING:
                player_turn_results.append({
                    'targeting_cancelled': True,
                })
            else:
                save_game(player, entities, game_map, message_log, game_state)
                return

        if fullscreen:
            tcod.console_set_fullscreen(not tcod.console_is_fullscreen())

        for player_turn_result in player_turn_results:
            message = player_turn_result.get('message')
            dead_entity = player_turn_result.get('dead')
            item_added: Optional[Entity] = player_turn_result.get('item_added')
            item_consumed = player_turn_result.get('consumed')
            item_dropped = player_turn_result.get('item_dropped')
            equip = player_turn_result.get('equip')
            targeting = player_turn_result.get('targeting')
            targeting_cancelled = player_turn_result.get('targeting_cancelled')
            xp = player_turn_result.get('xp')

            if message:
                message_log.add_message(message)

            if dead_entity:
                if dead_entity == player:
                    message, game_state = kill_player(dead_entity)
                else:
                    message = kill_monster(dead_entity)

                message_log.add_message(message)

            if item_added:
                entities.remove(item_added)
                game_state = GameStates.ENEMY_TURN

            if item_consumed:
                game_state = GameStates.ENEMY_TURN

            if targeting:
                previous_game_state = GameStates.PLAYERS_TURN
                game_state = GameStates.TARGETING
                targeting_item = targeting
                message_log.add_message(targeting_item.item.targeting_message)

            if targeting_cancelled:
                game_state = previous_game_state
                message_log.add_message(Message('Targeting cancelled'))

            if item_dropped:
                entities.append(item_dropped)
                game_state = GameStates.ENEMY_TURN

            if equip:
                equip_results = player.equipment.toggle_equip(equip)
                for equip_result in equip_results:
                    equipped = equip_result.get('equipped')
                    dequipped = equip_result.get('dequipped')
                    if equipped:
                        message_log.add_message(
                            Message(f"You equipped the {equipped.name}."))
                    if dequipped:
                        message_log.add_message(
                            Message(f"You removed the {dequipped.name}."))
                game_state = GameStates.ENEMY_TURN

            if xp:
                leveled_up = player.level.add_xp(xp)
                message_log.add_message(
                    Message(f'You gain {xp} experience points.'))
                if leveled_up:
                    message_log.add_message(
                        Message(
                            f'Your battle skills grow stronger!'
                            f' You reached level {player.level.current_level}!',
                            tcod.yellow))
                    previous_game_state = game_state
                    game_state = GameStates.LEVEL_UP

        if game_state == GameStates.ENEMY_TURN:
            for entity in entities:
                if entity.ai:
                    enemy_turn_results = entity.ai.take_turn(
                        player, fov_map, game_map, entities)

                    for enemy_turn_result in enemy_turn_results:
                        message = enemy_turn_result.get('message')
                        dead_entity = enemy_turn_result.get('dead')

                        if message:
                            message_log.add_message(message)

                        if dead_entity:
                            if dead_entity == player:
                                message, game_state = kill_player(dead_entity)
                            else:
                                message = kill_monster(dead_entity)

                            message_log.add_message(message)

                            if game_state == GameStates.PLAYER_DEAD:
                                break

                    if game_state == GameStates.PLAYER_DEAD:
                        break
            else:
                game_state = GameStates.PLAYERS_TURN
예제 #16
0
def Rogue(screen):
    max_y, max_x = screen.getmaxyx()

    # These actually define the height of the canvas (game map) not the host terminal
    screen_width = 80
    screen_height = 30
    cy = int((max_y - screen_height) / 2)
    cx = int((max_x - screen_width) / 2)
    #height, width = canvas.getmaxyx()
    map_height = 23
    map_width = 78

    # Values to define status bars and message log
    bar_width = 30
    panel_height = 6
    panel_y = cy + screen_height - panel_height + 1

    # message_x = bar_width + 2
    message_x = 1
    message_width = screen_width - 2
    message_height = cy


    canvas = curses.newwin(screen_height, screen_width, cy, cx)
    renderer = CursesRenderer(canvas)

    #status_win = curses.newwin(80, 3, 24, 0)
    panel = curses.newwin(panel_height, screen_width, panel_y, cx)
    message_panel = curses.newwin(cy, screen_width, 0, cx)

    colors = {
        'dark_wall': curses.color_pair(236)
    }

    fov = FOV(5)
    fighter = Fighter(hp=30, defense=2, power=5)
    player = Entity(5, 5, '@', curses.color_pair(6),
                    'Player', blocks=True, render_order=RenderOrder.ACTOR, fov=fov, fighter=fighter)
    entities = [player]

    game_map = GameMap(map_width, map_height-1)
    game_map.make_map(15, 8, 10, map_width, map_height, player, entities, 3)

    calculate_fov = True

    message_log = MessageLog(message_x, message_width, message_height)
    game_state = GameStates.PLAYER_TURN
    while True:
        key = canvas.getch()
        curses.flushinp()

        renderer.render_all(canvas, panel, message_panel,
                            bar_width, message_log,
                            game_map, fov, calculate_fov,
                            entities, player, colors)

        panel.refresh()
        message_panel.refresh()

        canvas.border()
        canvas.refresh()

        action = handle_keys(key)
        move = action.get('move')
        exit = action.get('exit')

        player_turn_results = []

        if exit:
            return True

        if move and game_state == GameStates.PLAYER_TURN:
            dx, dy = move
            destination_x = player.x + dx
            destination_y = player.y + dy

            if not game_map.is_blocked(player.x + dx, player.y + dy):
                if not game_map.is_blocked(destination_x, destination_y):
                    target = get_blocking_entities_at_location(entities, destination_x, destination_y)

                    if target:
                        attack_results = player.fighter.attack(target)
                        player_turn_results.extend(attack_results)
                    else:
                        player.move(dx, dy)
                        calculate_fov = True

                    game_state = GameStates.ENEMY_TURN

        for result in player_turn_results:
            message = result.get('message')
            dead_entity = result.get('dead')

            if message:
                message_log.add_message(message)

            if dead_entity:
                if dead_entity == player:
                    message, game_state = kill_player(dead_entity)
                else:
                    message = kill_monster(dead_entity)

                message_log.add_message(message)

        if game_state == GameStates.ENEMY_TURN:
            for entity in entities:
                if entity.ai:
                    enemy_turn_results = entity.ai.take_turn(player, fov, game_map, entities)

                    for result in enemy_turn_results:
                        message = result.get('message')
                        dead_entity = result.get('dead')

                        if message:
                            message_log.add_message(message)

                        if dead_entity:
                            if dead_entity == player:
                                message, game_state = kill_player(dead_entity)
                            else:
                                message = kill_monster(dead_entity)

                            if game_state == GameStates.PLAYER_DEAD:
                                break

                    if game_state == GameStates.PLAYER_DEAD:
                        break
            else:
                game_state = GameStates.PLAYER_TURN
예제 #17
0
파일: engine.py 프로젝트: QuinceP/sprl
def play_game():
    screen_width = 70
    screen_height = 45

    bar_width = 20

    panel_horiz_height = 10
    panel_horiz_y = screen_height - panel_horiz_height
    panel_horiz = libtcod.console_new(screen_width, panel_horiz_height)

    panel_vert_height = panel_horiz_y
    panel_vert_y = 0
    panel_vert = libtcod.console_new(48, panel_vert_height)

    message_x = 1
    message_width = screen_width - 1
    message_height = panel_horiz_height - 2

    map_width = 47
    map_height = panel_horiz_y

    room_max_size = 8
    room_min_size = 3
    max_rooms = 30

    fov_algorithm = 0
    fov_light_walls = True
    fov_radius = 10

    max_monsters_per_room = 3
    max_items_per_room = 2

    colors = {
        'dark_wall': libtcod.Color(0, 0, 100),
        'dark_ground': libtcod.Color(50, 50, 150),
        'light_wall': libtcod.Color(130, 110, 50),
        'light_ground': libtcod.Color(200, 180, 50)
    }

    fighter_component = Fighter(hp=100, defense=1, power=2)
    inventory_component = Inventory(26)
    level_component = Level()
    equipment_component = Equipment()

    player = Entity(0, 0, '@', libtcod.white, 'Player', blocks=True, render_order=RenderOrder.ACTOR,
                    fighter=fighter_component, inventory=inventory_component, level=level_component,
                    equipment=equipment_component)

    entities = [player]

    equippable_component = Equippable(EquipmentSlots.MAIN_HAND, power_bonus=2)
    dagger = Entity(0, 0, '-', libtcod.sky, 'Dagger', equippable=equippable_component)
    player.inventory.add_item(dagger)
    player.equipment.toggle_equip(dagger)

    libtcod.console_set_custom_font(consts.FONT, libtcod.FONT_LAYOUT_ASCII_INROW)

    libtcod.console_init_root(screen_width, screen_height, 'libtcod tutorial revised', False)

    con = libtcod.console_new(screen_width, screen_height)

    game_map = GameMap(map_width, map_height)
    game_map.make_map(max_rooms, room_min_size, room_max_size, map_width, map_height, player, entities)

    fov_recompute = True

    fov_map = initialize_fov(game_map)

    message_log = MessageLog(message_x, message_width, message_height)

    key = libtcod.Key()
    mouse = libtcod.Mouse()

    game_state = GameStates.PLAYERS_TURN
    previous_game_state = game_state

    targeting_item = None

    while not libtcod.console_is_window_closed():
        libtcod.sys_check_for_event(libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, key, mouse)

        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, fov_radius, fov_light_walls, fov_algorithm)

        render_all(con, panel_vert, panel_horiz, entities, player, game_map, fov_map, fov_recompute, message_log,
                   screen_width, screen_height,
                   bar_width, panel_horiz_height, panel_horiz_y, panel_vert_height, panel_vert_y, mouse, colors,
                   game_state)

        fov_recompute = False

        libtcod.console_flush()

        clear_all(con, entities)

        action = handle_keys(key, game_state)
        mouse_action = handle_mouse(mouse)

        move = action.get('move')
        exit = action.get('exit')
        pickup = action.get('pickup')
        fullscreen = action.get('fullscreen')
        show_inventory = action.get('show_inventory')
        inventory_index = action.get('inventory_index')
        drop_inventory = action.get('drop_inventory')
        take_stairs = action.get('take_stairs')
        level_up = action.get('level_up')
        show_character_screen = action.get('show_character_screen')
        wait = action.get('wait')

        left_click = mouse_action.get('left_click')
        right_click = mouse_action.get('right_click')

        player_turn_results = []

        if move and game_state == GameStates.PLAYERS_TURN:
            dx, dy = move
            destination_x = player.x + dx
            destination_y = player.y + dy

            if not game_map.is_blocked(player.x + dx, player.y + dy):
                if not game_map.is_blocked(destination_x, destination_y):
                    target = get_blocking_entities_at_location(entities, destination_x, destination_y)

                    if target:
                        attack_results = player.fighter.attack(target)
                        player_turn_results.extend(attack_results)
                    else:
                        player.move(dx, dy)

                        fov_recompute = True
                    game_state = GameStates.ENEMY_TURN

        elif wait:
            message_log.add_message(Message('You wait for a moment.', libtcod.yellow))
            game_state = GameStates.ENEMY_TURN

        elif pickup and game_state == GameStates.PLAYERS_TURN:
            for entity in entities:
                if entity.item and entity.x == player.x and entity.y == player.y:
                    pickup_results = player.inventory.add_item(entity)
                    player_turn_results.extend(pickup_results)

                    break
            else:
                message_log.add_message(Message('There is nothing here to pick up.', libtcod.yellow))

        if show_inventory:
            previous_game_state = game_state
            game_state = GameStates.SHOW_INVENTORY

        if drop_inventory:
            previous_game_state = game_state
            game_state = GameStates.DROP_INVENTORY

        if inventory_index is not None and previous_game_state != GameStates.PLAYER_DEAD and inventory_index < len(
                player.inventory.items):
            item = player.inventory.items[inventory_index]
            if game_state == GameStates.SHOW_INVENTORY:
                player_turn_results.extend(player.inventory.use(item, entities=entities, fov_map=fov_map))
            elif game_state == GameStates.DROP_INVENTORY:
                player_turn_results.extend(player.inventory.drop_item(item))

        if take_stairs and game_state == GameStates.PLAYERS_TURN:
            for entity in entities:
                if entity.stairs and entity.x == player.x and entity.y == player.y:
                    entities = game_map.next_floor(player, message_log, max_rooms, room_min_size, room_max_size,
                                                   map_width, map_height)
                    fov_map = initialize_fov(game_map)
                    fov_recompute = True
                    libtcod.console_clear(con)

                    break
            else:
                message_log.add_message(Message('There are no stairs here.', libtcod.yellow))

        if level_up:
            if level_up == 'hp':
                player.fighter.base_max_hp += 20
                player.fighter.hp += 20
            elif level_up == 'str':
                player.fighter.base_power += 1
            elif level_up == 'def':
                player.fighter.base_defense += 1

            game_state = previous_game_state

        if show_character_screen:
            previous_game_state = game_state
            game_state = GameStates.CHARACTER_SCREEN

        if game_state == GameStates.TARGETING:
            if left_click:
                target_x, target_y = left_click

                item_use_results = player.inventory.use(targeting_item, entities=entities, fov_map=fov_map,
                                                        target_x=target_x, target_y=target_y)
                player_turn_results.extend(item_use_results)
            elif right_click:
                player_turn_results.append({'targeting_cancelled': True})

        if exit:
            if game_state in (GameStates.SHOW_INVENTORY, GameStates.DROP_INVENTORY, GameStates.CHARACTER_SCREEN):
                game_state = previous_game_state
            elif game_state == GameStates.TARGETING:
                player_turn_results.append({'targeting_cancelled': True})
            else:
                return True

        if fullscreen:
            libtcod.console_set_fullscreen(not libtcod.console_is_fullscreen())

        for player_turn_result in player_turn_results:
            message = player_turn_result.get('message')
            dead_entity = player_turn_result.get('dead')
            item_added = player_turn_result.get('item_added')
            item_consumed = player_turn_result.get('consumed')
            item_dropped = player_turn_result.get('item_dropped')
            targeting = player_turn_result.get('targeting')
            targeting_cancelled = player_turn_result.get('targeting_cancelled')
            xp = player_turn_result.get('xp')
            equip = player_turn_result.get('equip')

            if message:
                message_log.add_message(message)

            if dead_entity:
                if dead_entity == player:
                    message, game_state = kill_player(dead_entity)
                else:
                    message = kill_monster(dead_entity)

                message_log.add_message(message)

            if item_added:
                entities.remove(item_added)

                game_state = GameStates.ENEMY_TURN

            if item_consumed:
                game_state = GameStates.ENEMY_TURN

            if targeting:
                previous_game_state = GameStates.PLAYERS_TURN
                game_state = GameStates.TARGETING

                targeting_item = targeting

                message_log.add_message(targeting_item.item.targeting_message)

            if targeting_cancelled:
                game_state = previous_game_state

                message_log.add_message(Message('Targeting cancelled'))

            if xp:
                leveled_up = player.level.add_xp(xp)
                message_log.add_message(Message('You gain {0} experience points.'.format(xp)))

                if leveled_up:
                    message_log.add_message(Message(
                        'Your battle skills grow stronger! You reached level {0}'.format(
                            player.level.current_level) + '!', libtcod.yellow))
                    previous_game_state = game_state
                    game_state = GameStates.LEVEL_UP

            if item_dropped:
                entities.append(item_dropped)

                game_state = GameStates.ENEMY_TURN

            if equip:
                equip_results = player.equipment.toggle_equip(equip)

                for equip_result in equip_results:
                    equipped = equip_result.get('equipped')
                    dequipped = equip_result.get('dequipped')

                    if equipped:
                        message_log.add_message(Message('You equipped the {0}'.format(equipped.name)))

                    if dequipped:
                        message_log.add_message(Message('You dequipped the {0}'.format(dequipped.name)))

                game_state = GameStates.ENEMY_TURN

        if game_state == GameStates.ENEMY_TURN:
            for entity in entities:
                if entity.ai:
                    enemy_turn_results = entity.ai.take_turn(player, fov_map, game_map, entities)

                    for enemy_turn_result in enemy_turn_results:
                        message = enemy_turn_result.get('message')
                        dead_entity = enemy_turn_result.get('dead')

                        if message:
                            message_log.add_message(message)

                        if dead_entity:
                            if dead_entity == player:
                                message, game_state = kill_player(dead_entity)
                            else:
                                message = kill_monster(dead_entity)

                            message_log.add_message(message)

                            if game_state == GameStates.PLAYER_DEAD:
                                break

                    if game_state == GameStates.PLAYER_DEAD:
                        break
            else:
                game_state = GameStates.PLAYERS_TURN
예제 #18
0
class Rogue(tcod.event.EventDispatch):
    def __init__(self):
        self.recompute = True
        self.game_map = None
        self.map_console = tcod.console.Console(CONFIG.get('map_width'),
                                                CONFIG.get('map_height'), 'F')
        self.info_console = tcod.console.Console(
            CONFIG.get('map_width'), CONFIG.get('info_panel_height'), 'F')
        self.message_console = tcod.console.Console(
            CONFIG.get('map_width'), CONFIG.get('message_panel_height'), 'F')
        self.menu_console = tcod.console.Console(CONFIG.get('map_width'),
                                                 CONFIG.get('map_height'), 'F')
        self.game_state = GameStates.PLAYER_TURN
        self.previous_game_state = None
        self.message_log = None
        self.motion = tcod.event.MouseMotion()
        self.lbut = self.mbut = self.rbut = 0
        self.quest_request = None
        self.using_item = None
        self.last_debug_entity = None

    def start_fresh_game(self):
        logging.basicConfig(
            filename=
            f'{resource_path("log")}/{datetime.datetime.now().strftime("%Y%m%d%H%M%S")}.log',
            filemode='w',
            format='%(asctime)s - %(message)s',
            datefmt='%d-%b-%y %H:%M:%S',
            level=CONFIG.get('logging_level'))

        pubsub.pubsub = pubsub.PubSub()

        self.message_log = MessageLog(CONFIG.get('message_width'),
                                      CONFIG.get('message_height'))
        pubsub.pubsub.subscribe(
            pubsub.Subscription(self.message_log, pubsub.PubSubTypes.MESSAGE,
                                pubsub.add_to_messages))

        self.player = create_player()

        self.game_map = GameMap()
        self.game_map.create_floor(self.player)

        self.start_game()

    def start_game(self):
        self.update_fov()

        quest.active_quests = []

        self.game_state = GameStates.PLAYER_TURN
        self.previous_game_state = None

        self.message_log.add_message(
            Message('Let\'s get ready to rock and/or roll!', tcod.yellow))

    def on_enter(self):
        tcod.sys_set_fps(60)

    def update_fov(self):
        self.game_map.current_level.compute_fov(
            self.player.x,
            self.player.y,
            algorithm=self.player.fov.fov_algorithm,
            radius=self.player.fov.fov_radius,
            light_walls=self.player.fov.fov_light_walls)

        if self.player.sleep:
            self.game_map.current_level.npc_fov = tcod.map.compute_fov(
                self.game_map.current_level.transparent,
                pov=(self.player.x, self.player.y),
                algorithm=tcod.FOV_RESTRICTIVE,
                light_walls=True,
                radius=10)

        else:
            self.game_map.current_level.npc_fov = self.game_map.current_level.fov

        if not CONFIG.get('debug'):
            where_fov = np.where(self.game_map.current_level.fov[:])
            self.game_map.current_level.explored[where_fov] = True
        else:
            self.game_map.current_level.fov[:] = True
            self.game_map.current_level.explored[:] = True

    def on_draw(self):
        #---------------------------------------------------------------------
        # Recompute the player's field of view.
        #---------------------------------------------------------------------
        self.update_fov()

        #---------------------------------------------------------------------
        # Render and display the dungeon and its inhabitates.
        #---------------------------------------------------------------------
        self.game_map.current_level.render(self.map_console)

        if not CONFIG.get('debug'):
            self.game_map.current_level.render_torch(
                self.player.x, self.player.y, self.player.fov.fov_radius,
                self.map_console)

        if CONFIG.get('debug') and self.game_map.current_level.within_bounds(
                self.motion.tile.x, self.motion.tile.y):
            for entity in self.game_map.current_level.entities.get_entities_in_position(
                (self.motion.tile.x, self.motion.tile.y)):
                if entity.movement:
                    dijkstra = calculate_dijkstra(self.game_map,
                                                  [(entity.x, entity.y)],
                                                  avoid_entity=self.player)
                    self.game_map.current_level.render_dijkstra(
                        dijkstra, self.map_console)

                    if entity.ai:
                        path = entity.ai.tree.namespace.get("path")
                        target = entity.ai.tree.namespace.get("target")
                        if path or target:
                            self.game_map.current_level.render_entity_detail(
                                path, target, self.map_console)
                    if not (entity == self.last_debug_entity):
                        entity.debug()
                        self.last_debug_entity = entity

        #---------------------------------------------------------------------
        # Render infomation panels.
        #---------------------------------------------------------------------
        render_info_console(self.info_console, self.player, self.game_map)
        render_message_console(self.message_console, self.message_log)

        #---------------------------------------------------------------------
        # Blit the subconsoles to the main console and flush all rendering.
        #---------------------------------------------------------------------
        root_console.clear(fg=COLORS.get('console_background'))

        self.map_console.blit(root_console, 0, 0, 0, 0, self.map_console.width,
                              self.map_console.height)

        under_mouse_text = get_names_under_mouse(self.motion.tile.x,
                                                 self.motion.tile.y,
                                                 self.game_map.current_level)
        text_height = root_console.get_height_rect(1, 0,
                                                   root_console.width - 2, 10,
                                                   under_mouse_text)

        root_console.print_box(
            1,
            CONFIG.get('info_panel_y') - text_height - 1,
            root_console.width - 2,
            text_height,
            under_mouse_text,
            fg=tcod.white,
            bg=None,
            alignment=tcod.LEFT,
        )

        self.info_console.blit(root_console, 0, CONFIG.get('info_panel_y'), 0,
                               0, CONFIG.get('full_screen_width'),
                               CONFIG.get('info_panel_height'))
        self.message_console.blit(root_console, 0,
                                  CONFIG.get('message_panel_y'), 0, 0,
                                  CONFIG.get('full_screen_width'),
                                  CONFIG.get('message_panel_height'))

        if self.game_state in MENU_STATES:
            #---------------------------------------------------------------------
            # Render any menus.
            #---------------------------------------------------------------------
            exclude = []
            if self.using_item:
                exclude.append(self.using_item)

            self.menu_console = render_menu_console(self.game_state,
                                                    self.player,
                                                    self.quest_request,
                                                    exclude)

            self.menu_console.blit(root_console, 0, 0, 0, 0,
                                   CONFIG.get('full_screen_width'),
                                   CONFIG.get('full_screen_height'))

    def ev_keydown(self, event: tcod.event.KeyDown):
        #---------------------------------------------------------------------
        # Get key input from the self.player.
        #---------------------------------------------------------------------
        input_result = handle_keys(event, self.game_state)

        if (len(input_result) == 0):
            if CONFIG.get('debug'):
                #logging.info("No corresponding result for key press.")
                pass
            return

        action, action_value = unpack_single_key_dict(input_result)
        self.process_turn(action, action_value)

    def ev_mousemotion(self, event: tcod.event.MouseMotion):
        self.motion = event

    def ev_mousebuttondown(self, event: tcod.event.MouseButtonDown):
        input_type = None
        if event.button == tcod.event.BUTTON_LEFT:
            self.lbut = True
            input_type = InputTypes.TARGETING
        elif event.button == tcod.event.BUTTON_MIDDLE:
            self.mbut = True
        elif event.button == tcod.event.BUTTON_RIGHT:
            self.rbut = True
            input_type = InputTypes.EXIT

        self.process_turn(input_type, (event.tile.x, event.tile.y))

    def ev_mousebuttonup(self, event: tcod.event.MouseButtonUp):
        if event.button == tcod.event.BUTTON_LEFT:
            self.lbut = False
        elif event.button == tcod.event.BUTTON_MIDDLE:
            self.mbut = False
        elif event.button == tcod.event.BUTTON_RIGHT:
            self.rbut = False

    def ev_quit(self, event: tcod.event.Quit):
        raise SystemExit()

    def game_actions(self, action, action_value):
        if action == InputTypes.GAME_EXIT:
            self.game_state = GameStates.GAME_EXIT
            return True

        if action == InputTypes.GAME_SAVE:
            #FIXME: Saves don't work
            #save_game(self.player, self.game_map, message_log, self.game_state, pubsub.pubsub)
            return True

        if action == InputTypes.GAME_RESTART:
            self.start_fresh_game()
            return True

        if action == InputTypes.GAME_RESET:
            self.game_map.first_floor(self.player)
            self.start_game()
            return True

        if action == InputTypes.RELOAD_LEVEL:
            self.game_map.next_floor(self.player)
            self.update_fov()
            return True

        return False

    def change_state_action(self, action, action_value):
        if action == InputTypes.CHARACTER_SCREEN:
            self.previous_game_state = self.game_state
            self.game_state = GameStates.CHARACTER_SCREEN
            return True

        if action == InputTypes.INVENTORY_DROP:
            self.previous_game_state = self.game_state
            self.game_state = GameStates.INVENTORY_DROP
            return True

        if action == InputTypes.INVENTORY_EXAMINE:
            self.previous_game_state = self.game_state
            self.game_state = GameStates.INVENTORY_EXAMINE
            return True

        if action == InputTypes.INVENTORY_THROW:
            self.previous_game_state = self.game_state
            self.game_state = GameStates.INVENTORY_THROW
            return True

        if action == InputTypes.INVENTORY_USE:
            self.previous_game_state = self.game_state
            self.game_state = GameStates.INVENTORY_USE
            return True

        if action == InputTypes.LEVEL_UP:
            self.player.level.level_up_stats(action_value)
            self.game_state = self.previous_game_state

        #This needs to come after leveling up or we get stuck in a loop
        if not (self.game_state
                in MENU_STATES) and self.player.level.can_level_up():
            self.previous_game_state = self.game_state
            self.game_state = GameStates.LEVEL_UP
            return True

        if action == InputTypes.QUEST_LIST:
            self.previous_game_state = self.game_state
            self.game_state = GameStates.QUEST_LIST
            return True

        return False

    def debug_actions(self, action, action_value):
        if action == InputTypes.DEBUG_ON:
            CONFIG.update({'debug': True})
            self.update_fov()

        if action == InputTypes.DEBUG_OFF:
            CONFIG.update({'debug': False})
            self.update_fov()

    def menu_actions(self, action, action_value):
        pass

    def quest_actions(self, action, action_value):
        if action == InputTypes.QUEST_RESPONSE:
            if action_value:
                self.quest_request.owner.start_quest(self.game_map)
                self.message_log.add_message(
                    Message(f"Started quest: {self.quest_request.title}",
                            tcod.yellow))
            self.quest_request = None
            self.game_state = self.previous_game_state

        if (action == InputTypes.QUEST_INDEX
                and self.previous_game_state != GameStates.GAME_OVER
                and action_value < len(quest.active_quests)):
            self.message_log.add_message(
                quest.active_quests[action_value].status())
            self.game_state = self.previous_game_state

    def player_actions(self, action, action_value):
        self.player.energy.take_action()

        player_turn_results = []

        player_on_turn_results = self.player.on_turn(self.game_map)
        self.process_results_stack(self.player, player_on_turn_results)

        if action == InputTypes.SLEEP:
            if not self.player.sleep:
                self.player.add_component(Sleep(), 'sleep')
                self.player.sleep.start()
                self.update_fov()
                pubsub.pubsub.add_message(
                    pubsub.Publish(None,
                                   pubsub.PubSubTypes.MESSAGE,
                                   message=Message('You have gone asleep.',
                                                   COLORS.get('effect_text'))))

        if self.player.health.dead:
            self.game_state = GameStates.GAME_OVER
        elif self.player.sleep:
            finished = self.player.sleep.on_turn(self.game_map)
            if finished:
                pubsub.pubsub.add_message(
                    pubsub.Publish(None,
                                   pubsub.PubSubTypes.MESSAGE,
                                   message=Message('You have woken up.',
                                                   COLORS.get('effect_text'))))
                self.update_fov()

            self.game_state = GameStates.ENEMY_TURN
        elif action == InputTypes.WAIT:
            self.game_state = GameStates.ENEMY_TURN
        elif action == InputTypes.MOVE:
            dx, dy = action_value

            if self.game_map.current_level.accessible_tile(
                    self.player.x + dx, self.player.y + dy):
                if self.game_map.current_level.blocked[self.player.x + dx,
                                                       self.player.y + dy]:
                    targets = self.game_map.current_level.entities.get_entities_in_position(
                        (self.player.x + dx, self.player.y + dy))

                    targets_in_render_order = sorted(
                        targets,
                        key=lambda x: x.render_order.value,
                        reverse=True)
                    target = targets_in_render_order[0]

                    if target.interaction.interaction_type == Interactions.QUESTGIVER:
                        quest_results = target.questgiver.talk(self.player)
                        player_turn_results.extend(quest_results)
                    elif target.interaction.interaction_type == Interactions.DOOR:
                        if target.locked:
                            can_unlock = False

                            if target.locked.requires_key:
                                all_keys = self.player.inventory.search(
                                    name='key')
                                for key_to_check in all_keys:
                                    if key_to_check.unlock.unlocks == target.uuid:
                                        can_unlock = True
                                        player_turn_results.extend([{
                                            ResultTypes.DISCARD_ITEM:
                                            key_to_check
                                        }])
                                        break
                            else:
                                can_unlock = True

                            if can_unlock:
                                target.locked.toggle()
                                self.game_map.current_level.update_entity_position(
                                    target)
                                self.update_fov()

                                message = Message(
                                    f"You have unlocked the {target.name}.",
                                    tcod.yellow)
                                player_turn_results.extend([{
                                    ResultTypes.MESSAGE:
                                    message
                                }])
                            else:
                                message = Message(
                                    f"The {target.name} is locked.",
                                    tcod.yellow)
                                player_turn_results.extend([{
                                    ResultTypes.MESSAGE:
                                    message
                                }])
                    elif target.interaction.interaction_type == Interactions.FOE:
                        if target.health and not target.health.dead:
                            attack_results = self.player.offence.attack(
                                target, self.game_map)
                            player_turn_results.extend(attack_results)
                else:
                    self.player.movement.move(dx, dy,
                                              self.game_map.current_level)
                    player_turn_results.extend(
                        quest.check_quest_for_location(self.player))

                    self.update_fov()

                self.game_state = GameStates.ENEMY_TURN
        elif action == InputTypes.PICKUP:
            entities = self.game_map.current_level.entities.get_entities_in_position(
                (self.player.x, self.player.y))
            pickup = False
            for entity in entities:
                if entity.item:
                    if entity.identifiable and identified_items.get(
                            entity.base_name):
                        entity.identifiable.identified = True
                    player_turn_results.extend([{
                        ResultTypes.ADD_ITEM_TO_INVENTORY:
                        entity
                    }])
                    pickup = True
            if not pickup:
                message = Message('There is nothing here to pick up.',
                                  tcod.yellow)
                player_turn_results.extend([{ResultTypes.MESSAGE: message}])
        elif action == InputTypes.DOWN_LEVEL:
            self.game_map.next_floor(self.player)
            self.update_fov()
            message = Message(
                'You take a moment to rest and recover your strength.',
                tcod.light_violet)
            player_turn_results.extend([{ResultTypes.MESSAGE: message}])

            #continue
            return
        elif action == InputTypes.TAKE_STAIRS:
            stair_state = self.game_map.check_for_stairs(
                self.player.x, self.player.y)
            if stair_state == StairOption.GODOWN:
                self.game_map.next_floor(self.player)
                self.update_fov()
                message = Message(
                    'You take a moment to rest and recover your strength.',
                    tcod.light_violet)
                player_turn_results.extend([{ResultTypes.MESSAGE: message}])

                #continue
                return
            elif stair_state == StairOption.GOUP:
                self.game_map.previous_floor(self.player)
                self.update_fov()

                return
            elif stair_state == StairOption.EXIT:
                self.game_state = GameStates.GAME_PAUSED
            else:
                message = Message('There are no stairs here.', tcod.yellow)
                player_turn_results.extend([{ResultTypes.MESSAGE: message}])

        self.process_results_stack(self.player, player_turn_results)

        pubsub.pubsub.process_queue(self.game_map)

    def npc_actions(self):
        self.game_map.current_level.clear_paths()
        for entity in self.game_map.current_level.entities:
            if entity == self.player:
                continue
            entity.energy.increase_energy()
            if entity.energy.take_action():
                if entity.level and entity.level.can_level_up():
                    entity.level.random_level_up(1)
                enemy_turn_results = entity.on_turn(self.game_map)
                self.process_results_stack(entity, enemy_turn_results)
                enemy_turn_results.clear()

                if entity.health and entity.health.dead:
                    entity.death.decompose(self.game_map)
                elif entity.ai:
                    # Enemies move and attack if possible.
                    enemy_turn_results.extend(
                        entity.ai.take_turn(self.game_map))

                    self.process_results_stack(entity, enemy_turn_results)
                    enemy_turn_results.clear()

                pubsub.pubsub.process_queue(self.game_map)

    def process_turn(self, action, action_value):
        player_turn_results = []

        if self.game_actions(action, action_value):
            return

        if self.change_state_action(action, action_value):
            return

        self.debug_actions(action, action_value)

        self.quest_actions(action, action_value)

        if action == InputTypes.EXIT:
            if self.game_state in CANCEL_STATES:
                self.game_state = self.previous_game_state
                self.using_item = None
                if self.game_state == GameStates.QUEST_ONBOARDING:
                    player_turn_results.append(
                        {ResultTypes.QUEST_CANCELLED: True})
            else:
                self.previous_game_state = self.game_state
                self.game_state = GameStates.GAME_PAUSED
                return

        if (action == InputTypes.TARGETING
                and self.game_state == GameStates.TARGETING):
            target_x, target_y = action_value

            player_turn_results.extend(
                self.using_item.usable.use(game_map=self.game_map,
                                           user=self.player,
                                           target_x=target_x,
                                           target_y=target_y))

        if (action == InputTypes.INVENTORY_INDEX
                and self.previous_game_state != GameStates.GAME_OVER
                and action_value < len(self.player.inventory.items)):

            items = self.player.inventory.items.copy()

            if self.using_item:
                items.remove(self.using_item)

            item = items[action_value]

            if self.game_state == GameStates.INVENTORY_USE:
                if item.usable:
                    self.using_item = item
                    player_turn_results.extend(
                        item.usable.use(self.game_map, self.player))
                else:
                    player_turn_results.extend([{ResultTypes.EQUIP: item}])

            elif self.game_state == GameStates.INVENTORY_SELECT:
                player_turn_results.extend(
                    self.using_item.usable.use(self.game_map, self.player,
                                               item))
                self.using_item = None
            elif self.game_state == GameStates.INVENTORY_DROP:
                player_turn_results.extend(
                    self.player.inventory.drop_item(item))
            elif self.game_state == GameStates.INVENTORY_EXAMINE:
                player_turn_results.extend(
                    self.player.inventory.examine_item(item))

        self.process_results_stack(self.player, player_turn_results)

        pubsub.pubsub.process_queue(self.game_map)

        #-------------------------------------------------------------------
        # Player takes their turn.
        #-------------------------------------------------------------------
        if (self.game_state == GameStates.PLAYER_TURN
                or self.game_state == GameStates.PLAYER_SLEEP):
            self.player_actions(action, action_value)

        if (self.game_state in INPUT_STATES
                or self.game_state == GameStates.GAME_OVER):
            return

        #-------------------------------------------------------------------
        # NPCs take their turns.
        #-------------------------------------------------------------------
        self.npc_actions()

        self.player.energy.increase_energy()
        if self.player.energy.can_act:
            if self.player.sleep:
                self.game_state = GameStates.PLAYER_SLEEP
            else:
                if not self.game_state in INPUT_STATES:
                    self.game_state = GameStates.PLAYER_TURN
        else:
            if not self.game_state in INPUT_STATES:
                self.game_state = GameStates.ENEMY_TURN

        if not self.game_state == GameStates.PLAYER_TURN:
            sleep(CONFIG.get('time_between_enemy_turns'))

        #---------------------------------------------------------------------
        # And done...so broadcast a tick
        #---------------------------------------------------------------------
        pubsub.pubsub.add_message(pubsub.Publish(None,
                                                 pubsub.PubSubTypes.TICK))

        pubsub.pubsub.process_queue(self.game_map)

    def process_results_stack(self, entity, turn_results):
        #----------------------------------------------------------------------
        # Process the results stack
        #......................................................................
        # We are done processing inputs, and may have some results on
        # the entity turn stack. Process the stack by popping off the top
        # result from the queue. There are many different possible results,
        # so each is handled with a dedicated handler.
        #
        # Note: Handling a result may result in other results being added to
        # the stack, so we continually process the results stack until it is
        # empty.
        #----------------------------------------------------------------------
        while turn_results != []:
            # Sort the turn results stack by the priority order.
            turn_results = sorted(
                flatten_list_of_dictionaries(turn_results),
                key=lambda d: get_key_from_single_key_dict(d))

            result = turn_results.pop()
            result_type, result_data = unpack_single_key_dict(result)

            # Handle a simple message.
            if result_type == ResultTypes.MESSAGE:
                message = result_data
                pubsub.pubsub.add_message(
                    pubsub.Publish(None,
                                   pubsub.PubSubTypes.MESSAGE,
                                   message=message))

            if result_type == ResultTypes.FOV_RECOMPUTE:
                self.update_fov()

            if result_type == ResultTypes.END_TURN:
                self.game_state = GameStates.ENEMY_TURN

            if result_type == ResultTypes.EARN_XP:
                if result_data['xp'] > 0:
                    result_data['earner'].level.add_xp(result_data['xp'])
                    message = Message(
                        f"{result_data['earner'].name} gained {result_data['xp']} xp",
                        COLORS.get('success_text'),
                        target=result_data['earner'],
                        type=MessageType.EVENT)
                    turn_results.extend([{ResultTypes.MESSAGE: message}])

            # Handle death.
            if result_type == ResultTypes.DEAD_ENTITY:
                self.game_state = result_data['dead'].death.npc_death(
                    self.game_map)
                if entity == result_data['dead']:
                    turn_results = []
                if result_data['attacker'] and result_data['attacker'].ai:
                    result_data['attacker'].ai.remove_target(
                        target=result_data['dead'])
                result_data['dead'].deregister_turn_all()

            if result_type == ResultTypes.TARGET_ITEM_IN_INVENTORY:
                self.game_state = GameStates.INVENTORY_SELECT

            if result_type == ResultTypes.CANCEL_TARGET_ITEM_IN_INVENTORY:
                self.using_item = None
                self.game_state = GameStates.PLAYER_TURN

            # Add an item to the inventory, and remove it from the game map.
            if result_type == ResultTypes.ADD_ITEM_TO_INVENTORY:
                turn_results.extend(entity.inventory.add_item(result_data))
                self.game_state = GameStates.ENEMY_TURN
            # Remove consumed items from inventory
            if result_type == ResultTypes.DISCARD_ITEM:
                entity.inventory.remove_item(result_data)
                self.game_state = GameStates.ENEMY_TURN
                self.using_item = None

            # Remove dropped items from inventory and place on the map
            if result_type == ResultTypes.DROP_ITEM_FROM_INVENTORY:
                self.game_map.current_level.add_entity(result_data)
                message = Message(
                    f"{entity.name} dropped the {result_data.name}",
                    COLORS.get('success_text'),
                    target=entity,
                    type=MessageType.EVENT)
                turn_results.extend([{ResultTypes.MESSAGE: message}])
                self.game_state = GameStates.ENEMY_TURN

            if result_type == ResultTypes.EQUIP:
                equip_results = entity.equipment.toggle_equip(result_data)

                for equip_result in equip_results:
                    equipped = equip_result.get('equipped')
                    dequipped = equip_result.get('dequipped')

                    if equipped:
                        message = Message(
                            f"{entity.name} equipped the {equipped.name}",
                            target=entity,
                            type=MessageType.EVENT)

                    if dequipped:
                        message = Message(
                            f"{entity.name} dequipped the {dequipped.name}",
                            target=entity,
                            type=MessageType.EVENT)

                    turn_results.extend([{ResultTypes.MESSAGE: message}])

                self.game_state = GameStates.ENEMY_TURN
            if result_type == ResultTypes.QUEST_ONBOARDING:
                self.quest_request = result_data
                self.previous_game_state = self.game_state
                self.game_state = GameStates.QUEST_ONBOARDING

            if result_type == ResultTypes.QUEST_CANCELLED:
                pass

            if result_type == ResultTypes.SET_POSITION:
                npc, point = result_data
                npc.movement.place(point.x, point.y,
                                   self.game_map.current_level)
            # Handle a move towards action.  Move towards a target.
            if result_type == ResultTypes.MOVE_TOWARDS:
                npc, target_x, target_y = result_data
                npc.movement.attempt_move(Point(target_x, target_y),
                                          self.game_map)
            # Handle a move towards action.  Move towards a target following a particular path.
            if result_type == ResultTypes.MOVE_WITH_PATH:
                npc, path = result_data
                self.game_map.current_level.paths.append(path)
                npc.movement.attempt_move(Point(path[0][0], path[0][1]),
                                          self.game_map)
            # Handle a move random adjacent action.  Move to a random adjacent
            # square.
            if result_type == ResultTypes.MOVE_RANDOM_ADJACENT:
                npc = result_data
                npc.movement.move_to_random_adjacent(self.game_map)

            if result_type == ResultTypes.MOVE_FORCE:
                target, dx, dy, damage = result_data
                if damage > 0 and not target.movement.move(
                        dx, dy, self.game_map.current_level):
                    damage_results, total_damage = target.health.take_damage(
                        damage)
                    msg_text = '{0} crashes into the wall and takes {1} hit points damage.'
                    message = Message(
                        msg_text.format(target.name, str(total_damage)),
                        COLORS.get('damage_text'))
                    turn_results.extend([{ResultTypes.MESSAGE: message}])
                    turn_results.extend(damage_results)

            # Add a new entity to the game.
            if result_type == ResultTypes.ADD_ENTITY:
                self.game_map.current_level.add_entity(result_data)
            # Remove an entity from the game.
            if result_type == ResultTypes.REMOVE_ENTITY:
                self.game_map.current_level.remove_entity(result_data)
            if result_type == ResultTypes.TARGETING:
                self.previous_game_state = self.game_state
                self.game_state = GameStates.TARGETING

            if result_type == ResultTypes.COMMON_IDENT:
                identified_items[result_data] = True
예제 #19
0
def main():
    name = "pythonRL"

    screenWidth = 80
    screenHeight = 50

    bar_width = 20
    panel_height = 7
    panel_y = screenHeight - panel_height

    message_x = bar_width + 2
    message_width = screenWidth - bar_width - 1
    message_height = panel_height - 1

    mapWidth = 80
    mapHeight = 43

    room_min_size = 6
    room_max_size = 10
    max_rooms = 30

    fov_algorithm = 0
    fov_light_walls = True
    fov_radius = 10

    max_monsters_per_room = 3

    colors = {
        'dark_wall': tcod.Color(61, 31, 0),
        'dark_ground': tcod.Color(41, 21, 0),
        'light_wall': tcod.Color(77, 38, 0),
        'light_ground': tcod.Color(56, 28, 0),
        'nothing': tcod.Color(0, 0, 0)
    }

    fighter_component = Fighter(hp=30, defense=2, power=5)
    player = Entity(0,
                    0,
                    "@",
                    tcod.white,
                    "Player",
                    blocks=True,
                    render_order=RenderOrder.ACTOR,
                    fighter=fighter_component)
    entities = [player]

    tcod.console_set_custom_font(
        'arial10x10.png', tcod.FONT_TYPE_GREYSCALE | tcod.FONT_LAYOUT_TCOD)

    tcod.console_init_root(screenWidth, screenHeight, name, False,
                           tcod.RENDERER_SDL2, "F", True)

    con = tcod.console.Console(screenWidth, screenHeight, "F")
    panel = tcod.console.Console(screenWidth, panel_height)

    game_map = GameMap(mapWidth, mapHeight)
    game_map.make_map(max_rooms, room_min_size, room_max_size, mapWidth,
                      mapHeight, player, entities, max_monsters_per_room)

    fov_recompute = True

    fov_map = initialize_fov(game_map)

    message_log = MessageLog(message_x, message_width, message_height)

    key = tcod.Key()
    mouse = tcod.Mouse()

    game_state = GameStates.PLAYERS_TURN

    while not tcod.console_is_window_closed():
        tcod.sys_check_for_event(tcod.EVENT_KEY_PRESS | tcod.EVENT_MOUSE, key,
                                 mouse)

        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, fov_radius,
                          fov_light_walls, fov_algorithm)

        render_all(con, panel, entities, player, game_map, fov_map,
                   fov_recompute, message_log, screenWidth, screenHeight,
                   bar_width, panel_height, panel_y, mouse, colors)

        fov_recompute = False

        tcod.console_flush()

        clear_all(con, entities)

        action = handle_keys(key)

        move = action.get("move")
        exit = action.get("exit")
        fullscreen = action.get("fullscreen")
        generate = action.get("gen")

        player_turn_results = []

        if move and game_state == GameStates.PLAYERS_TURN:
            dx, dy = move
            dest_x = player.x + dx
            dest_y = player.y + dy

            if not game_map.is_blocked(dest_x, dest_y):
                target = get_blocking_entities_at_location(
                    entities, dest_x, dest_y)

                if target:
                    attack_results = player.fighter.attack(target)
                    player_turn_results.extend(attack_results)
                else:
                    player.move(dx, dy)
                    fov_recompute = True

                game_state = GameStates.ENEMY_TURN

        if exit:
            return True

        if fullscreen:
            tcod.console_set_fullscreen(not tcod.console_is_fullscreen())

        for player_turn_result in player_turn_results:
            message = player_turn_result.get("message")
            dead_entity = player_turn_result.get("dead")

            if message:
                message_log.add_message(message)

            if dead_entity:
                if dead_entity == player:
                    message, game_state = kill_player(dead_entity)
                else:
                    message = kill_monster(dead_entity)

                message_log.add_message(message)

        if game_state == GameStates.ENEMY_TURN:
            for entity in entities:
                if entity.ai:
                    enemy_turn_results = entity.ai.take_turn(
                        player, fov_map, game_map, entities)

                    for enemy_turn_result in enemy_turn_results:
                        message = enemy_turn_result.get("message")
                        dead_entity = enemy_turn_result.get("dead")

                        if message:
                            message_log.add_message(message)

                        if dead_entity:
                            if dead_entity == player:
                                message, game_state = kill_player(dead_entity)
                            else:
                                message = kill_monster(dead_entity)

                            message_log.add_message(message)

                            if game_state == GameStates.PLAYER_DEAD:
                                break

                    if game_state == GameStates.PLAYER_DEAD:
                        break

            else:
                game_state = GameStates.PLAYERS_TURN

        if generate:
            game_map.clear()
            game_map.make_map(max_rooms, room_min_size, room_max_size,
                              mapWidth, mapHeight, player)
            fov_map = initialize_fov(game_map)
            fov_recompute = True
예제 #20
0
def main():
    screen_width = 80
    screen_height = 50

    bar_width = 20
    panel_height = 7
    panel_y = screen_height - panel_height

    message_x = bar_width + 2
    message_width = screen_width - bar_width - 2
    message_height = panel_height - 1

    map_width = 80
    map_height = 43

    room_max_size = 10
    room_min_size = 6
    max_rooms = 30

    fov_algorithm = 0
    fov_light_walls = True
    fov_radius = 10

    max_monsters_per_room = 3

    colors = {
        'dark_wall': libtcod.Color(0, 0, 100),
        'dark_ground': libtcod.Color(50, 50, 150),
        'light_wall': libtcod.Color(130, 110, 50),
        'light_ground': libtcod.Color(200, 180, 50)
    }

    fighter_component = Fighter(hp=30, defense=2, power=5)
    player = Entity(0,
                    0,
                    "@",
                    libtcod.white,
                    'Player',
                    blocks=True,
                    render_order=RenderOrder.ACTOR,
                    fighter=fighter_component)
    entities = [player]

    libtcod.console_set_custom_font(
        'arial10x10.png',
        libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD)

    libtcod.console_init_root(screen_width, screen_height, 'Paradiso', False)

    con = libtcod.console_new(screen_width, screen_height)
    panel = libtcod.console_new(screen_width, panel_height)

    game_map = GameMap(map_width, map_height)
    game_map.make_map(max_rooms, room_min_size, room_max_size, map_width,
                      map_height, player, entities, max_monsters_per_room)

    fov_recompute = True

    fov_map = initialize_fov(game_map)

    message_log = MessageLog(message_x, message_width, message_height)

    key = libtcod.Key()
    mouse = libtcod.Mouse()

    game_state = GameStates.PLAYERS_TURN

    while not libtcod.console_is_window_closed():
        libtcod.sys_check_for_event(
            libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, key, mouse)

        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, fov_radius,
                          fov_light_walls, fov_algorithm)

        render_all(con, panel, entities, player, game_map, fov_map,
                   fov_recompute, message_log, screen_width, screen_height,
                   bar_width, panel_height, panel_y, mouse, colors)
        fov_recompute = False

        libtcod.console_flush()

        clear_all(con, entities)

        action = handle_keys(key)

        move = action.get('move')
        exit = action.get('exit')
        fullscreen = action.get('fullscreen')

        player_turn_results = []

        if move and game_state == GameStates.PLAYERS_TURN:
            dx, dy = move
            destination_x = player.x + dx
            destination_y = player.y + dy

            if not game_map.is_blocked(destination_x, destination_y):
                target = get_blocking_entities_at_location(
                    entities, destination_x, destination_y)

                if target:
                    attack_results = player.fighter.attack(target)
                    player_turn_results.extend(attack_results)
                else:
                    player.move(dx, dy)
                    fov_recompute = True

                game_state = GameStates.ENEMY_TURN

        if exit:
            return True

        if fullscreen:
            libtcod.console_set_fullscreen(not libtcod.console_is_fullscreen())

        for player_turn_result in player_turn_results:
            message = player_turn_result.get('message')
            dead_entity = player_turn_result.get('dead')

            if message:
                message_log.add_message(message)

            if dead_entity:
                if dead_entity == player:
                    message, game_state = kill_player(dead_entity)
                else:
                    message = kill_monster(dead_entity)

                message_log.add_message(message)

        if game_state == GameStates.ENEMY_TURN:
            for entity in entities:
                if entity.ai:
                    enemy_turn_results = entity.ai.take_turn(
                        player, fov_map, game_map, entities)

                    for enemy_turn_result in enemy_turn_results:
                        message = enemy_turn_result.get('message')
                        dead_entity = enemy_turn_result.get('dead')

                        if message:
                            message_log.add_message(message)

                        if dead_entity:
                            if dead_entity == player:
                                message, game_state = kill_player(dead_entity)
                            else:
                                message = kill_monster(dead_entity)

                            message_log.add_message(message)

                            if game_state == GameStates.PLAYER_DEAD:
                                break

                    if game_state == GameStates.PLAYER_DEAD:
                        break
            else:
                game_state = GameStates.PLAYERS_TURN
예제 #21
0
def main():
    screen_width: int = 80
    screen_height: int = 35

    bar_width: int = 20
    panel_height: int = 7
    panel_y: int = screen_height - panel_height
    ui_layer = 10

    message_x = bar_width + 2
    message_width = screen_width - bar_width - 2
    message_height = panel_height - 1

    map_width = 80
    map_height = 28
    max_monsters_per_room = 3

    con = Console(x=0, y=0, width=screen_width, height=screen_height)
    panel = Console(0, panel_y, screen_width, panel_height, layer=ui_layer)

    title = "Rogue Alchemist"
    font = "mplus-1p-regular.ttf"

    fighter_component = Fighter(hp=30, defense=2, power=5)
    player = Entity(x=0,
                    y=0,
                    char='@',
                    color=Color.BLACK,
                    name='Player',
                    blocks=True,
                    render_order=RenderOrder.ACTOR,
                    fighter=fighter_component)
    entities = [player]

    game_map = GameMap(map_width, map_height)
    game_map.generate_dungeon(player, entities, max_monsters_per_room)
    # game_map.generate_dungeon(map_width, map_height, cave=True)
    start_room = game_map.dungeon.rooms[0]

    fov_algorithm = 0
    fov_light_walls = True
    fov_radius = 10

    colors = {
        "dark_wall": Color.DARK_SLATE_GRAY,
        "dark_ground": Color.DIM_GRAY,
        "light_wall": Color.LIGHT_SLATE_GRAY,
        "light_ground": Color.LIGHT_GRAY,
        "dark_door": Color.SADDLE_BROWN,
        "light_door": Color.BROWN,
        "test": Color.GOLD,
    }

    fov_recompute = True
    fov_map = initialize_fov(game_map)

    message_log = MessageLog(message_x, message_width, message_height)

    key = None

    blt.open()  # initializes BearLib Terminal instance with default parameters
    terminal_options = f"window: title={title}, size={str(screen_width)}x{str(screen_height)}; font:{font}, size=12"
    blt.set(terminal_options)

    game_state = GameStates.PLAYERS_TURN

    while True:
        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, fov_radius,
                          fov_light_walls, fov_algorithm)

        render_all(entities, player, game_map, fov_map, fov_recompute,
                   message_log, screen_width, screen_height, bar_width,
                   panel_height, panel_y, colors)
        blt.refresh()

        fov_recompute = False

        # remove player's previous position
        clear_all(entities)

        if blt.has_input():  # if no inputs, don't wait
            key = blt.read()

        action = handle_keys(key)
        key = None

        movement = action.get("move")
        exit_game = action.get("exit")

        player_turn_results = []

        if movement and game_state == GameStates.PLAYERS_TURN:
            dx, dy = movement
            destination_x = player.x + dx
            destination_y = player.y + dy

            if not game_map.is_blocked(destination_x, destination_y):
                target = get_blocking_entities_at_location(
                    entities, destination_x, destination_y)

                if target:
                    attack_results = player.fighter.attack(target)
                    player_turn_results.extend(attack_results)
                else:
                    player.move(*movement)

                    fov_recompute = True

                game_state = GameStates.ENEMY_TURN

        if exit_game:
            blt.close()
            return True

        for player_turn_result in player_turn_results:
            message = player_turn_result.get("message")
            dead_entity = player_turn_result.get("dead")

            if message:
                message_log.add_message(message)

            if dead_entity:
                if dead_entity == player:
                    message, game_state = kill_player(dead_entity)
                else:
                    message = kill_monster(dead_entity)

                message_log.add_message(message)

        if game_state == GameStates.ENEMY_TURN:
            for entity in entities:
                visible = libtcod.map_is_in_fov(fov_map, entity.x, entity.y)
                if entity.ai:
                    enemy_turn_results = entity.ai.take_turn(
                        player, fov_map, game_map, entities)

                    for enemy_turn_result in enemy_turn_results:
                        message = enemy_turn_result.get("message")
                        dead_entity = enemy_turn_result.get("dead")

                        if message:
                            message_log.add_message(message)

                        if dead_entity:
                            if dead_entity == player:
                                message, game_state = kill_player(dead_entity)
                            else:
                                message = kill_monster(dead_entity)

                            message_log.add_message(message)

                            if game_state == GameStates.PLAYER_DEAD:
                                break

            if game_state == GameStates.PLAYER_DEAD:
                break

            game_state = GameStates.PLAYERS_TURN
예제 #22
0
def main():
    screen_width = 80
    screen_height = 50

    bar_width = 20
    panel_height = 7
    panel_y = screen_height - panel_height

    message_x = bar_width + 2
    message_width = screen_width - bar_width - 2
    message_height = panel_height - 1

    map_width = 80
    map_height = 43

    room_max_size = 10
    room_min_size = 6
    max_rooms = 30

    fov_algorithm = 'BASIC'
    fov_light_walls = True
    fov_radius = 10

    max_monsters_per_room = 3

    colors = {
        'dark_wall': (0, 0, 100),
        'dark_ground': (50, 50, 150),
        'light_wall': (130, 110, 50),
        'light_ground': (200, 180, 50),
        'desaturated_green': (63, 127, 63),
        'darker_green': (0, 127, 0),
        'dark_red': (191, 0, 0),
        'white': (255, 255, 255),
        'black': (0, 0, 0),
        'red': (255, 0, 0),
        'orange': (255, 127, 0),
        'light_red': (255, 114, 114),
        'darker_red': (127, 0, 0)
    }

    fighter_component = Fighter(hp=30, defense=2, power=5)
    player = Entity(0,
                    0,
                    '@', (255, 255, 255),
                    'Player',
                    blocks=True,
                    render_order=RenderOrder.ACTOR,
                    fighter=fighter_component)
    entities = [player]

    tdl.set_font('arial12x12.png', greyscale=True, altLayout=True)

    root_console = tdl.init(screen_width,
                            screen_height,
                            title='Roguelike Tutorial Revised')
    con = tdl.Console(screen_width, screen_height)
    panel = tdl.Console(screen_width, panel_height)

    game_map = GameMap(map_width, map_height)
    make_map(game_map, max_rooms, room_min_size, room_max_size, map_width,
             map_height, player, entities, max_monsters_per_room, colors)

    fov_recompute = True

    message_log = MessageLog(message_x, message_width, message_height)

    mouse_coordinates = (0, 0)

    game_state = GameStates.PLAYERS_TURN

    while not tdl.event.is_window_closed():
        if fov_recompute:
            game_map.compute_fov(player.x,
                                 player.y,
                                 fov=fov_algorithm,
                                 radius=fov_radius,
                                 light_walls=fov_light_walls)

        render_all(con, panel, entities, player, game_map, fov_recompute,
                   root_console, message_log, screen_width, screen_height,
                   bar_width, panel_height, panel_y, mouse_coordinates, colors)
        tdl.flush()

        clear_all(con, entities)

        fov_recompute = False

        for event in tdl.event.get():
            if event.type == 'KEYDOWN':
                user_input = event
                break
            elif event.type == 'MOUSEMOTION':
                mouse_coordinates = event.cell
        else:
            user_input = None

        if not user_input:
            continue

        action = handle_keys(user_input)

        move = action.get('move')
        exit_action = action.get('exit')
        switch_fullscreen = action.get('switch_fullscreen')

        player_turn_results = []

        if move and game_state == GameStates.PLAYERS_TURN:
            dx, dy = move
            destination_x = player.x + dx
            destination_y = player.y + dy
            if game_map.walkable[destination_x, destination_y]:
                target = get_blocking_entities_at_location(
                    entities, destination_x, destination_y)

                if target:
                    attack_results = player.fighter.attack(target)
                    player_turn_results.extend(attack_results)
                else:
                    player.move(dx, dy)
                    fov_recompute = True

                game_state = GameStates.ENEMY_TURN

        if exit_action:
            return True

        if switch_fullscreen:
            tdl.set_fullscreen(not tdl.get_fullscreen())

        for player_turn_result in player_turn_results:
            message = player_turn_result.get('message')
            dead_entity = player_turn_result.get('dead')

            if message:
                message_log.add_message(message)

            if dead_entity:
                if dead_entity == player:
                    message, game_state = kill_player(dead_entity, colors)
                else:
                    message = kill_monster(dead_entity, colors)

                message_log.add_message(message)

        if game_state == GameStates.ENEMY_TURN:
            for entity in entities:
                if entity.ai:
                    enemy_turn_results = entity.ai.take_turn(
                        player, game_map, entities)

                    for enemy_turn_result in enemy_turn_results:
                        message = enemy_turn_result.get('message')
                        dead_entity = enemy_turn_result.get('dead')

                        if message:
                            message_log.add_message(message)

                        if dead_entity:
                            if dead_entity == player:
                                message, game_state = kill_player(
                                    dead_entity, colors)
                            else:
                                message = kill_monster(dead_entity, colors)

                            message_log.add_message(message)

                            if game_state == GameStates.PLAYER_DEAD:
                                break

                if game_state == GameStates.PLAYER_DEAD:
                    break
            else:
                game_state = GameStates.PLAYERS_TURN

        if user_input.key == 'ESCAPE':
            return True
예제 #23
0
def main():
	screen_width = 80 # /4 = 20
	screen_height = 50 # /4 ~= 12

	# Map panel parameters
	map_width = 45
	map_height = 40

	fov_algorithm = libtcod.FOV_SHADOW
	fov_light_walls = True
	fov_radius = 9

	# Health/Stats panel parameters
	bar_x = 4
	bar_width = 24
	panel_height = screen_height - map_height - 1
	panel_y = screen_height - panel_height

	# Message panel parameters
	message_x = bar_width + bar_x + 2
	message_width = screen_width - bar_width - bar_x - 2
	message_height = panel_height - 2

	message_log = MessageLog(message_x, message_width, message_height)

	# set up player entity and active entity list
	# TODO: Allow player to assign stats when starting to play
	fighter_component = Fighter(
		hp=30, 
		defense=5, spdefense=5, 
		attack=5, spattack=5, 
		speed=5)
	player = Entity(int(screen_width / 2), int(screen_height / 2), 
		'@', libtcod.white, 'Player', 
		render_order=RenderOrder.ACTOR, blocks=True, fighter=fighter_component)
	entities = []

	# set up console
	libtcod.console_set_custom_font('arial10x10.png', 
		libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD)
	libtcod.console_init_root(screen_width, screen_height, 
		'libtcod tutorial revised', False, 
		libtcod.RENDERER_SDL2, vsync=True)

	# set up all panels
	con = libtcod.console.Console(screen_width, screen_height)
	panel = libtcod.console.Console(screen_width, panel_height)

	# load map, entities and player
	game_world = GameWorld(map_width, map_height)
	game_world.loadfirstfloor(player, entities)

	# player field of vision variables
	fov_recompute = True
	fov_map = initialize_fov(game_world.currmap)

	# input variables
	key = libtcod.Key()
	mouse = libtcod.Mouse()

	# state variables
	game_state = GameState.PLAYERS_TURN

	while not libtcod.console_is_window_closed():
		# poll input
		libtcod.sys_check_for_event(
			libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, 
			key, mouse)

		# compute field of vision
		if fov_recompute:
			if game_world.currmap.islair:
				current_fov_radius = 20
			else:
				current_fov_radius = fov_radius
			recompute_fov(fov_map, player.x, player.y, current_fov_radius, 
				fov_light_walls, fov_algorithm)

		# draw screen
		render_all(con, panel, entities, player, game_world.currmap, 
			message_log, fov_map, fov_recompute, 
			screen_width, screen_height, 
			bar_x, bar_width, panel_height, panel_y, mouse)
		fov_recompute = False
		libtcod.console_flush()

		# erase previous player position
		clear_all(con, entities)

		# parse input
		action = handle_keys(key)

		move = action.get('move')
		exit = action.get('exit')
		fullscreen = action.get('fullscreen')
		confirm = action.get('confirm')
		cancel = action.get('cancel')
		wait = action.get('wait')

		player_turn_results = []

		# update
		if move and game_state == GameState.PLAYERS_TURN:
			dx, dy = move # saves dx and dy outside of the while loop too
			dest_x = player.x + dx
			dest_y = player.y + dy

			if not game_world.currmap.tileblocked(dest_x, dest_y):
				target = get_blocking_entities_at_location(
					entities, dest_x, dest_y)

				if target:
					if target.door:
						game_world.movetonextroom(player, entities, 
							target.door.direction)
						fov_map = initialize_fov(game_world.currmap)
						fov_recompute = True
						con.clear(fg=(0, 0, 0))
					elif target.stairs:
						game_world.movetonextfloor(player, entities)
						fov_map = initialize_fov(game_world.currmap)
						fov_recompute = True
						con.clear(fg=(0, 0, 0))
					elif target.fighter:
						attack_results = player.fighter.attacktarget(
							target, player.fighter.attacks[0])
						player_turn_results.extend(attack_results)
				else:
					player.move(dx, dy)
					fov_recompute = True

				if (game_state == GameState.PLAYERS_TURN):
					game_state = GameState.ENEMY_TURN

		if wait and game_state == GameState.PLAYERS_TURN:
			game_state = GameState.ENEMY_TURN

		if exit:
			return True

		if fullscreen:
			libtcod.console_set_fullscreen(
				not libtcod.console_is_fullscreen())

		for player_turn_result in player_turn_results:
			message = player_turn_result.get('message')
			dead_entity = player_turn_result.get('dead')

			if message:
				message_log.add_message(message)

			if dead_entity:
				if dead_entity == player:
					message, game_state = kill_player(dead_entity)
				else:
					if (dead_entity.char == '@'):
						# dead boss, spawn stairs, update world
						game_world.bosses_cleared[game_world.current_floor] = True
						entities.extend(
							game_world.currmap.spawnstairsdown())
					message = kill_monster(dead_entity)

				message_log.add_message(message)

		if game_state == GameState.ENEMY_TURN:
			for entity in entities:
				if entity.ai:
					enemy_turn_results = entity.ai.take_turn(
						game_world.currmap, entities)

					for enemy_turn_result in enemy_turn_results:
						message = enemy_turn_result.get('message')
						dead_entity = enemy_turn_result.get('dead')

						if message:
							message_log.add_message(message)

						if dead_entity:
							if dead_entity == player:
								message, game_state = kill_player(dead_entity)
							else:
								if (dead_entity.char == '@'):
									# dead boss, spawn stairs, update world
									game_world.bosses_cleared[game_world.current_floor] = True
									entities.extend(
										game_world.currmap.spawnstairsdown())
								message = kill_monster(dead_entity)

							message_log.add_message(message)

							if game_state == GameState.PLAYER_DEAD:
								break

					if game_state == GameState.PLAYER_DEAD:
						break
			else:
				game_state = GameState.PLAYERS_TURN
예제 #24
0
class Engine():
    def __init__(self):
        # Set up the game window
        #libtcod.console_set_custom_font('spritesheet.png', libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD)
        libtcod.console_set_custom_font(
            'Winterwing_Curses.png',
            libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_ASCII_INROW)
        libtcod.console_init_root(game_constants.screen_width,
                                  game_constants.screen_height,
                                  'Ascetic of the Cabal',
                                  True,
                                  libtcod.RENDERER_SDL2,
                                  vsync=True)

        # Establish the primary console as well as the detail panel
        self.con = libtcod.console.Console(game_constants.screen_width,
                                           game_constants.screen_height)
        self.panel = libtcod.console.Console(game_constants.screen_width,
                                             game_constants.panel_height)

        # Create references for the player input
        self.key = libtcod.Key()
        self.mouse = libtcod.Mouse()

        self.initialize_game()

    # Initializes a lot of run-specific items. Kept outside of init because it has to be re-run on a restart
    def initialize_game(self):
        # Create and initialize the Message Log
        self.message_log = MessageLog()

        #Initialize the player
        self.player = self.initialize_player()

        # Create a game map and fill it with enemies
        self.build_map()

        self.player_target = None

        # Establish the Game State
        self.game_map.compute_dijkstra_map([self.player], 'player', True)
        self.game_map.compute_dijkstra_map(
            self.entities.get_sublist(lambda x: x.name != "Ascetic"),
            "enemies")
        self.game_state = GameStates.PLAYERS_TURN
        self.previous_game_state = GameStates.PLAYERS_TURN
        self.game_running = True

    # Creates the player object, with all associated defaults
    # This can and probably should be moved to another file
    def initialize_player(self):
        player_components = {
            "Fighter":
            Fighter(hp=300, defense=2, power=5, factions=[Factions.PLAYER]),
            "Inventory":
            Inventory(26),
            "Devotee":
            Devotee(100),
            "StatusContainer":
            StatusContainer()
        }

        player = Entity(int(game_constants.screen_width / 2),
                        int(game_constants.screen_height / 2),
                        '@',
                        libtcod.white,
                        "Ascetic",
                        True,
                        RenderOrder.ACTOR,
                        message_log=self.message_log,
                        state=AIStates.INANIMATE,
                        components=player_components)

        player.get_component("Inventory").equip_item(
            generate_starting_pistol(self.message_log))
        return player

    # Generates a game map and initializes the FOV map of it
    def build_map(self, level=1):
        self.game_map = GameMap(self.message_log, level)
        self.entities = Entities(self.game_map)
        self.game_map.make_map(self.player, self.entities)
        self.entities.insert_entity(self.player)

        self.fov_recompute = True
        self.fov_map = initialize_fov(self.game_map)

    # Literally 0 recollection what this does
    def grade_map_down(self):
        self.game_map.grade_down()

    def cull_dead(self):
        # Finds every entity in the game world with 0 or less health and kills them
        # Returns true if it kills the player, otherwise false
        player_killed = False
        dead_entities = self.entities.get_sublist(
            lambda x: x.has_component("Fighter") and not x.get_component(
                "Fighter").isAlive() and x.char != '%')

        if dead_entities:
            for dead_entity in dead_entities:
                drop = dead_entity.get_component("Fighter").die()
                if drop:
                    self.entities.insert_entity(drop)
                if dead_entity == self.player:
                    player_killed = True
        return player_killed

    def send_invalid_action_message(self):
        self.message_log.add_message(Message("Can't do that here"),
                                     libtcod.red)

    # Initializes the game's start menu, and captures any player input on that menu and passes it to the appropriate handler
    def start_screen(self):
        show_main_menu = True

        while show_main_menu:
            libtcod.sys_check_for_event(
                libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, self.key,
                self.mouse)
            main_menu(self.con, game_constants.main_menu_background_image)

            libtcod.console_flush()

            action = handle_keys(self.key, GameStates.MAIN_MENU)
            game_type = action.get('game_start')
            exit_game = action.get('action') == 'exit'

            if exit_game:
                return False
            elif game_type == 'from_scratch':
                return True
            elif game_type == 'from_save':
                self.player, self.entities, self.game_map, self.message_log, self.game_state = load_game(
                )
                self.fov_map = initialize_fov(self.game_map)
                self.entities.set_log_all(self.message_log)
                return True

    def main(self):
        # Game Loop
        while self.game_running:
            # Check input streams for an event
            libtcod.sys_check_for_event(
                libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, self.key,
                self.mouse)

            # If we need to recompute fov, do so
            if self.fov_recompute:
                recompute_fov(self.fov_map, self.player.x, self.player.y)

            # Render the game world according to current FOV, mark FOV recompute as complete, and flush to console
            render_all(self.con, self.panel, self.entities, self.player,
                       self.game_map, self.fov_map, self.fov_recompute,
                       self.message_log, self.mouse, self.game_state,
                       self.player_target)
            self.fov_recompute = False
            libtcod.console_flush()

            # Interpret the input into a game action
            input = handle_keys(self.key, self.game_state)
            action = input.get('action')

            inventory_item = input.get(
                'inventory_item') if 'inventory_item' in input else None
            dialogue_option = input.get(
                'dialogue_option') if 'dialogue_option' in input else None
            shop_option = input.get(
                'shop_option') if 'shop_option' in input else None
            unequip_item = input.get('slot') if 'slot' in input else None

            # If players turned and it's their turn to move
            if action == 'move' and self.game_state == GameStates.PLAYERS_TURN:
                # Calculate where they should move
                dx, dy = input.get('move')
                destination_x = self.player.x + dx
                destination_y = self.player.y + dy

                # TODO: This is where you hid the noclip check. Fix this for release
                #if not self.game_map.is_blocked(destination_x, destination_y):
                if True:
                    # If they're not about to walk into a wall, check for enemies at the destination
                    potential_collision_list = self.entities.get_sublist(
                        lambda ent: ent.x == destination_x and ent.y ==
                        destination_y and ent.blocks)
                    target = potential_collision_list[
                        0] if potential_collision_list else None
                    if target and target.state == AIStates.HOSTILE:
                        # If there are enemies, attack them
                        self.player.get_component("Fighter").attack(target)
                        self.game_state = GameStates.ENEMY_TURN
                    elif target and target.state == AIStates.FRIENDLY:
                        self.previous_game_state = self.game_state
                        self.player_target = target
                        self.game_state = GameStates.DIALOGUE
                    else:
                        # If there are not enemies, move and mark FOV for recomputation
                        self.player.move(dx, dy, self.game_map)
                        self.fov_recompute = True
                        self.game_map.compute_dijkstra_map([self.player],
                                                           'player', True)
                        self.game_state = GameStates.ENEMY_TURN

            # If the player grabs something, check if there is an object at their feet, and either have them pick it up (if it's an Item) or add it to their wallet (if it's money)
            elif action == 'grab' and self.game_state == GameStates.PLAYERS_TURN:
                for item in self.entities.get_sublist(
                        lambda entity: (entity.has_component("Item") or entity.
                                        has_component("Money")) and entity.x ==
                        self.player.x and entity.y == self.player.y):
                    if item.has_component("Money"):
                        self.player.get_component("Fighter").pick_up_money(
                            item)
                    else:
                        self.player.get_component("Inventory").add_item(item)
                    self.entities.remove_entity(item)
                    self.game_state = GameStates.ENEMY_TURN

            # Open up the inventory menu
            elif action == 'inventory' and inventory_item is None:
                self.previous_game_state = self.game_state
                self.game_state = GameStates.INVENTORY_OPEN

            # Open up the equipped menu
            elif action == 'equipped':
                self.previous_game_state = self.game_state
                self.game_state = GameStates.EQUIPPED_OPEN

            elif action == 'unequip' and self.game_state == GameStates.EQUIPPED_OPEN:
                self.player.get_component("Inventory").unequip_slot(
                    unequip_item)

            # if the player has selected an inventory item to use, get the item object, and equip it if it's vgear, or use it if it's a consumable (like a potion)
            elif inventory_item is not None and self.previous_game_state != GameStates.PLAYER_DEAD and inventory_item < len(
                    self.player.get_component("Inventory").items):
                item_entity = self.player.get_component(
                    "Inventory").items[inventory_item]
                if ItemType(item_entity.get_component(
                        "Item").item_type) != ItemType.NONE:
                    self.player.get_component("Inventory").equip_item(
                        item_entity)
                else:
                    print("In the else")
                    if item_entity.get_component("Item").use(self.player):
                        self.player.get_component("Inventory").remove_item(
                            item_entity)

            # if the player is in dialogue, provide the dialogue option to the target's Character object
            elif dialogue_option is not None:
                dialogue_response = self.player_target.get_component(
                    "Character").talk(dialogue_option)
                if dialogue_response.shop:
                    self.game_state = GameStates.SHOPPING

            # if the player attempts to go down some stairs, make sure they're on stairs, then build a new map and clear the console
            elif action == 'go_down' and self.game_state == GameStates.PLAYERS_TURN:
                stairs_candidates = self.entities.get_sublist(
                    lambda entity: entity.x == self.player.x and entity.y ==
                    self.player.y and entity.has_component("Stairs"))
                if stairs_candidates:
                    self.build_map(
                        stairs_candidates[0].get_component("Stairs").floor)
                    libtcod.console_clear(self.con)

            # Save the game
            elif action == 'save':
                save_game(self.player, self.entities, self.game_map,
                          self.message_log, self.game_state)

            # if the player draws their gun, change to a player shoot state and await gunfire
            elif self.game_state == GameStates.PLAYERS_TURN and action == 'gun':
                if (self.player.get_component("Inventory").slot_filled(
                        "RANGED")):
                    self.previous_game_state = self.game_state
                    self.game_state = GameStates.PLAYER_SHOOT
                    self.message_log.add_message(
                        Message(
                            "Taking aim. Click on your target, or e to holster"
                        ))
                else:
                    self.message_log.add_message(
                        Message("No ranged weapon equipped!"))

            # if the player already has their gun drawn and presses the draw button, holster it instead
            elif self.game_state == GameStates.PLAYER_SHOOT and action == 'holster':
                self.game_state = self.previous_game_state
                self.message_log.add_message(Message("Holstered your weapon"))

            # if the player has their gun drawn and clicks on a target, check if there is line of sight
            # and if so, shoot the target. This sets the AI to hostile if it isn't already (this should be handled by Fighter)
            elif self.game_state == GameStates.PLAYER_SHOOT and self.mouse.lbutton_pressed:
                target = get_shoot_target(self.mouse, self.entities,
                                          self.fov_map)
                if (target):
                    line_of_sight = draw_line((self.player.x, self.player.y),
                                              (target.x, target.y))
                    if not [
                            space for space in line_of_sight
                            if self.game_map.is_blocked(space[0], space[1])
                    ]:
                        self.player.get_component("Fighter").ranged_attack(
                            target)
                        target.state = AIStates.HOSTILE
                        self.game_state = GameStates.ENEMY_TURN
                    else:
                        self.message_log.add_message(
                            Message("You don't have a clear line of sight!"))

            # if the player right clicks something, get open up the inspect menu for that target
            elif self.mouse.rbutton_pressed and self.game_state != GameStates.INSPECT_OPEN:
                target = get_shoot_target(self.mouse, self.entities,
                                          self.fov_map, False)
                if (target):
                    self.player_target = target
                    self.previous_game_state = self.game_state
                    self.game_state = GameStates.INSPECT_OPEN

            # If the player is buying something, they make the purchase
            elif action == 'buy' and shop_option is not None:
                target.get_component("Shop").purchase(shop_option, self.player)

            elif action == 'status':
                self.previous_game_state = self.game_state
                self.game_state = GameStates.STATUS

            # Exit the game
            if action == 'exit' and (self.game_state in [
                    GameStates.INVENTORY_OPEN, GameStates.DIALOGUE,
                    GameStates.EQUIPPED_OPEN, GameStates.SHOPPING,
                    GameStates.INSPECT_OPEN, GameStates.STATUS
            ]):
                self.game_state = self.previous_game_state
            elif action == 'exit':
                return True

            # Set the game to fullscreen
            if action == 'fullscreen':
                libtcod.console_set_fullscreen(
                    not libtcod.console_is_fullscreen())

            # cull_dead returns true if the player is dead, so this conditional calls it to cull the dead, and then
            # checks if the game is over
            if self.cull_dead():
                self.game_state = GameStates.PLAYER_DEAD

            # when it's the AI's turn, find every entity that has AI and move it (if it's hostile)
            if self.game_state == GameStates.ENEMY_TURN:
                for entity in self.entities.get_entity_set():
                    if entity.has_component(
                            "AI") and entity.state == AIStates.HOSTILE:
                        entity.get_component("AI").take_turn(
                            self.player, self.fov_map, self.game_map,
                            self.entities)
                        if self.cull_dead():
                            self.game_state = GameStates.PLAYER_DEAD
                    if entity.has_component("StatusContainer"):
                        entity.get_component("StatusContainer").tick_clocks()
                        for status in entity.get_component(
                                "StatusContainer").get_statuses():
                            status_mapping[status](entity, self.entities,
                                                   self.game_map)

                if self.game_state != GameStates.PLAYER_DEAD:
                    self.player.get_component("StatusContainer").tick_clocks()
                    for status in self.player.get_component(
                            "StatusContainer").get_statuses():
                        status_mapping[status](self.player, self.entities,
                                               self.game_map)
                    self.game_map.compute_dijkstra_map(
                        self.entities.get_sublist(
                            lambda x: x.name != "Ascetic"), "enemies")
                    self.game_state = GameStates.PLAYERS_TURN

            # TODO: need a check somewhere around here to tick condition clocks, and then to apply conditions

            if action == 'restart':
                libtcod.console_clear(self.con)
                self.initialize_game()
예제 #25
0
def main():
    screen_width = 80
    screen_height = 50

    bar_width = 20
    panel_height = 7
    panel_y = screen_height - panel_height

    message_x = bar_width + 2
    message_width = screen_width - bar_width - 2
    message_height = panel_height - 1

    map_width = 80
    map_height = 43

    fov_algorithm = 'BASIC'
    fov_light_walls = True
    fov_radius = 10

    colors = {
        'dark_wall': (0, 0, 100),
        'dark_ground': (50, 50, 150),
        'light_wall': (130, 110, 50),
        'light_ground': (200, 180, 50),
        'white': (255, 255, 255),
        'black': (0, 0, 0),
        'light red': (255, 100, 100),
        'red': (255, 0, 0),
        'yellow': (255, 255, 0),
        'orange': (255, 127, 0),
        'green': (
            0,
            255,
            0,
        ),
        'light_red': (255, 114, 114),
        'darker_red': (127, 0, 0),
        'highlight': (199, 234, 70)
    }

    mech_component = Mech(hp=30, peak_momentum=6)
    weapon_component = Weapon(name="Laser",
                              damage=5,
                              min_targets=0,
                              max_targets=5,
                              color=colors.get('green'),
                              range=10)
    player = Entity(int(screen_width / 2),
                    int(screen_height / 2),
                    '@',
                    colors.get('white'),
                    "player",
                    mech=mech_component,
                    weapon=weapon_component)
    npc = Entity(int(screen_width / 2 - 5), int(screen_height / 2), '@',
                 colors.get('yellow'), "NPC")
    cursor_component = Cursor()
    cursor = Entity(
        -1, -1, ' ', colors.get('red'), "cursor", cursor=cursor_component
    )  # The ' ' isn't actually "nothing". To have nothing, I would have to mess with a render order.
    entities = [npc, player, cursor]

    tdl.set_font('arial10x10.png', greyscale=True, altLayout=True)

    root_console = tdl.init(screen_width, screen_height, title='MVP v0.0')
    con = tdl.Console(screen_width, screen_height)
    panel = tdl.Console(screen_width, panel_height)

    game_map = GameMap(map_width, map_height)
    make_map(game_map)

    message_log = MessageLog(message_x, message_width, message_height)

    mouse_coordinates = (0, 0)

    game_state = GameStates.PLAYER_TURN
    previous_game_state = game_state
    turn_state = TurnStates.UPKEEP_PHASE

    fov_recompute = True

    while not tdl.event.is_window_closed():
        if fov_recompute:
            game_map.compute_fov(player.x,
                                 player.y,
                                 fov=fov_algorithm,
                                 radius=fov_radius,
                                 light_walls=fov_light_walls)

        render_all(con, panel, entities, game_map, fov_recompute, root_console,
                   message_log, screen_width, screen_height, bar_width,
                   panel_height, panel_y, mouse_coordinates, colors)

        tdl.flush()

        clear_all(con, entities)

        for event in tdl.event.get():
            if event.type == 'KEYDOWN':
                user_input = event
                break
            elif event.type == 'MOUSEMOTION':
                mouse_coordinates = event.cell
        else:
            user_input = None

        fov_recompute = False

        action = handle_keys(user_input, game_state)
        impulse = None  # This is to avoid logic problems.
        change_game_state = None  # This is to avoid logic problems.

        move = action.get('move')  # Attempt to move.
        impulse = action.get('impulse')  # Adjust mech impulse.
        next_turn_phase = action.get(
            'next turn phase')  # Move to the next phase.
        change_game_state = action.get(
            'change game state')  # Go to different game_state
        select = action.get(
            'select')  # A target has been selected via keyboard.
        exit = action.get('exit')  # Exit whatever screen is open.
        fullscreen = action.get('fullscreen')  # Set game to full screen.

        if exit:
            if game_state == GameStates.TARGETING:
                # Turn off cursor
                cursor.char = ' '
                cursor.x = -1
                cursor.y = -1

                fov_recompute = True
                game_state = previous_game_state

            else:
                return True

        if fullscreen:
            tdl.set_fullscreen(not tdl.get_fullscreen())

        if game_state == GameStates.PLAYER_TURN:
            # See game_states.py for the turn structure.
            # Turns order is reversed so ensure that the loop runs once for each
            if turn_state == TurnStates.POST_ATTACK_PHASE:
                # Reset map flags and remove targets.
                reset_flags(game_map)
                for x, y in player.weapon.targets:
                    erase_cell(con, x, y)
                turn_state = TurnStates.UPKEEP_PHASE
                game_state = GameStates.ENEMY_TURN

            if turn_state == TurnStates.ATTACK_PHASE:
                if change_game_state == GameStates.TARGETING:
                    # Turn on cursor.
                    cursor.char = 'X'
                    # If there were no previous targets, start on the player.
                    if len(player.weapon.targets) == 0:
                        cursor.x = player.x
                        cursor.y = player.y
                    else:
                        cursor.x, cursor.y = player.weapon.targets[-1]

                    fov_recompute = True
                    previous_game_state = game_state
                    game_state = GameStates.TARGETING

                if next_turn_phase:
                    turn_state = TurnStates.POST_ATTACK_PHASE

            if turn_state == TurnStates.PRE_ATTACK_PHASE:
                message_log.add_message(
                    Message('Begin ATTACK PHASE.', colors.get('white')))
                message_log.add_message(
                    Message(
                        'Press f to target. Press ESC to stop targeting. Enter to change phase.',
                        colors.get('orange')))
                fov_recompute = True

                turn_state = TurnStates.ATTACK_PHASE

            if turn_state == TurnStates.POST_MOVEMENT_PHASE:
                reset_flags(game_map)
                player.reset(
                )  # Reset the mech for the next turn. ### Move this to the post-attack phase
                fov_recompute = True

                turn_state = TurnStates.PRE_ATTACK_PHASE

            if turn_state == TurnStates.MOVEMENT_PHASE:
                if move:
                    dx, dy = move
                    if game_map.walkable[player.x + dx, player.y + dy]:
                        player.move(dx, dy)

                        fov_recompute = True

                if next_turn_phase and player.mech.has_spent_minimum_momentum(
                ):
                    turn_state = TurnStates.POST_MOVEMENT_PHASE
                elif next_turn_phase and not player.mech.has_spent_minimum_momentum(
                ):
                    message_log.add_message(
                        Message('Must spend more momentum.',
                                colors.get('red')))

            if turn_state == TurnStates.PRE_MOVEMENT_PHASE:
                if impulse is not None:
                    player.mech.impulse = impulse
                    turn_state = TurnStates.MOVEMENT_PHASE
                    message_log.add_message(
                        Message('Impulse set to {0}.'.format(impulse),
                                colors.get('orange')))
                    fov_recompute = True
                    highlight_legal_moves(player, game_map)

            if turn_state == TurnStates.UPKEEP_PHASE and game_state == GameStates.PLAYER_TURN:  # This is added to avoid starting the Upkeep Phase when the turn just ended.
                message_log.add_message(
                    Message('Begin PLAYER TURN.', colors.get('white')))
                message_log.add_message(
                    Message('Begin MOVEMENT PHASE.', colors.get('white')))
                message_log.add_message(
                    Message('Choose impulse. PAGEUP, PAGEDOWN or HOME.',
                            colors.get('orange')))
                turn_state = TurnStates.PRE_MOVEMENT_PHASE
                fov_recompute = True

        if game_state == GameStates.ENEMY_TURN:
            message_log.add_message(
                Message('Begin ENEMY TURN.', colors.get('white')))
            fov_recompute = True

            game_state = GameStates.PLAYER_TURN

        if game_state == GameStates.TARGETING:
            if move:
                dx, dy = move
                # Ensure the first target is in firing range.
                if len(player.weapon.targets) == 0:
                    if player.distance(cursor.x + dx,
                                       cursor.y + dy) <= player.weapon.range:
                        cursor.fly(dx, dy)
                        fov_recompute = True
                    else:
                        message_log.add_message(
                            Message('Out of range.', colors.get('red')))
                # Ensure that the next targets are adjacent to the previous target
                elif len(player.weapon.targets) > 0:
                    tar_x, tar_y = player.weapon.targets[
                        -1]  # Get the most recent target added.
                    if abs(tar_x -
                           (cursor.x + dx)) + abs(tar_y -
                                                  (cursor.y + dy)) <= 1:
                        cursor.fly(dx, dy)
                        fov_recompute = True
                    else:
                        message_log.add_message(
                            Message('Invalid target.', colors.get('red')))

            if select:
                if len(player.weapon.targets) < player.weapon.max_targets:
                    if set_targeted(
                            game_map, cursor.x, cursor.y
                    ):  # At the moment, this always returns True. In the future, this may change.
                        fov_recompute = True
                        player.weapon.targets.append((cursor.x, cursor.y))
                else:
                    message_log.add_message(
                        Message('Targeting failed.', colors.get('red')))
예제 #26
0
def main():
    # Limit the FPS
    tcod.sys_set_fps(max_fps)

    # Set the font to be used
    tcod.console_set_custom_font('terminal8x8_gs_as.png', tcod.FONT_TYPE_GREYSCALE | tcod.FONT_LAYOUT_ASCII_INCOL)

    # Create the screen
    tcod.console_init_root(screen_width, screen_height, 'Rogue', False)

    con = tcod.console_new(screen_width, screen_height)
    panel = tcod.console_new(screen_width, screen_height)

    # Generate the tile map
    game_map = GameMap(map_width, map_height)

    # Initialize the player and the entities list
    player = Player(player_stats[0], player_stats[1], player_stats[2], player_stats[3], player_stats[4], game_map.tiles,
                    screen_width // 2, screen_height // 2, '@', colors.get("player"), "player", True)
    entities.append(player)

    # Represents the current dungeon floor
    floor_number = 1

    # Generate the rest of the game map
    generate_all(game_map, map_width, map_height, max_rooms, min_room_size, max_room_size, min_npcs, max_npcs, colors,
                 entities, floor_number)

    # Initialize user input
    key = tcod.Key()
    mouse = tcod.Mouse()

    # Initialize the game state
    game_state = GameStates.PLAYER_TURN

    # Initialize the message log
    message_log = MessageLog(message_x, message_width, message_height)

    # Determine whether or not the FOV needs to be recalculated
    fov_recalculate = True
    fov_map = initialize_fov(game_map)

    # Game loop
    while not tcod.console_is_window_closed():
        # Update key and mouse with the user inputs
        tcod.sys_check_for_event(tcod.EVENT_KEY_PRESS, key, mouse)

        if fov_recalculate:
            calculate_fov(fov_map, player.x, player.y, fov_radius, fov_light_walls, fov_algorithm)

        # Render everything
        render_all(con, panel, message_log, entities, game_map, fov_map, fov_recalculate, screen_width, screen_height,
                   bar_width,
                   panel_height, panel_y, debug)
        fov_recalculate = False

        # Apply the updates on screen
        tcod.console_flush()

        # Clear the entities in preparation for updates
        clear_all(con, entities)

        # Handle key presses
        action = handle_keys(key)

        move = action.get("move")
        use = action.get("use")
        exit = action.get("exit")
        fullscreen = action.get("fullscreen")
        reset = action.get("reset")
        regenerate = action.get("regenerate")

        player_turn_results = []

        if move and game_state == GameStates.PLAYER_TURN:
            dx, dy = move
            if not game_map.is_blocked(player.x + dx, player.y + dy):
                player.move(game_map.tiles, dx, dy)
                fov_recalculate = True

            target = enty.get_entity_at_location(player.x + dx, player.y + dy, entities)

            if target != -1:
                player_turn_results.extend(player.attack(target))

            game_state = GameStates.ENEMY_TURN

        if use and game_state == GameStates.PLAYER_TURN:
            if player.inventory[use - 1] is not None:
                player_turn_results.extend(player.inventory[use - 1].use(entities))

        if exit:
            return True

        if fullscreen:
            tcod.console_set_fullscreen(not tcod.console_is_fullscreen())

        if reset:  # Reset the game
            player, game_state, regen_values = reset_map(game_map, map_width, map_height, max_rooms, min_room_size,
                                                         max_room_size, min_npcs, max_npcs, colors, entities, message_x,
                                                         message_width, message_height)
            game_map, fov_recalculate, fov_map, message_log = regen_values

        if regenerate and debug:  # Properly generate a new game map
            game_map, fov_recalculate, fov_map, message_log = regenerate_map(player, map_width, map_height, max_rooms,
                                                                             min_room_size, max_room_size, min_npcs,
                                                                             max_npcs, colors, entities, floor_number,
                                                                             message_x, message_width, message_height)

        # Handle the player turn results
        for result in player_turn_results:
            dead_attacker = result.get("dead")

            if dead_attacker:
                message_log.add_message(Message("You have killed the {0}".format(dead_attacker.name)))
                dead_attacker.kill(game_map.tiles)

                message_log.add_message(Message("{0} XP granted".format(dead_attacker.xp)))
                level_up = player.add_xp(dead_attacker.xp).get("level up")

                if level_up:
                    message_log.add_message(Message("You reached level {0}".format(level_up[0])))
                    message_log.add_message(Message(level_up[1]))
                entities.remove(dead_attacker)

            damaged_entity = result.get("damaged")

            if damaged_entity:
                message_log.add_message(
                    Message("You attacked the {0} for {1} damage".format(damaged_entity[0], damaged_entity[1])))

            pickup_used = result.get("pickup_used")

            if pickup_used:
                message_log.add_message(Message(pickup_used[0]))
                if pickup_used[1].deletes:
                    pickup_used[1].delete(player)

            next_floor = result.get("next_floor")

            if next_floor:
                message_log.add_message(Message("You have advanced to floor {0}".format(next_floor + 1)))
                floor_number += 1
                game_map, fov_recalculate, fov_map, null = regenerate_map(player, map_width, map_height,
                                                                          max_rooms, min_room_size,
                                                                          max_room_size, min_npcs, max_npcs,
                                                                          colors, entities, floor_number,
                                                                          message_x, message_width,
                                                                          message_height, preserve_messages=True)

        # Enemy turn (really every entity that is not the player)
        if game_state == GameStates.ENEMY_TURN:
            enemy_turn_results = enty.entity_turn(entities, fov_map, game_map)
            game_state = GameStates.PLAYER_TURN

            # Handle the entity turn results
            for result in enemy_turn_results:
                dead = result.get("dead")

                if dead:
                    game_state = player.kill(game_map.tiles)
                    message_log.add_message(Message("You have died"))
                    message_log.add_message(Message("GAME OVER"))
                    break

                damaged_entity = result.get("damaged")

                if damaged_entity:
                    message_log.add_message(
                        Message("The {0} attacked you for {1} damage".format(damaged_entity[0], damaged_entity[1])))

                pickup_failed = result.get("pickup_failed")

                if pickup_failed:
                    message_log.add_message(
                        Message("You cannot pick up the {0} since your inventory is full".format(pickup_failed[0])))

                pickup_success = result.get("pickup_success")

                if pickup_success:
                    message_log.add_message(Message("You picked up the {0}".format(pickup_success[0])))
                    pickup_success[1].kill(game_map.tiles)
                    entities.remove(pickup_success[1])

                upgrade_used = result.get("upgrade_used")

                if upgrade_used:
                    message_log.add_message(Message(upgrade_used[0]))
                    message_log.add_message(Message(upgrade_used[1]))
                    upgrade_used[2].kill(game_map.tiles)
                    entities.remove(upgrade_used[2])
예제 #27
0
def main():
    # map vars
    map_width = 40
    map_height = 60
    room_min_size = 6
    room_max_size = 10
    max_rooms = 50
    max_monsters_per_room = 3
    max_items_per_room = 2

    # screen vars
    viewport_width = 80
    viewport_height = 60
    rerender_viewport = True
    map_x = viewport_width
    map_y = 0

    screen_width = viewport_width + map_width

    # stats panel vars
    bar_width = 20
    panel_width = screen_width
    panel_height = 8
    panel_x = 0
    panel_y = viewport_height
    message_x = bar_width + 2
    message_width = screen_width - bar_width - 2
    message_height = panel_height - 1

    screen_height = viewport_height + panel_height

    # fov vars
    fov_algorithm = 12
    fov_light_walls = True
    fov_radius = 10
    fov_recompute = True

    # game vars
    game_state = GameStates.PLAYER_TURN
    previous_game_state = game_state
    colours = {
        'dark_wall': tcod.Color(0, 0, 100),
        'dark_ground': tcod.Color(50, 50, 150),
        'light_wall': tcod.Color(130, 110, 50),
        'light_ground': tcod.Color(200, 180, 50)
    }

    # init player
    fighter_component = Fighter(30, 2, 5)
    inventory_component = Inventory(26)
    player = Entity(0,
                    0,
                    '@',
                    tcod.white,
                    'Player',
                    render_order=RenderOrder.ACTOR,
                    blocks=True,
                    fighter=fighter_component,
                    inventory=inventory_component)
    player_rot = 0.0
    entities = [player]

    # load assets
    wall_texture = Image.open('assets/wall_vines0.png')
    orc_texture = Image.open('assets/orc.png')
    troll_texture = Image.open('assets/troll.png')
    potion_texture = Image.open('assets/ruby.png')

    # init game map
    game_map = GameMap(map_width, map_height)
    game_map.make_map(max_rooms, room_min_size, room_max_size, map_width,
                      map_height, player, entities, max_monsters_per_room,
                      max_items_per_room, orc_texture, troll_texture,
                      potion_texture)
    game_map.recompute_fov(player.x, player.y, fov_radius, fov_light_walls,
                           fov_algorithm)

    # init message log
    message_log = MessageLog(message_x, message_width, message_height)

    tcod.console_set_custom_font(
        'arial10x10.png', tcod.FONT_TYPE_GREYSCALE | tcod.FONT_LAYOUT_TCOD)
    with tcod.console_init_root(screen_width,
                                screen_height,
                                'firstpersonroguelike',
                                vsync=True) as root_console:
        viewport_console = tcod.console.Console(viewport_width,
                                                viewport_height)
        map_console = tcod.console.Console(map_width, map_height)
        panel_console = tcod.console.Console(panel_width, panel_height)

        mouse = (0, 0)
        time_start = perf_counter()

        # game loop begin
        while True:
            for event in tcod.event.wait():
                tcod.console_flush()

                player_turn_results = []

                # handle inputs
                if event.type == "QUIT":
                    raise SystemExit()
                elif event.type == "MOUSEMOTION":
                    # record the new mouse position, render_all will take care of the rest
                    mouse = event.tile
                # player keyboard interaction
                elif event.type == "KEYDOWN":
                    action = handle_keys(event, game_state)

                    if len(action) == 0:
                        continue

                    elif action.get('exit'):
                        if game_state in (GameStates.SHOW_INVENTORY,
                                          GameStates.DROP_INVENTORY):
                            game_state = previous_game_state
                        else:
                            raise SystemExit()

                    elif action.get(
                            'pickup') and game_state is GameStates.PLAYER_TURN:
                        for entity in entities:
                            if entity.item and entity.x == player.x and entity.y == player.y:
                                pickup_results = player.inventory.add_item(
                                    entity)
                                player_turn_results.extend(pickup_results)
                                break
                        else:
                            message_log.add_message(
                                Message(
                                    'You inspect the empty ground below you. Looks pretty dirty',
                                    tcod.yellow))
                        game_state = GameStates.ENEMIES_TURN

                    elif action.get('show_inventory'
                                    ) and game_state is GameStates.PLAYER_TURN:
                        previous_game_state = game_state
                        game_state = GameStates.SHOW_INVENTORY

                    elif action.get('drop_inventory'
                                    ) and game_state is GameStates.PLAYER_TURN:
                        previous_game_state = game_state
                        game_state = GameStates.DROP_INVENTORY

                    elif action.get(
                            'inventory_index'
                    ) is not None and previous_game_state is not GameStates.PLAYER_DEAD:
                        inventory_index = action.get('inventory_index')
                        if inventory_index < len(player.inventory.items):
                            item = player.inventory.items[inventory_index]
                            if game_state is GameStates.SHOW_INVENTORY:
                                message_log.add_message(
                                    Message('Used ' + item.name))
                                player_turn_results.extend(
                                    player.inventory.use_item(item))
                            elif game_state is GameStates.DROP_INVENTORY:
                                message_log.add_message(
                                    Message('Dropped ' + item.name))
                                player_turn_results.extend(
                                    player.inventory.drop_item(item))
                            game_state = GameStates.ENEMIES_TURN

                    elif action.get(
                            'move') and game_state is GameStates.PLAYER_TURN:
                        dx, dy = action.get('move')
                        to_x, to_y = player.x + dx, player.y + dy
                        if game_map.walkable(to_x, to_y):
                            target = get_blocking_entities_at_location(
                                entities, to_x, to_y)
                            if target:
                                player_turn_results.extend(
                                    player.fighter.attack(target))
                            else:
                                player.move(dx, dy)
                                fov_recompute = True
                            # end our turn
                            game_state = GameStates.ENEMIES_TURN

                    elif action.get(
                            'move2') and game_state is GameStates.PLAYER_TURN:
                        to_x = player.x
                        to_y = player.y
                        if action.get('move2') == 'forward':
                            to_x += int(math.sin(player_rot) * 1.5)
                            to_y += int(math.cos(player_rot) * 1.5)
                        elif action.get('move2') == 'rearward':
                            to_x -= int(math.sin(player_rot) * 1.5)
                            to_y -= int(math.cos(player_rot) * 1.5)

                        if game_map.walkable(to_x, to_y):
                            target = get_blocking_entities_at_location(
                                entities, to_x, to_y)
                            if target:
                                player_turn_results.extend(
                                    player.fighter.attack(target))
                            else:
                                player.x = to_x
                                player.y = to_y
                                fov_recompute = True
                            # end our turn
                            game_state = GameStates.ENEMIES_TURN

                    elif action.get(
                            'turn') and game_state is GameStates.PLAYER_TURN:
                        dir = action.get('turn')
                        if dir == 'left':
                            player_rot += math.pi / 4.0
                        elif dir == 'right':
                            player_rot -= math.pi / 4.0
                        rerender_viewport = True
                # end_switch event.type

                # process player's turn results
                for ptr in player_turn_results:
                    message = ptr.get('message')
                    dead_entity = ptr.get('dead')

                    if message:
                        message_log.add_message(message)
                    if dead_entity:
                        if dead_entity == player:
                            message, game_state = kill_player(player)
                        else:
                            message = kill_monster(dead_entity)
                        message_log.add_message(message)
                    if ptr.get('item_added'):
                        entities.remove(ptr.get('item_added'))
                    if ptr.get('item_dropped'):
                        entities.append(ptr.get('item_dropped'))
                # end_for player_turn_results

                # run the enemy turn
                if game_state is GameStates.ENEMIES_TURN:
                    for entity in entities:
                        if entity.ai:
                            enemy_turn_results = entity.ai.take_turn(
                                player, game_map, entities)

                            for etr in enemy_turn_results:
                                message = etr.get('message')
                                dead_entity = etr.get('dead')

                                if message:
                                    message_log.add_message(message)
                                if dead_entity:
                                    if dead_entity is player:
                                        message, game_state = kill_player(
                                            player)
                                    else:
                                        message = kill_monster(dead_entity)
                                    message_log.add_message(message)
                                    if game_state is GameStates.PLAYER_DEAD:
                                        break
                            if game_state is GameStates.PLAYER_DEAD:
                                break
                    else:
                        game_state = GameStates.PLAYER_TURN
                # endif enemy turn

                if fov_recompute:
                    game_map.recompute_fov(player.x, player.y, fov_radius,
                                           fov_light_walls, fov_algorithm)

                # draw each part of the screen
                render_viewport(
                    root_console, viewport_console, 0, 0, viewport_width,
                    viewport_height, game_map, entities, colours, player.x,
                    player.y, player_rot, fov_radius, rerender_viewport
                    or game_state is GameStates.ENEMIES_TURN, wall_texture)
                render_map(root_console, map_console, game_map, entities,
                           map_x, map_y, colours, fov_recompute)
                # TODO: extend render_menu to accept a top-left co-ordinate (start_x, start_y)
                render_menu(root_console, player, screen_width, screen_height,
                            game_state)

                fps = 1.0 / (perf_counter() - time_start)
                render_panel(root_console, panel_console, entities, player,
                             game_map, message_log, bar_width, panel_width,
                             panel_height, panel_x, panel_y, mouse, fps)
                time_start = perf_counter()

                tcod.console_flush()
                clear_all(map_console, entities)
                fov_recompute = False
예제 #28
0
def main():
    screen_width = 190
    screen_height = 100

    bar_width = 20
    panel_height = 7
    panel_y = screen_height - panel_height  # panel y informs the y axis of
    # of the panel for both message log
    # and health bar

    message_x = bar_width + 2  # message x informs the x axis
    message_width = screen_width - bar_width - 2  # of the message
    message_height = panel_height - 1

    map_width = 170
    map_height = 80

    room_max_size = 20
    room_min_size = 8
    max_rooms = 100

    fov_algorithm = 0  # shape of pov
    fov_light_walls = True  #if Walls will light or not
    fov_radius = 15

    max_monsters_per_room = 4

    colors = {
        "dark_wall": libtcod.Color(127, 127, 127),
        "dark_ground": libtcod.Color(127, 101, 63),
        "light_walls": libtcod.Color(127, 137, 127),
        "light_ground": libtcod.Color(127, 110, 63)
    }

    fighter_component = Fighter(hp=(randint(100, 200)),
                                defense=(randint(0, 3)),
                                power=(randint(20, 40)))
    player = Entity(0,
                    0,
                    "@",
                    libtcod.green,
                    "Player",
                    blocks=True,
                    render_order=RenderOrder.ACTOR,
                    fighter=fighter_component)
    entities = [player]

    libtcod.console_set_custom_font(
        "arial10x10.png",
        libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD)

    libtcod.console_init_root(screen_width, screen_height, "Ork Brawl", False)

    con = libtcod.console_new(screen_width, screen_height)
    panel = libtcod.console_new(screen_width, panel_height)

    game_map = GameMap(map_width, map_height)
    game_map.make_map(max_rooms, room_min_size, room_max_size, map_width,
                      map_height, player, entities, max_monsters_per_room)

    fov_recompute = True
    #Because FOV doesn't need to be computed every turn (standing still), only need when moving to recompute
    #True by default because it needs to be computed when the game start

    fov_map = initialize_fov(
        game_map)  # This call function and store result in fov_map

    message_log = MessageLog(message_x, message_width, message_height)

    test = Message(
        "You wake up naked and angry with an urge to kill 'someting' ",
        libtcod.red)
    message = test
    message_log.add_message(message)

    key = libtcod.Key()
    mouse = libtcod.Mouse()

    game_state = GameStates.PLAYERS_TURN

    while not libtcod.console_is_window_closed():
        libtcod.sys_check_for_event(
            libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, key, mouse)

        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, fov_radius,
                          fov_light_walls, fov_algorithm)

        render_all(con, panel, entities, player, game_map, fov_map,
                   fov_recompute, message_log, screen_width, screen_height,
                   bar_width, panel_height, panel_y, mouse, colors)

        fov_recompute = False  # in theory doesn't matter, can remove code but its good practise to
        # to switch it off when you are not using it

        libtcod.console_flush()

        clear_all(con, entities)

        action = handle_keys(key)

        move = action.get("move")
        exit = action.get("exit")
        fullscreen = action.get("fullscreen")

        player_turn_results = []

        if move and game_state == GameStates.PLAYERS_TURN:
            dx, dy = move
            destination_x = player.x + dx
            destination_y = player.y + dy

            if not game_map.is_blocked(destination_x, destination_y):
                target = get_blocking_entities_at_location(
                    entities, destination_x, destination_y)
                # return entity or 'None' hence target=entity
                if target:
                    attack_results = player.fighter.attack(target)
                    player_turn_results.extend(attack_results)

                else:
                    player.move(dx, dy)

                    fov_recompute = True  # will be in False due to game loop above

                game_state = GameStates.ENEMY_TURN

        if exit:
            return True  # This could be either return False or break
            # returns a value to main hence ending the programme.

        if fullscreen:
            libtcod.console_set_fullscreen(not libtcod.console_is_fullscreen())

        for player_turn_result in player_turn_results:
            message = player_turn_result.get("message")
            dead_entity = player_turn_result.get("dead")

            if message:
                message_log.add_message(message)

            if dead_entity:
                if dead_entity == player:
                    message, game_state = kill_player(dead_entity)
                else:
                    message = kill_monster(dead_entity)

                message_log.add_message(message)

        if game_state == GameStates.ENEMY_TURN:
            for entity in entities:
                if entity.ai:
                    enemy_turn_results = entity.ai.take_turn(
                        player, fov_map, game_map, entities)

                    for enemy_turn_result in enemy_turn_results:
                        message = enemy_turn_result.get("message")
                        dead_entity = enemy_turn_result.get("dead")

                        if message:
                            message_log.add_message(message)

                        if dead_entity:
                            if dead_entity == player:
                                message, game_state = kill_player(dead_entity)
                            else:
                                message = kill_monster(dead_entity)

                            message_log.add_message(message)

                            if game_state == GameStates.PLAYER_DEAD:
                                break

                    if game_state == GameStates.PLAYER_DEAD:
                        break

            else:
                game_state = GameStates.PLAYERS_TURN
예제 #29
0
def main():
    screen_width = 80
    screen_height = 50
    bar_width = 20
    panel_height = 7
    panel_y = screen_height - panel_height
    message_x = bar_width + 2
    message_width = screen_width - bar_width - 2
    message_height = panel_height - 1
    map_width = 80
    map_height = 43

    room_max_size = 10
    room_min_size = 6
    max_rooms = 30

    fov_algorithm = 0
    fov_light_walls = True
    fov_radius = 10

    max_monsters_per_room = 3
    max_items_per_room = 2

    colors = {
        'dark_wall' : libtcod.Color(0, 0, 100),
        'dark_ground' : libtcod.Color(50, 50, 150),
        'light_wall' : libtcod.Color(130, 110, 50),
        'light_ground' : libtcod.Color(200, 180, 50)
    }

    fighter_component = Fighter(hp=30, defense=2, power=5)
    inventory_component = Inventory(26)

    player = Entity(0, 0, '@', libtcod.white, 'Player', blocks=True, render_order=RenderOrder.ACTOR,
                    fighter=fighter_component, inventory=inventory_component)
    entities = [player]

    libtcod.console_set_custom_font('arial10x10.png', libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD)

    libtcod.console_init_root(screen_width, screen_height, 'libtcod tutorial revised', False)

    con = libtcod.console_new(screen_width, screen_height)
    panel = libtcod.console_new(screen_width, panel_height)

    game_map = GameMap(map_width, map_height)
    game_map.make_map(max_rooms, room_min_size, room_max_size, map_width, map_height, player, entities, max_monsters_per_room, max_items_per_room)

    fov_recompute = True
    fov_map = initialize_fov(game_map)
    message_log = MessageLog(message_x, message_width, message_height)

    key = libtcod.Key()
    mouse = libtcod.Mouse()

    game_state = GameStates.PLAYERS_TURN
    previous_game_state =  game_state

    while not libtcod.console_is_window_closed():
        libtcod.sys_check_for_event(libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, key, mouse)
        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, fov_radius, fov_light_walls, fov_algorithm)
        render_all(con, panel, entities, player, game_map, fov_map, fov_recompute, message_log, screen_width, screen_height,
                   bar_width, panel_height, panel_y, mouse, colors, game_state)
        fov_recompute = False
        libtcod.console_flush()
        clear_all(con, entities)

        action = handle_keys(key, game_state)

        move = action.get('move')
        pickup = action.get('pickup')
        show_inventory = action.get('show_inventory')
        drop_inventory = action.get('drop_inventory')
        inventory_index = action.get('inventory_index')
        exit = action.get('exit')
        fullscreen = action.get('fullscreen')

        player_turn_results = []

        if move and game_state == GameStates.PLAYERS_TURN:
            dx, dy = move
            destination_x = player.x + dx
            destination_y = player.y + dy

            if not game_map.is_blocked(destination_x, destination_y):
                target = get_blocking_entities_at_location(entities, destination_x, destination_y)

                if target:
                    attack_results = player.fighter.attack(target)
                    player_turn_results.extend(attack_results)
                else:
                    player.move(dx, dy)
                    
                    fov_recompute = True
                
                game_state = GameStates.ENEMY_TURN
        elif pickup and game_state == GameStates.PLAYERS_TURN:
            for entity in entities:
                if entity.item and entity.x == player.x and entity.y == player.y:
                    pickup_results = player.inventory.add_item(entity)
                    player_turn_results.extend(pickup_results)
                    break
            else:
                message_log.add_message(Message('There is nothing to pickup here.', libtcod.yellow))

        if show_inventory:
            previous_game_state = game_state
            game_state = GameStates.SHOW_INVENTORY

        if drop_inventory:
            previous_game_state = game_state
            game_state = GameStates.DROP_INVENTORY

        if inventory_index is not None and previous_game_state != GameStates.PLAYER_DEAD and inventory_index < len(
            player.inventory.items):
            item = player.inventory.items[inventory_index]

            if game_state == GameStates.SHOW_INVENTORY:
                player_turn_results.extend(player.inventory.use(item))
            elif game_state == GameStates.DROP_INVENTORY:
                player_turn_results.extend(player.inventory.drop_item(item))
        if exit:
            if game_state in (GameStates.SHOW_INVENTORY, GameStates.DROP_INVENTORY):
                game_state = previous_game_state
            else:
                return True
        
        if fullscreen:
            libtcod.console_set_fullscreen(not libtcod.console_is_fullscreen())

        for player_turn_result in player_turn_results:
            message = player_turn_result.get('message')
            dead_entity = player_turn_result.get('dead')
            item_added = player_turn_result.get('item_added')
            item_consumed = player_turn_result.get('consumed')
            item_dropped = player_turn_result.get('item_dropped')

            if message:
                message_log.add_message(message)

            if dead_entity:
                if dead_entity == player:
                    message, game_state = kill_player(dead_entity)
                else:
                    message = kill_monster(dead_entity)

                message_log.add_message(message)

            if item_added:
                entities.remove(item_added)
                game_state = GameStates.ENEMY_TURN

            if item_consumed:
                game_state = GameStates.ENEMY_TURN

            if item_dropped:
                entities.append(item_dropped)
                game_state = GameStates.ENEMY_TURN

        if game_state == GameStates.ENEMY_TURN:
            for entity in entities:
                if entity.ai:
                    enemy_turn_results = entity.ai.take_turn(player, fov_map, game_map, entities)

                    for enemy_turn_result in enemy_turn_results:
                        message = enemy_turn_result.get('message')
                        dead_entity = enemy_turn_result.get('dead')

                        if message:
                            message_log.add_message(message)
                        
                        if dead_entity:
                            if dead_entity == player:
                                message, game_state = kill_player(dead_entity)
                            else:
                                message = kill_monster(dead_entity)

                            message_log.add_message(message)

                        if game_state == GameStates.PLAYER_DEAD:
                            break
                    
                    if game_state == GameStates.PLAYER_DEAD:
                        break

            else:
                game_state = GameStates.PLAYERS_TURN
예제 #30
0
def main():
    screen_width = 80
    screen_height = 50
    bar_width = 20
    panel_height = 7
    panel_y = screen_height - panel_height
    message_x = bar_width + 2
    message_width = screen_width - bar_width - 2
    message_height = panel_height - 1
    map_width = 80
    map_height = 43
    room_max_size = 10
    room_min_size = 6
    max_rooms = 30
    fov_algorithm = 0
    fov_light_walls = True
    fov_radius = 10

    max_monsters_per_room = 3

    colors = {
        "dark_wall": lcod.Color(0, 0, 100),
        "dark_ground": lcod.Color(50, 50, 150),
        "light_wall": lcod.Color(130, 110, 50),
        "light_ground": lcod.Color(200, 180, 50),
    }

    fighter_component = Fighter(hp=12, defense=3, power=5)
    player = Entity(0,
                    0,
                    '@',
                    lcod.white,
                    "Player", [],
                    blocks=True,
                    render_order=RenderOrder.ACTOR,
                    fighter=fighter_component)
    entities = [player]

    lcod.console_set_custom_font(
        "arial10x10.png", lcod.FONT_TYPE_GRAYSCALE | lcod.FONT_LAYOUT_TCOD)

    lcod.console_init_root(screen_width, screen_height, "TicTacRogue", False)

    con = lcod.console_new(screen_width, screen_height)
    panel = lcod.console_new(screen_width, panel_height)

    game_map = GameMap(map_width, map_height)
    game_map.make_map(max_rooms, room_min_size, room_max_size, map_width,
                      map_height, player, entities, max_monsters_per_room)

    fov_recompute = True
    fov_map = initialize_fov(game_map)

    message_log = MessageLog(message_x, message_width, message_height)

    key = lcod.Key()
    mouse = lcod.Mouse()

    game_state = GameStates.PLAYER_TURN
    power_armor = PowerArmor(player)

    while not lcod.console_is_window_closed():
        lcod.sys_check_for_event(lcod.EVENT_KEY_PRESS, key, mouse)

        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, fov_radius)

        render_all(con, panel, entities, player, game_map, fov_map,
                   fov_recompute, message_log, screen_width, screen_height,
                   bar_width, panel_height, panel_y, colors)

        lcod.console_flush()

        clear_all(con, entities)

        action = handle_keys(key)

        move = action.get("move")
        exit = action.get("exit")
        cast = action.get("cast")
        fullscreen = action.get("fullscreen")

        player_turn_results = []

        if cast and game_state == GameStates.PLAYER_TURN:
            if power_armor not in player.effects:
                print("Adding effects to list")
                player.effects.append(power_armor)

            player.evaluate_effects()
            game_state = GameStates.ENEMY_TURN

        elif move and game_state == GameStates.PLAYER_TURN:
            dx, dy = move
            destination_x = player.x + dx
            destination_y = player.y + dy

            if not game_map.is_blocked(destination_x, destination_y):
                target = get_blocking_entities_at_location(
                    entities, destination_x, destination_y)

                if target:
                    attack_results = player.fighter.attack(target)
                    player_turn_results.extend(attack_results)
                else:
                    player.move(dx, dy)
                    fov_recompute = True

                player.evaluate_effects()
                player.clean_effects()
                game_state = GameStates.ENEMY_TURN

        if exit:
            return True

        if fullscreen:
            lcod.console_set_fullscreen(not lcod.console_is_fullscreen())

        for player_turn_result in player_turn_results:
            message = player_turn_result.get("message")
            dead_entity = player_turn_result.get("dead")

            if message:
                message_log.add_message(message)

            if dead_entity:
                if dead_entity == player:
                    message, game_state = kill_player(dead_entity)
                else:
                    message = kill_monster(dead_entity)

                message_log.add_message(message)

        if game_state == GameStates.ENEMY_TURN:
            for entity in entities:
                if entity.ai:
                    enemy_turn_results = entity.ai.take_turn(
                        player, fov_map, game_map, entities)

                    for enemy_turn_result in enemy_turn_results:
                        message = enemy_turn_result.get("message")
                        dead_entity = enemy_turn_result.get("dead")

                        if message:
                            message_log.add_message(message)
                        if dead_entity:
                            if dead_entity == player:
                                message, game_state = kill_player(dead_entity)
                            else:
                                message = kill_monster(dead_entity)

                            message_log.add_message(message)

                        if game_state == GameStates.PLAYER_DEAD:
                            break

                    if game_state == GameStates.PLAYER_DEAD:
                        break

            else:
                game_state = GameStates.PLAYER_TURN