Exemple #1
0
    def evaluate_dead_entity(self, dead_entity):
        if not dead_entity:
            return

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

        self.message_log.add_message(message)
Exemple #2
0
def process_turn(player, enemy_turn_results, message_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(dead_entity)
            else:
                message = kill_monster(dead_entity)
            message_log.add_message(message)

            if game_state == GameStates.PLAYER_DEAD:
                break
def play_game(player, entities, game_map, message_log, game_state, con, panel,
              constants):
    fov_recompute = True

    fov_map = initialize_fov(game_map)

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

    if not game_state == GameStates.PLAYER_DEAD:
        game_state = GameStates.PLAYERS_TURN

    begin_player_turn = True

    previous_game_state = game_state

    targeting_item = None

    if not game_state == GameStates.PLAYER_DEAD:
        PLAYERDEADSTATE = False
    else:
        PLAYERDEADSTATE = True

    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'])

        render_all(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'], constants['kill_count'], game_state,
                   constants['wall_tile'], constants['floor_tile'])

        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')
        wait = action.get('wait')
        pickup = action.get('pickup')
        show_inventory = action.get('show_inventory')
        drop_inventory = action.get('drop_inventory')
        drop_equipment = action.get('drop_equipment')
        show_equipment_inventory = action.get('show_equipment_inventory')
        show_bag = action.get('show_bag')
        inventory_index = action.get('inventory_index')
        equipment_inventory_index = action.get('equipment_inventory_index')
        take_stairs = action.get('take_stairs')
        level_up = action.get('level_up')
        show_character_screen = action.get('show_character_screen')
        show_help_menu = action.get('show_help_menu')
        exit = action.get('exit')
        exit_quit_menu = action.get('exit_quit_menu')
        fullscreen = action.get('fullscreen')
        cast_magic_wand = action.get('cast_magic_wand')
        shoot_bow = action.get('shoot_bow')
        drop_menu = action.get('drop_menu')
        sell_menu = action.get('sell_menu')
        sell_equipment_menu = action.get('sell_equipment_menu')
        buy_menu = action.get('buy_menu')
        buy_equipment_menu = action.get('buy_equipment_menu')
        shop_menu = action.get('shop_menu')
        shop_menu_index = action.get('shop_menu_index')
        shop_equipment_menu_index = action.get('shop_equipment_menu_index')

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

        player_turn_results = []

        if begin_player_turn and game_state == GameStates.PLAYERS_TURN:
            begin_player_turn = False

            if player.fighter.status:
                player_turn_results.extend(player.fighter.status.update())

        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,
                                                           constants,
                                                           entities=entities)
                    #playsound('sounds/attack.m4a', block=False)
                    player_turn_results.extend(attack_results)
                else:
                    player.move(dx, dy)

                    fov_recompute = True

                game_state = GameStates.ENEMY_TURN

        elif wait:
            game_state = GameStates.ENEMY_TURN

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

                    break

                elif entity.item and entity.x == player.x and entity.y == player.y:
                    pickup_results = player.equipment_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 show_equipment_inventory:
            previous_game_state = game_state
            game_state = GameStates.SHOW_EQUIPMENT_INVENTORY

        if drop_inventory:
            previous_game_state = game_state
            game_state = GameStates.DROP_INVENTORY

        if drop_equipment:
            previous_game_state = game_state
            game_state = GameStates.DROP_EQUIPMENT

        if show_bag:
            previous_game_state = game_state
            game_state = GameStates.SHOW_BAG

        if drop_menu:
            previous_game_state = game_state
            game_state = GameStates.DROP_MENU

        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))
            elif game_state == GameStates.SELL_MENU:
                player_turn_results.extend(
                    player.inventory.sell(item, game_state))

        if equipment_inventory_index is not None and previous_game_state != GameStates.PLAYER_DEAD and equipment_inventory_index < len(
                player.equipment_inventory.items):
            equip_item = player.equipment_inventory.items[
                equipment_inventory_index]

            if game_state == GameStates.SHOW_EQUIPMENT_INVENTORY:
                player_turn_results.extend(
                    player.equipment_inventory.use(equip_item))
            elif game_state == GameStates.DROP_EQUIPMENT:
                player_turn_results.extend(
                    player.equipment_inventory.drop_item(equip_item))
            elif game_state == GameStates.SELL_EQUIPMENT_MENU:
                player_turn_results.extend(
                    player.equipment_inventory.sell(equip_item, game_state))

        if shop_menu_index is not None and previous_game_state != GameStates.PLAYER_DEAD:
            item = game_map.shop_items[shop_menu_index]

            if game_state == GameStates.BUY_MENU:
                player_turn_results.extend(
                    player.inventory.buy(item, game_state))

        if shop_equipment_menu_index is not None and previous_game_state != GameStates.PLAYER_DEAD:
            item = game_map.shop_equipment_items[shop_equipment_menu_index]

            if game_state == GameStates.BUY_EQUIPMENT_MENU:
                player_turn_results.extend(
                    player.equipment_inventory.buy(item, game_state))

        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,
                                                   constants)
                    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 cast_magic_wand and game_state == GameStates.PLAYERS_TURN:
            wand = player.inventory.search("Magic Wand")
            staff = player.inventory.search("Wizard Staff")
            if wand is None and staff is None:
                message_log.add_message(
                    Message("You cannot cast magic without a magic item!",
                            libtcod.orange))
            else:
                player_turn_results.extend(
                    player.inventory.use(wand,
                                         entities=entities,
                                         fov_map=fov_map))

                game_state = GameStates.ENEMY_TURN

        if shoot_bow and game_state == GameStates.PLAYERS_TURN:
            bow = player.inventory.search("Long Bow")
            arrow = player.inventory.search("Arrow")
            if bow is None and arrow is None:
                message_log.add_message(
                    Message(
                        "You don't have anything to shoot with at this time!",
                        libtcod.orange))
            elif bow is None and arrow is not None:
                message_log.add_message(
                    Message("You cannot shoot an arrow without a bow!",
                            libtcod.orange))
            elif bow is not None and arrow is None:
                message_log.add_message(
                    Message("You need arrows to use your bow", libtcod.orange))
            else:
                player_turn_results.extend(
                    player.inventory.use(bow,
                                         entities=entities,
                                         fov_map=fov_map))

                game_state = GameStates.ENEMY_TURN

        if level_up:
            if level_up == 'hp':
                player.fighter.base_max_hp += 20
                player.fighter.hp += 20
                message_log.add_message(
                    Message("You leveled up your HP!", libtcod.light_cyan))
            elif level_up == 'str':
                player.fighter.base_power += 1
                message_log.add_message(
                    Message("You leveled up your ATTACK!", libtcod.light_cyan))
            elif level_up == 'def':
                player.fighter.base_defense += 1
                message_log.add_message(
                    Message("You leveled up your DEFENSE!",
                            libtcod.light_cyan))
            elif level_up == 'mgk':
                player.fighter.base_magic += 1
                message_log.add_message(
                    Message("You leveled up your MAGIC!", libtcod.light_cyan))
            elif level_up == 'mgk_def':
                player.fighter.base_magic_defense += 1
                message_log.add_message(
                    Message("You leveled up your MAGIC RESISTANCE!",
                            libtcod.light_cyan))

            game_state = previous_game_state

        if show_character_screen:
            previous_game_state = game_state
            game_state = GameStates.CHARACTER_SCREEN

        if show_help_menu:
            previous_game_state = game_state
            game_state = GameStates.HELP_MENU

        if sell_menu:
            previous_game_state = game_state
            game_state = GameStates.SELL_MENU

        if sell_equipment_menu:
            previous_game_state = game_state
            game_state = GameStates.SELL_EQUIPMENT_MENU

        if buy_menu:
            previous_game_state = game_state
            game_state = GameStates.BUY_MENU

        if buy_equipment_menu:
            previous_game_state = game_state
            game_state = GameStates.BUY_EQUIPMENT_MENU

        if shop_menu:
            previous_game_state = game_state
            game_state = GameStates.SHOP_MENU

        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.DROP_EQUIPMENT,
                              GameStates.CHARACTER_SCREEN,
                              GameStates.HELP_MENU,
                              GameStates.SHOW_EQUIPMENT_INVENTORY,
                              GameStates.SELL_MENU, GameStates.BUY_MENU,
                              GameStates.SELL_EQUIPMENT_MENU,
                              GameStates.BUY_EQUIPMENT_MENU):
                game_state = previous_game_state
            elif game_state == GameStates.TARGETING:
                player_turn_results.append({'targeting_cancelled': True})
            elif game_state == GameStates.SHOW_BAG:
                if PLAYERDEADSTATE == True:
                    game_state = GameStates.PLAYER_DEAD
                else:
                    game_state = GameStates.PLAYERS_TURN
            elif game_state == GameStates.SHOP_MENU:
                if PLAYERDEADSTATE == True:
                    game_state = GameStates.PLAYER_DEAD
                else:
                    game_state = GameStates.PLAYERS_TURN
            elif game_state == GameStates.PLAYERS_TURN:
                game_state = GameStates.QUIT_MENU
            elif game_state == GameStates.DROP_MENU:
                game_state = GameStates.PLAYERS_TURN
            else:
                save_game(player, entities, game_map, message_log, game_state)

                return True

        if exit_quit_menu:
            if game_state == GameStates.QUIT_MENU:
                game_state = previous_game_state

        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')
            equipment_item_added = player_turn_result.get(
                'equipment_item_added')
            item_consumed = player_turn_result.get('consumed')
            equipment_consumed = player_turn_result.get('equipment_consumed')
            item_dropped = player_turn_result.get('item_dropped')
            loot_dropped = player_turn_result.get('loot_dropped')
            staff_used = player_turn_result.get('staff_used')
            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')
            item_bought = player_turn_result.get('item_bought')
            equipment_bought = player_turn_result.get('equipment_bought')
            end_turn = player_turn_result.get('end_turn')

            if message:
                message_log.add_message(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 prowess grows stronger! You reached level {0}!"
                            .format(player.level.current_level),
                            libtcod.yellow))
                    previous_game_state = game_state
                    game_state = GameStates.LEVEL_UP

            if dead_entity:
                if dead_entity == player:
                    PLAYERDEADSTATE = True
                    message, game_state = kill_player(dead_entity, constants)
                    message_log.add_message(message)
                else:
                    monster_name = ''
                    monster_name = dead_entity.name
                    message = kill_monster(dead_entity, player, constants)
                    constants['kill_count'] += 1
                    message_log.add_message(message)

                    while dead_entity.equipment_inventory.items:
                        item = dead_entity.equipment_inventory.items[0]
                        dead_entity.equipment_inventory.loot_item(item)
                        entities.append(item)
                        message_log.add_message(
                            Message(
                                "The {0} dropped the {1}.".format(
                                    monster_name, item.name), libtcod.yellow))

                    while dead_entity.inventory.items:
                        item = dead_entity.inventory.items[0]
                        dead_entity.inventory.loot_item(item)
                        entities.append(item)
                        message_log.add_message(
                            Message(
                                "The {0} dropped the {1}.".format(
                                    monster_name, item.name), libtcod.yellow))

            if item_added:
                entities.remove(item_added)

                game_state = GameStates.ENEMY_TURN

            if equipment_item_added:
                entities.remove(equipment_item_added)

                game_state = GameStates.ENEMY_TURN

            if item_consumed:
                game_state = GameStates.ENEMY_TURN

            if item_bought:
                game_map.shop_items.remove(item_bought)

                game_state = GameStates.ENEMY_TURN

            if equipment_bought:
                game_map.shop_equipment_items.remove(equipment_bought)

                game_state = GameStates.ENEMY_TURN

            if equipment_consumed:
                game_state = GameStates.ENEMY_TURN

            if staff_used:
                game_state = GameStates.ENEMY_TURN

            if end_turn:
                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 loot_dropped:
                entities.append(loot_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:
            fov_recompute = True
            for entity in entities:
                if entity.ai:
                    if entity.fighter.status:
                        entity.fighter.status.update()

                    enemy_turn_results = entity.ai.take_turn(
                        player, fov_map, game_map, entities, constants)

                    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:
                                PLAYERDEADSTATE = True
                                message, game_state = kill_player(
                                    dead_entity, constants)
                                message_log.add_message(message)
                            else:
                                monster_name = ''
                                monster_name = dead_entity.name
                                message = kill_monster(dead_entity, player,
                                                       constants)
                                constants['kill_count'] += 1
                                message_log.add_message(message)

                                while dead_entity.equipment_inventory.items:
                                    item = dead_entity.equipment_inventory.items[
                                        0]
                                    dead_entity.equipment_inventory.loot_item(
                                        item)
                                    entities.append(item)
                                    message_log.add_message(
                                        Message(
                                            "The {0} dropped the {1}.".format(
                                                monster_name, item.name),
                                            libtcod.yellow))

                                while dead_entity.inventory.items:
                                    item = dead_entity.inventory.items[0]
                                    dead_entity.inventory.loot_item(item)
                                    entities.append(item)
                                    message_log.add_message(
                                        Message(
                                            "The {0} dropped the {1}.".format(
                                                monster_name, item.name),
                                            libtcod.yellow))

                            if game_state == GameStates.PLAYER_DEAD:
                                break
                    if game_state == GameStates.PLAYER_DEAD:
                        break
            else:
                game_state = GameStates.PLAYERS_TURN
                begin_player_turn = True
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
def play_game(player, entities, game_map, message_log, game_state, con, panel,
              constants):
    fov_recompute = True

    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

    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'])

        render_all(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)

        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')
        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')
        take_stairs = action.get('take_stairs')
        level_up = action.get('level_up')
        show_character_screen = action.get('show_character_screen')
        exit = action.get('exit')
        fullscreen = action.get('fullscreen')

        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 wait:
            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,
                                                   constants)
                    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:
                save_game(player, entities, game_map, message_log, game_state)

                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')
            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 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 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:

                    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
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
Exemple #7
0
def main():
	screen_width = 80
	screen_height = 50
	map_width = 80
	map_height = 45

	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, '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, max_monsters_per_room)

	fov_recompute = True

	fov_map = initialize_fov(game_map)

	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, key, mouse)

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

		render_all(con, entities, player, game_map, fov_map, fov_recompute, screen_width, screen_height, colors)

		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:
				print(message)

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

				print(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:
							print(message)

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

							print(message)

							if game_state == GameStates.PLAYER_DEAD:
								break

					if game_state == GameStates.PLAYER_DEAD:
						break

			else:
				game_state = GameStates.PLAYERS_TURN
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
Exemple #9
0
def play_game(player, entities, game_map, message_log, game_state, con, panel,
              constants):
    fov_recompute = True

    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

    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'])

        render_all(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)

        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')
        aim_weapon = action.get('aim_weapon')
        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')
        take_stairs = action.get('take_stairs')
        show_character_screen = action.get('show_character_screen')
        exit = action.get('exit')
        level_up = action.get('level_up')
        fullscreen = action.get('fullscreen')
        exit_menu = action.get('exit_menu')

        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 dx == 0 and dy == 0:
                    player.move(dx, dy)

                    fov_recompute = True
                elif target:  # ATTACK!

                    if player.equipment.power_bonus == 4:
                        attack_results = player.fighter.basic_bow_attack(
                            target)
                        player_turn_results.extend(attack_results)

                    else:
                        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 aim_weapon and game_state == GameStates.PLAYERS_TURN:  # ALSO ATTACK! Working on this at the moment
            if player.equipment.power_bonus == 4 and game_state == GameStates.PLAYERS_TURN:
                message_log.add_message(
                    Message(
                        'Left click a tile to fire at it or right click to cancel!',
                        libtcod.yellow))
                game_state = GameStates.AIMING
            else:
                message_log.add_message(
                    Message('You do not have a ranged weapon equipped!',
                            libtcod.yellow))

        elif wait:
            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,
                                                   constants)
                    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 game_state == GameStates.AIMING:
            if left_click:
                target_x, target_y = left_click
                coordinates = target_x, target_y  # OKAY NOW WHAT THE F**K I DONT UNDESTAND WHY THIS WORKS OR HOW THE
                # VARIABLES GET FROM HERE TO THE FUNCTION I NEED THEM I MEAN JESUS CHRIST I JUST WOUND UP WITH THIS
                # ARRANGEMENT BY F*****G AROUND I MEAN IT WORKS BUT SERIOUSLY I DONT UNDERSTAND WHY THIS WORKS
                player_turn_results.append({'fire_weapon': True})
            elif right_click:
                player_turn_results.append({'targeting_cancelled': True})

        if exit_menu:
            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})

        if exit:
            save_game(player, entities, game_map, message_log, game_state)

            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')
            fire_weapon = player_turn_result.get('fire_weapon')
            item_added = 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 fire_weapon:
                destination_x, destination_y = coordinates
                target = get_blocking_entities_at_location(
                    entities, destination_x, destination_y)
                try:
                    if target == player:
                        message_log.add_message(
                            Message(
                                'No hitting yourself. Targeting cancelled.',
                                libtcod.yellow))
                        game_state = previous_game_state
                    elif target.ai and libtcod.map_is_in_fov(
                            fov_map, target.x, target.y):
                        attack_results = player.fighter.basic_bow_attack(
                            target)
                        player_turn_results.extend(attack_results)
                        game_state = GameStates.ENEMY_TURN
                    elif target.ai and not libtcod.map_is_in_fov(
                            fov_map, target.x, target.y):
                        message_log.add_message(
                            Message(
                                'That cannot be targeted. Targeting cancelled.',
                                libtcod.yellow))
                        game_state = previous_game_state
                except:
                    message_log.add_message(
                        Message(
                            'That cannot be targeted. Targeting cancelled.',
                            libtcod.yellow))
                    game_state = previous_game_state

            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 config.win == True:
                    game_state = GameStates.PLAYER_DEAD

            if game_state == GameStates.PLAYER_DEAD:
                break

            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 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 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 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
Exemple #10
0
def play_game(player, entities, game_map, message_log, game_state, con, panel,
              constants):
    fov_recompute = True
    fov_map = initialize_fov(game_map)

    previous_game_state = game_state

    targeting_item = None

    message_log.add_message(
        Message(f'You are a ghost.  You have nothing.', libtcod.white))
    message_log.add_message(
        Message(f'Use the arrow keys to move', libtcod.white))
    message_log.add_message(
        Message(f'Press \'p\' to possess a creature and gain its abilities...',
                libtcod.white))
    message_log.add_message(
        Message(f'(Mouse over symbols for more information)', libtcod.white))

    first_body = True
    first_inventory = True
    mouse_event = None
    while True:
        key_event = None
        left_click = None
        right_click = None
        exit_game = False

        for event in libtcod.event.get():
            #print(f"Got Event: {event.type}")
            if event.type in ("QUIT"):
                print("QUIT event: Exiting")
                raise SystemExit()
            if event.type == "KEYDOWN":
                if event.sym == libtcod.event.K_ESCAPE:
                    print(f"{event.type} K_ESCAPE: Exiting")
                    exit_game = True
                else:
                    key_event = event
                #print(f"Got Event: {event.type}: {key}")
            if event.type == "MOUSEMOTION":
                mouse_event = event
                if event.state & libtcod.event.BUTTON_LMASK:
                    left_click = mouse_event
                if event.state & libtcod.event.BUTTON_RMASK:
                    right_click = mouse_event

        if exit_game:
            break

        fov_radius = player.fighter.fov(
        ) if player.fighter else Constants.min_fov_radius
        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, fov_radius,
                          Constants.fov_light_walls, Constants.fov_algorithm)

        render_all(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_event,
                   Constants.colors, game_state)

        fov_recompute = False

        libtcod.console_flush()

        clear_all(con, entities)
        action = handle_keys(key_event, game_state)

        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')
        take_stairs = action.get('take_stairs')
        level_up = action.get('level_up')
        show_character_screen = action.get('show_character_screen')
        exit = action.get('exit')
        fullscreen = action.get('fullscreen')
        possession = action.get('possession')
        #start_test_mode = action.get('start_test_mode')
        restart = action.get('restart')

        player_turn_results = []

        if False:  # start_test_mode:
            fighter_component = Fighter(hp=30,
                                        defense=2,
                                        power=8,
                                        body='god mode',
                                        xp=100,
                                        will_power=4)
            player.fighter = fighter_component
            player.fighter.owner = player
            player.inventory = Inventory(26)
            player.equipment = Equipment()
            player.inventory.owner = player
            player.equipment.owner = player
            equippable_component = Equippable(EquipmentSlots.MAIN_HAND,
                                              power_bonus=1)
            item = Entity(player.x,
                          player.y,
                          '/',
                          libtcod.red,
                          'Small Dagger',
                          equippable=equippable_component)
            entities.append(item)

        if restart:
            player, entities, game_map, message_log, game_state = get_game_variables(
                Constants)
            game_state = GameStates.PLAYERS_TURN
            fov_map = initialize_fov(game_map)
            fov_recompute = True
            con.clear()

        if possession:
            if not player.fighter:
                for entity in entities:
                    if entity.fighter and entity.x == player.x and entity.y == player.y:
                        if player.level.current_level >= entity.fighter.will_power:
                            message_log.add_message(
                                Message(
                                    f"You take control of the {entity.name}'s body...",
                                    libtcod.white))
                            if first_body:
                                message_log.add_message(
                                    Message(f'(Press p to release it)',
                                            libtcod.gray))
                                first_body = False
                            if entity.inventory and first_inventory:
                                message_log.add_message(
                                    Message(
                                        f'(Press g to Get items, i for Inventory)',
                                        libtcod.gray))
                                first_inventory = False
                            player.fighter = entity.fighter
                            player.inventory = entity.inventory
                            player.equipment = entity.equipment
                            player.possessed_entity = entity
                            player.fighter.owner = player
                            player.char = entity.char
                            player.render_order = entity.render_order
                            player.name = f'Ghost/{entity.name}'
                            entities.remove(entity)
                        else:
                            message_log.add_message(
                                Message(
                                    f'The {entity.name} is too powerful for you to possess!',
                                    libtcod.yellow))

            else:
                message_log.add_message(
                    Message(
                        f'You cast your spirit out of the {player.possessed_entity.name}, leaving a shambling husk behind...',
                        libtcod.red))
                ai_component = SlowMonster()
                zombie_name = f'Zombie {player.possessed_entity.name}'
                zombie_char = player.possessed_entity.char
                zombie = Entity(player.x,
                                player.y,
                                zombie_char,
                                libtcod.desaturated_green,
                                zombie_name,
                                blocks=True,
                                render_order=RenderOrder.ACTOR,
                                fighter=player.fighter,
                                ai=ai_component,
                                inventory=player.inventory,
                                equipment=player.equipment)
                zombie.fighter.xp = 5
                zombie.fighter.owner = zombie
                entities.append(zombie)

                player.fighter = None
                player.inventory = None
                player.equipment = None
                player.char = ' '
                player.render_order = RenderOrder.GHOST
                player.name = 'Ghost'

        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 and player.fighter:
                    attack_results = player.fighter.attack(target)
                    player_turn_results.extend(attack_results)
                else:
                    player.move(dx, dy)
                    fov_recompute = True
                    over_entities = [
                        e for e in entities
                        if e.x == player.x and e.y == player.y and e != player
                    ]
                    if over_entities:
                        over_fighters = [e for e in over_entities if e.fighter]
                        over_items = [
                            e for e in over_entities if not e.fighter
                        ]
                        if over_fighters:
                            over_fighter = over_fighters[0]
                            message_log.add_message(
                                Message(
                                    f'Your shadow falls over the {over_fighter.name}...',
                                    libtcod.white))
                        elif over_items:
                            if len(over_items) == 1:
                                over_items_list = f'{over_items[0].name}'
                            elif len(over_items) == 2:
                                over_items_list = f'{over_items[1].name} and a {over_items[0].name}'
                            else:
                                over_items_list = [
                                    n.name for n in over_items[:-1]
                                ].join(', a ')
                                over_items_list += "and a {over_items[-1].name}"
                            message_log.add_message(
                                Message(f'There is a {over_items_list} here.',
                                        libtcod.white))
                            if 'Staircase' in [e.name for e in over_items
                                               ] and player.fighter:
                                message_log.add_message(
                                    Message(
                                        f'(Press enter/return to use stairs)',
                                        libtcod.gray))
                game_state = GameStates.ENEMY_TURN

        elif wait:
            game_state = GameStates.ENEMY_TURN

        elif pickup and game_state == GameStates.PLAYERS_TURN:
            if player.inventory:
                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))
            elif player.fighter:
                message_log.add_message(
                    Message('This creature cannot carry items.',
                            libtcod.yellow))
            else:
                message_log.add_message(
                    Message(
                        "You can't pick up items without a body of some kind...",
                        libtcod.yellow))

        if show_inventory:
            if player.inventory:
                previous_game_state = game_state
                game_state = GameStates.SHOW_INVENTORY
            elif player.fighter:
                message_log.add_message(
                    Message('This creature cannot carry items.',
                            libtcod.yellow))
            else:
                message_log.add_message(
                    Message('You lack a body to carry items...',
                            libtcod.yellow))

        if drop_inventory:
            previous_game_state = game_state
            game_state = GameStates.DROP_INVENTORY

        if inventory_index is not None and player.inventory 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,
                                                   constants)
                    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 player.fighter:
                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:
                save_game(player, entities, game_map, message_log, game_state)
                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')
            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 targeting_cancelled:
                game_state = previous_game_state
                message_log.add_message(
                    Message('Targeting cancelled', libtcod.yellow))

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

                message_log.add_message(message)

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

                if leveled_up:
                    message_log.add_message(
                        Message(
                            'You grow stronger! You reached level {0}'.format(
                                player.level.current_level) + '!',
                            libtcod.green))
                    message_log.add_message(
                        Message('You can now possess larger creatures...',
                                libtcod.red))

                if fighter_leveled_up:
                    previous_game_state = game_state
                    game_state = GameStates.LEVEL_UP

            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 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 targeting:
                previous_game_state = GameStates.PLAYERS_TURN
                game_state = GameStates.TARGETING

                targeting_item = targeting

                message_log.add_message(targeting_item.item.targeting_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.fighter == player.fighter:
                                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
Exemple #11
0
def main():
    SCREEN_WIDTH = 80
    SCREEN_HEIGHT = 50

    MAP_WIDTH = 80
    MAP_HEIGHT = 45

    ROOM_MAX_SIZE = 10
    ROOM_MIN_SIZE = 6
    MAX_ROOMS = 30

    fov_algorithm = 0
    fov_light_walls = True
    fov_radius = 5

    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,
                              '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, max_monsters_per_room)

    fov_recompute = True

    fov_map = initialize_fov(game_map)

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

    game_state = GameStates.PLAYERS_TURN

    # gameplay loop
    while not libtcod.console_is_window_closed():
        # this function captures new "events" - user input
        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, entities, player, game_map, fov_map, fov_recompute,
                   SCREEN_WIDTH, SCREEN_HEIGHT, colors)

        fov_recompute = False

        libtcod.console_flush()  # presents everything to screen

        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:
                print(message)

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

                print(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:
                            print(message)

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

                            print(message)

                            if game_state == GameStates.PLAYER_DEAD:
                                break

                    if game_state == GameStates.PLAYER_DEAD:
                        break

            else:
                game_state = GameStates.PLAYERS_TURN
Exemple #12
0
def play_game(game: Game):

    game.fov_map: tcod.map.Map = initialize_fov(game.game_map)

    game.game_state: GameStates = GameStates.PLAYER_TURN
    game.previous_state: GameStates = game.game_state

    game.camera: Camera = Camera(player=game.player,
                                 width=CONSTANTS.camera_width,
                                 height=CONSTANTS.camera_height)
    game.camera.fov_update: bool = True

    targeting_item: Optional[Entity] = None

    mouse_position: Point = Point(x=blt.state(blt.TK_MOUSE_X) // 2,
                                  y=blt.state(blt.TK_MOUSE_Y) // 2)

    while game.game_running:
        if game.camera.fov_update:
            recompute_fov(
                fov_map=game.fov_map,
                point=game.player.position,
                radius=CONSTANTS.fov_radius,
                light_walls=CONSTANTS.fov_light_walls,
                algorithm=CONSTANTS.fov_algorithm,
            )

        render_all(
            entities=game.entities,
            player=game.player,
            game_map=game.game_map,
            fov_map=game.fov_map,
            camera=game.camera,
            message_log=game.message_log,
            ui_panel=CONSTANTS.ui_panel,
            bar_width=CONSTANTS.bar_width,
            mouse_position=mouse_position,
            game_state=game.game_state,
        )

        game.camera.fov_update = False

        if blt.has_input():
            terminal_input: int = blt.read()
            mouse_position: Point = Point(x=blt.state(blt.TK_MOUSE_X) // 2,
                                          y=blt.state(blt.TK_MOUSE_Y) // 2)

            action: dict = handle_keys(key=terminal_input,
                                       game_state=game.game_state)
            mouse_action: dict = handle_mouse(key=terminal_input)

            movement: Optional[Point] = action.get("move")
            wait: bool = action.get("wait", False)
            pickup: bool = action.get("pickup", False)
            show_inventory: bool = action.get("show_inventory", False)
            drop_inventory: bool = action.get("drop_inventory", False)
            inventory_index: Optional[int] = action.get("inventory_index")
            take_stairs: bool = action.get("take_stairs", False)
            level_up: str = action.get("level_up")
            show_character_screen: bool = action.get("show_character_screen",
                                                     False)
            exit_action: bool = action.get("exit", False)

            left_click: Point = mouse_action.get("left_click")
            right_click: Point = mouse_action.get("right_click")

            player_turn_results: List = []

            if movement and game.game_state == GameStates.PLAYER_TURN:
                destination = game.player.position + movement

                if not game.game_map.is_blocked(destination):
                    target = get_blocking_entities_at_location(
                        entities=game.entities, destination=destination)

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

                    game.change_state(GameStates.ENEMY_TURN)
            elif wait:
                game.change_state(GameStates.ENEMY_TURN)
            elif pickup and game.game_state == GameStates.PLAYER_TURN:
                for entity in game.entities:
                    if entity.item and entity.position == game.player.position:
                        pickup_results = game.player.inventory.add_item(entity)
                        player_turn_results.extend(pickup_results)

                        break
                else:
                    game.message_log.add_message(
                        Message("There is nothing here to pick up."))

            if show_inventory:
                game.change_state(GameStates.SHOW_INVENTORY)

            if drop_inventory:
                game.change_state(GameStates.DROP_INVENTORY)

            if (inventory_index is not None
                    and game.previous_state != GameStates.PLAYER_DEAD
                    and inventory_index < len(game.player.inventory.items)):
                item = game.player.inventory.items[inventory_index]

                if game.game_state == GameStates.SHOW_INVENTORY:
                    player_turn_results.extend(
                        game.player.inventory.use(item,
                                                  entities=game.entities,
                                                  fov_map=game.fov_map))
                elif game.game_state == GameStates.DROP_INVENTORY:
                    player_turn_results.extend(
                        game.player.inventory.drop_item(item))

            if take_stairs and game.game_state == GameStates.PLAYER_TURN:
                for entity in game.entities:
                    if entity.stairs and entity.position == game.player.position:
                        game.next_floor()
                        game.fov_map = initialize_fov(game.game_map)
                        game.camera.fov_update = True

                        break

                else:
                    game.message_log.add_message(
                        Message("There are no stairs here.", Colors.YELLOW))

            if level_up:
                if level_up == "hp":
                    game.player.fighter.base_max_hp += 20
                    game.player.fighter.hp += 20
                elif level_up == "str":
                    game.player.fighter.base_power += 1
                elif level_up == "dex":
                    game.player.fighter.base_defense += 1

                game.change_state(game.previous_state)

            if show_character_screen:
                game.change_state(GameStates.CHARACTER_SCREEN)

            if game.game_state == GameStates.TARGETING:
                if left_click:
                    target_position: Point = game.camera.map_point(left_click)

                    item_use_results = game.player.inventory.use(
                        targeting_item,
                        entities=game.entities,
                        fov_map=game.fov_map,
                        target_position=target_position,
                    )
                    player_turn_results.extend(item_use_results)
                elif right_click:
                    player_turn_results.append({"targeting_cancelled": True})

            if exit_action:
                if game.game_state in (GameStates.SHOW_INVENTORY,
                                       GameStates.DROP_INVENTORY,
                                       GameStates.CHARACTER_SCREEN):
                    game.change_state(GameStates.PLAYER_TURN)
                elif game.game_state == GameStates.TARGETING:
                    player_turn_results.append({"targeting_cancelled": True})
                else:
                    game.save_game()
                    game.game_running = False

            for player_turn_result in player_turn_results:
                message: Optional[Message] = player_turn_result.get("message")
                dead_entity: Optional[Entity] = player_turn_result.get("dead")
                item_added: Optional[Entity] = player_turn_result.get(
                    "item_added")
                item_consumed: Optional[Entity] = player_turn_result.get(
                    "consumed")
                item_dropped: Optional[Entity] = player_turn_result.get(
                    "item_dropped")
                equip: Optional[Entity] = player_turn_result.get("equip")
                targeting: Optional[Entity] = player_turn_result.get(
                    "targeting")
                xp: Optional[int] = player_turn_result.get("xp")
                targeting_cancelled: bool = player_turn_result.get(
                    "targeting_cancelled", False)

                if message:
                    game.message_log.add_message(message)

                if targeting_cancelled:
                    game.game_state = game.previous_state

                    game.message_log.add_message(
                        Message("Targeting cancelled"))

                if xp:
                    leveled_up = game.player.level.add_xp(xp=xp)
                    game.message_log.add_message(
                        Message(f"You gain {xp} experience points."))

                    if leveled_up:
                        game.message_log.add_message(
                            Message(
                                f"Your battle skills grow stronger! You reached level {game.player.level.current_level}!",
                                Colors.YELLOW))
                        game.change_state(GameStates.LEVEL_UP)

                if dead_entity:
                    if dead_entity == game.player:
                        message = kill_player(player=dead_entity)
                        game.change_state(GameStates.PLAYER_DEAD)
                    else:
                        message = kill_monster(monster=dead_entity)

                    game.message_log.add_message(message)

                if item_added:
                    game.entities.remove(item_added)

                    game.change_state(GameStates.ENEMY_TURN)
                    game.camera.fov_update = True

                if item_consumed:
                    game.change_state(GameStates.ENEMY_TURN)

                if targeting:
                    game.change_state(GameStates.TARGETING)

                    targeting_item: Entity = targeting

                    game.message_log.add_message(
                        targeting_item.item.targeting_message)

                if item_dropped:
                    game.entities.append(item_dropped)

                    game.change_state(GameStates.ENEMY_TURN)

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

                    for equip_result in equip_results:
                        equipped: Optional[Entity] = equip_result.get(
                            "equipped")
                        dequipped: Optional[Entity] = equip_result.get(
                            "dequipped")

                        if equipped:
                            game.message_log.add_message(
                                Message(f"You equipped the {equipped.name}"))

                        if dequipped:
                            game.message_log.add_message(
                                Message(f"You dequipped the {dequipped.name}"))

                    game.change_state(GameStates.ENEMY_TURN)

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

                        for enemy_turn_result in enemy_turn_results:
                            message: Optional[Message] = enemy_turn_result.get(
                                "message")
                            dead_entity = enemy_turn_result.get("dead")

                            if message:
                                game.message_log.add_message(message)

                            if dead_entity:
                                if dead_entity == game.player:
                                    message = kill_player(player=dead_entity)
                                    game.change_state(GameStates.PLAYER_DEAD)
                                else:
                                    message = kill_monster(monster=dead_entity)
                                game.message_log.add_message(message)
                                if game.game_state == GameStates.PLAYER_DEAD:
                                    break
                else:
                    game.change_state(GameStates.PLAYER_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
Exemple #14
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
Exemple #15
0
def play_game(player, entities, game_map, message_log, game_state, con, panel, constants):
	fov_recompute = True

	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

	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'])

		render_all(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)

		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')
		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')
		take_stairs = action.get('take_stairs')
		level_up = action.get('level_up')
		show_character_screen = action.get('show_character_screen')
		exit = action.get('exit')
		fullscreen = action.get('fullscreen')

		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 wait:
			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, constants)
					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.max_hp += 20
				player.fighter.hp += 20
			elif level_up == 'str':
				player.fighter.power += 1
			elif level_up == 'def':
				player.fighter.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:
				save_game(player, entities, game_map, message_log, game_state)

				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')

			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 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 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
Exemple #16
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
Exemple #17
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
Exemple #18
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
Exemple #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
Exemple #20
0
def main():
    screen_width = 80
    screen_height = 50
    map_width = 80
    map_height = 45

    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, 150, 50),
        'desaturated_green': (63, 127, 63),
        'darker_green': (0, 127, 0),
        'dark_red': (191, 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]

    player_x = int(screen_width / 2)
    player_y = int(screen_height / 2)

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

    root_console = tdl.init(screen_width, screen_height, title='Roguelike Tutorial Revised', \
                            renderer='GLSL')
    con = tdl.Console(screen_width, screen_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
    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, entities, player, game_map, fov_recompute,
                       root_console, screen_width, screen_height, colors)
        tdl.flush()

        clear_all(con, entities)

        fov_recompute = False

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

        if not user_input:
            continue

        action = handle_keys(user_input)

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

        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 screenshot:
            tdl.screenshot()

        if exit:
            return True

        if 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:
                print(message)
            if dead_entity:
                if dead_entity == player:
                    message, game_state = kill_player(dead_entity, colors)
                else:
                    message = kill_monster(dead_entity, colors)
                print(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:
                            print(message)
                        if dead_entity:
                            if dead_entity == player:
                                message, game_state = kill_player(
                                    dead_entity, colors)
                            else:
                                message = kill_monster(dead_entity, colors)
                            print(message)
                            if game_state == GameStates.PLAYER_DEAD:
                                break
                if game_state == GameStates.PLAYER_DEAD:
                    break
            else:
                game_state = GameStates.PLAYERS_TURN
Exemple #21
0
def play_game(player, entities, game_map, message_log, game_state, con, panel, constants, bg_music, play_bg_music, score):
    """
    Cette fonction est le squelette du jeu. Elle utilise, directement ou indirectement, tous les autres modules de
    ce projet. Elle est chargée de l'éxécution des commandes du joueur lorsqu'il est en jeu. Elle est constituée
    d'une boucle while infinie (tant que la fenêtre est ouverte) qui teste tous les cas possibles à chaque itération.

    Parametres:
    ----------
    player : Entity
        Le joueur
    entities : list
        Liste des entités présentes (visibiles ou non) à ce niveau
    game_map : GameMap
        Plateau de jeu
    message_log : MessageLog
        Boîte de dialogue, feedback au joueur
    game_state : int
        Désormais inutilisé dans cette fonction
    con : tcod.console
        Console du jeu
    panel : tcod.console
        Console interface
    constants : dict
        Dictionnaire contenant toutes les constantes du jeu
    bg_music : fichier .wav
        Musique de fond
    play_bg_music : bool
        Faut-il jouer la musique de fond ?
    score : int
        Score actuel du joueur (visible qu'à sa mort)

    Renvoi:
    -------
    player : Entity
        Le joueur
    entities : list
        Liste des entités présentes (visibiles ou non) à ce niveau
    game_map : GameMap
        Plateau de jeu
    message_log : MessageLog
        Boîte de dialogue, feedback au joueur
    game_state : int
        Désormais inutilisé dans cette fonction
    bg_music : fichier .wav
        Musique de fond
    play_bg_music : bool
        Faut-il jouer la musique de fond ?
    score : int
        Score actuel du joueur (visible qu'à sa mort)

    """
    sword_sounds = constants.get('sound').get('sword')
    hurt_sound = sm.Son(constants.get('sound').get('hurt')[0])
    clean_stage_sound = sm.Son(constants.get('sound').get('clean_stage')[0])

    fov_recompute = True
    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

    play_boss_music = False
    play_stage_music = False

    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'])
        # Affiche la carte generee
        render_all(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,
                   constants.get('graphics'))

        # Gere la lecture aleatoire de la musique de fond dans les differents stages
        if pygame.mixer.get_busy() == 0 and play_bg_music:
            if game_map.dungeon_level % 5 == 0:
                bg_music.playpause()
                bg_music = sm.choose_sound(constants.get('sound').get('boss_fight'))
                bg_music.playpause()
            else:
                bg_music.playpause()
                bg_music = sm.choose_sound(constants.get('sound').get('background_music'))
                bg_music.playpause()

        if play_boss_music:
            play_boss_music = not play_boss_music
            if play_bg_music:
                bg_music.playpause()
                bg_music = sm.choose_sound(constants.get('sound').get('boss_fight'))
                bg_music.playpause()
            else:
                bg_music = sm.choose_sound(constants.get('sound').get('boss_fight'))

        if play_stage_music:
            play_stage_music = not play_stage_music
            if play_bg_music:
                bg_music.playpause()
                bg_music = sm.choose_sound(constants.get('sound').get('background_music'))
                bg_music.playpause()
            else:
                bg_music = sm.choose_sound(constants.get('sound').get('background_music'))

        fov_recompute = False

        libtcod.console_flush()

        clear_all(con, entities)

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

        # Lit les touches pressees pour en deduire quoi faire
        # Depend du gamestate
        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')
        take_stairs = action.get('take_stairs')
        level_up = action.get('level_up')
        show_character_screen = action.get('show_character_screen')
        exit = action.get('exit')
        fullscreen = action.get('fullscreen')

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

        player_turn_results = []

        hp80 = 0.80*player.fighter.max_hp
        hp60 = 0.60*player.fighter.max_hp
        hp40 = 0.40*player.fighter.max_hp
        hp20 = 0.20*player.fighter.max_hp

        # Si c'est au joueur et qu'il presse une touche de deplacement
        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)
                    sword = sm.choose_sound(sword_sounds)
                    sword.playpause()
                    player_turn_results.extend(attack_results)
                    for entity in entities:
                        if entity.stairs:
                            entity.visible = True
                else:
                    player.move(dx, dy)
                game_state = GameStates.ENEMY_TURN
            fov_recompute = True

        # Si le joueur passe son tour
        elif wait:
            fov_recompute = True
            game_state = GameStates.ENEMY_TURN

        # Si le joueur ramasse un objet
        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('Rien a ramasser', libtcod.yellow))

        # Si le joueur consulte son inventaire
        if show_inventory:
            previous_game_state = game_state
            game_state = GameStates.SHOW_INVENTORY

        # Si le joueur souhaite jeter un item
        if drop_inventory:
            previous_game_state = game_state
            game_state = GameStates.DROP_INVENTORY

        # Si le joueur est dans son inventaire : que faire pour utiliser ou jetter un item
        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))

        # Passage au niveau suivant
        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, play_boss_music, play_stage_music = game_map.next_floor(player, message_log, constants, constants.get('graphics'))
                    fov_map = initialize_fov(game_map)
                    fov_recompute = True
                    libtcod.console_clear(con)
                    score = (score[0] + 1, score[1])
                    break
            else:
                message_log.add_message(Message("Il n'y a pas d'escaliers ici.", 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
            player.inventory.add_capacity(2)
            game_state = previous_game_state

        if show_character_screen:
            previous_game_state = game_state
            game_state = GameStates.CHARACTER_SCREEN

        # Si le joueur est en train de cibler avec un parchemin
        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, GameStates.MENU_SCREEN):
                game_state = previous_game_state
            elif game_state == GameStates.TARGETING:
                player_turn_results.append({'targeting_cancelled': True})
            else:
                return player, entities, game_map, message_log, game_state, bg_music, play_bg_music, score

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

        # Execute tous les resultats precedent
        # Qui ne sont pas None
        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')
            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)
                    if all_dead(entities):
                        leveled_up = player.level.add_xp(0.1 * player.level.level_up_base)
                        clean_stage_sound.playpause()
                        message_log.add_message(Message('Plus de monstres, bonus 10% XP', libtcod.yellow))
                        if leveled_up:
                            message_log.add_message(Message('Level UP : niveau {0} atteint !'.format(
                                player.level.current_level), libtcod.yellow))
                            previous_game_state = game_state
                            game_state = GameStates.LEVEL_UP
                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 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('{0} equipe(e)'.format(equipped.name)))
                    if dequipped:
                        message_log.add_message(Message('{0} desequippe(e)'.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 targeting_cancelled:
                game_state = previous_game_state
                message_log.add_message(Message('Ciblage annule'))

            if xp:
                leveled_up = player.level.add_xp(xp)
                score = (score[0], score[1] + xp)
                message_log.add_message(Message('+{0} XP'.format(xp)))
                if leveled_up:
                    message_log.add_message(Message('Level UP : niveau {0} atteint !'.format(
                        player.level.current_level), libtcod.yellow))
                    previous_game_state = game_state
                    game_state = GameStates.LEVEL_UP

        # Gere le tour des enemis : parcours toutes les entites et fait jouer les fighter ai
        if game_state == GameStates.ENEMY_TURN:
            for entity in entities:
                if entity.ai:
                    hp_before_attack = player.fighter.hp
                    enemy_turn_results = entity.ai.take_turn(player, fov_map, game_map, entities)
                    if (player.fighter.hp <= hp80 < hp_before_attack) \
                            or (player.fighter.hp <= hp60 < hp_before_attack) \
                            or (player.fighter.hp <= hp40 < hp_before_attack) \
                            or (player.fighter.hp <= hp20 < hp_before_attack):
                        hurt_sound.playpause()
                    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)
                                save_score(score)
                                delete_save()
                            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

    return player, entities, game_map, message_log, game_state, bg_music, play_bg_music, score
Exemple #22
0
def main():
    """ Main game function """
    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]

    # Import font
    tcod.console_set_custom_font(
        FONT, tcod.FONT_TYPE_GREYSCALE | tcod.FONT_LAYOUT_TCOD)

    # Console initialization
    tcod.console_init_root(screen_width,
                           screen_height,
                           'Pilferer %s' % VERSION,
                           False,
                           vsync=False)
    con = tcod.console.Console(screen_width, screen_height)

    # Mapping
    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
    fov_recompute = True
    fov_map = initialize_fov(game_map)

    # Variables for holding input
    key = tcod.Key()
    mouse = tcod.Mouse()

    # Game state
    game_state = GameStates.PLAYERS_TURN

    # Main game loop
    while not tcod.console_is_window_closed():
        # FOV
        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, fov_radius,
                          fov_light_walls, fov_algorithm)

        # Draw
        render_all(con, entities, player, game_map, fov_map, fov_recompute,
                   screen_width, screen_height, colors)
        fov_recompute = False
        tcod.console_flush()
        clear_all(con, entities)

        # INDPUT HANDLING
        tcod.sys_check_for_event(tcod.EVENT_KEY_PRESS, key, mouse)
        action = handle_keys(key)

        # Command move
        player_turn_results = []
        move = action.get('move')
        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_entity_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

        # Command exit
        exit = action.get('exit')
        if exit:
            return True

        # Command Fullscreen
        fullscreen = action.get('fullscreen')
        if fullscreen:
            tcod.console_set_fullscreen(not tcod.console_is_fullscreen())

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

            if message:
                print(message)

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

                print(message)

        # Monster turns
        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:
                            print(message)

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

                            print(message)

                            if game_state == GameStates.PLAYER_DEAD:
                                break

                    if game_state == GameStates.PLAYER_DEAD:
                        break

            else:
                game_state = GameStates.PLAYERS_TURN

            game_state = GameStates.PLAYERS_TURN
Exemple #23
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
Exemple #24
0
def main():
    constants = get_constants()

    libtcod.console_set_custom_font(
        'arial10x10.png',
        libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD)
    libtcod.console_init_root(constants['screen_width'],
                              constants['screen_height'], 'rogue', False)

    con = libtcod.console_new(constants['screen_width'],
                              constants['screen_height'])
    panel = libtcod.console_new(constants['screen_width'],
                                constants['panel_height'])

    player, entities, game_map, message_log, game_state = get_game_variables(
        constants)

    fov_recompute = True

    fov_map = initialize_fov(game_map)

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

    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, constants['fov_radius'],
                          constants['fov_light_walls'],
                          constants['fov_algorithm'])

        render_all(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'],
                   constants['mouse'], constants['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')
        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')

        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):
                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

        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.append(item_use_results)
            elif right_click:
                player_turn_results.append({'targeting_cancelled': True})

        if exit:
            if game_state in (game_state.SHOW_INVENTORY,
                              game_state.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 = game_state.ENEMY_TURN

            if item_consumed:
                game_state.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
Exemple #25
0
def play_game(player, entities, game_map, message_log, game_state, con, panel,
              constants):
    fov_recompute = True

    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

    # game loop
    while not libtcod.console_is_window_closed():
        # captures user input - will update the key and mouse variables with what the user inputs
        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'])

        # draw the entities and blit the changes to the screen - only render the item inventory when the game state is in the inventory state
        render_all(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)

        fov_recompute = False

        # present everything on the screen
        libtcod.console_flush()

        # clear entities after drawing to screen - this makes it so that when entities move, they do not leave a trail behind
        clear_all(con, entities)

        # gives a way to gracefully exit program by hitting the ESC key
        # gets any keyboard input to the program and stores in the key variable
        action = handle_keys(key, game_state)
        mouse_action = handle_mouse(mouse)

        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')
        take_stairs = action.get('take_stairs')
        level_up = action.get('level_up')
        show_character_screen = action.get('show_character_screen')
        exit = action.get('exit')
        fullscreen = action.get('fullscreen')

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

        player_turn_results = []

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

            # check if there is something at the destination that would block the player - if not, move the player there
            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

                # change to enemy's turn after player's move
                game_state = GameStates.ENEMY_TURN

        elif wait:
            game_state = GameStates.ENEMY_TURN

        # if the player did not move and performed the pickup action by pressing the key 'g'...
        elif pickup and game_state == GameStates.PLAYERS_TURN:
            # loop through each entity on the map, check if it is an item and occupies the same space as the player
            for entity in entities:
                # if the entity is an item and in the same position as the player
                if entity.item and entity.x == player.x and entity.y == player.y:
                    # add the item to the inventory and append the results to player_turn_results
                    pickup_results = player.inventory.add_item(entity)
                    player_turn_results.extend(pickup_results)

                    break  # makes it so the player only picks up one item at a time
            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

        # take the index selected, use the item selected
        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,
                                                   constants)
                    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.max_hp += 20
                player.fighter.hp += 20
            elif level_up == 'str':
                player.fighter.power += 1
            elif level_up == 'def':
                player.fighter.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})

        # checks if the key pressed was the Esc key - if it was, then exit the loop
        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 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')

            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_dropped:
                entities.append(item_dropped)

                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 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
            # note that this is a for-else statement; without a break statement, this else will always happen
            else:
                game_state = GameStates.PLAYERS_TURN
Exemple #26
0
def play_game(player, entities, game_map, message_log, game_state, con, panel,
              constants):
    # bool to store whether we update fov or not
    fov_recompute = True
    fov_map = initialize_fov(game_map)

    # key and mouse to capture input
    key = libtcod.Key()
    mouse = libtcod.Mouse()
    mouse_pos = 0

    # set game state
    game_state = GameStates.PLAYERS_TURN
    previous_game_state = game_state

    # make sure set to none
    targeting_item = None

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

        # This is will update the mouse when it is moved.
        if mouse.x != mouse_pos:
            fov_recompute = True
            mouse_pos = mouse.x

        #if player doesn't move fov won't update.
        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, constants['fov_radius'],
                          constants['fov_light_walls'],
                          constants['fov_algorithm'])

        #update everything
        render_all(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)
        fov_recompute = False

        libtcod.console_flush()

        clear_all(con, entities)

        action = handle_keys(key, game_state)

        mouse_action = handle_mouse(mouse)

        #----ACTIONS-----
        move = action.get('move')
        pickup = action.get('pickup')
        show_inventory = action.get('show_inventory')
        inventory_index = action.get('inventory_index')
        drop_inventory = action.get('drop_inventory')
        exit = action.get('exit')
        fullscreen = action.get('fullscreen')

        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
            fov_recompute = True
            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
                #after player's turn set to enemy turn
                game_state = GameStates.ENEMY_TURN
        elif pickup and game_state == GameStates.PLAYERS_TURN:
            fov_recompute = True
            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:
            fov_recompute = True
            previous_game_state = game_state
            game_state = GameStates.SHOW_INVENTORY

        if drop_inventory:
            fov_recompute = True
            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):
            fov_recompute = True
            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
                fov_recompute = True
            elif game_state == GameStates.TARGETING:
                player_turn_results.append({'targeting_canclled': True})
            else:
                # save when the game is exited
                save_game(player, entities, game_map, message_log, game_state)

                return True

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

        ##-----PLAYER TURN RESULTS
        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 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)
                fov_recompute = True
                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.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 game_state == GameStates.ENEMY_TURN:
            for entity in entities:
                if entity.ai:  #if an entity object has an ai, it gets a turn.
                    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:
                #after all the enemies move, players turn
                game_state = GameStates.PLAYERS_TURN
Exemple #27
0
def play_game(player, entities, game_map, message_log, game_state, con, panel,
              constants, root_con):
    tcod.console_set_custom_font(
        "arial10x10.png", tcod.FONT_LAYOUT_TCOD | tcod.FONT_TYPE_GREYSCALE)
    fov_recompute = True
    fov_map = initialize_fov(game_map)
    previous_game_state = game_state
    targeting_item = None
    while True:
        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, constants['fov_radius'],
                          constants['fov_light_walls'],
                          constants['fov_algorithm'])
        render_all(con, panel, entities, player, game_map, fov_map,
                   fov_recompute, message_log, constants["screen_width"],
                   constants["screen_height"], constants["bar_width"],
                   constants["panel_y"], constants["colors"], root_con,
                   game_state)
        tcod.console_flush()
        clear_all(con, entities)
        for event in tcod.event.get():
            move = None
            pickup = None
            look_enemy = None
            left_click = None
            right_click = None
            show_inventory = None
            drop_inventory = None
            inventory_index = None
            take_stairs = None
            leave = None
            fullscreen = None
            show_character_screen = None
            player_turn_results = []
            if isinstance(event, tcod.event.KeyDown):
                action = handle_keys(event, game_state)
                move = action.get("move")
                pickup = action.get("pickup")
                look_enemy = action.get("look_enemy")
                show_inventory = action.get("show_inventory")
                drop_inventory = action.get("drop_inventory")
                inventory_index = action.get("inventory_index")
                take_stairs = action.get('take_stairs')
                leave = action.get("leave")
                fullscreen = action.get("fullscreen")
                show_character_screen = action.get('show_character_screen')
            if isinstance(event, tcod.event.MouseButtonDown):
                mouse_action = handle_mouse(event)
                left_click = mouse_action.get("left_click")
                right_click = mouse_action.get("right_click")
            if look_enemy and game_state == GameStates.PLAYER_TURN:
                game_state = GameStates.LOOK_ENEMY
                player_turn_results.extend([{
                    'message':
                    Message('You are in the looking mode', tcod.green)
                }])
            elif look_enemy and game_state == GameStates.LOOK_ENEMY:
                game_state = GameStates.PLAYER_TURN
                player_turn_results.extend([{
                    'message':
                    Message('You left the looking mode', tcod.green)
                }])
            elif left_click and game_state == GameStates.LOOK_ENEMY:
                entities_at_location = check_entity_at_location(
                    entities, left_click[0], left_click[1])
                player_turn_results.extend(entities_at_location)
            elif pickup and game_state == 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('There is nothing here to pick up.',
                                tcod.yellow))
            elif show_inventory:
                previous_game_state = game_state
                game_state = GameStates.SHOW_INVENTORY
                MenuState.menu_state = 0
            elif drop_inventory:
                previous_game_state = game_state
                game_state = GameStates.DROP_INVENTORY
            elif 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))
            elif game_state == GameStates.TARGETING:
                if left_click and targeting_item:
                    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})
            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.melee_attack(target)
                        player_turn_results.extend(attack_results)
                    else:
                        player.move(dx, dy)

                        fov_recompute = True
                    game_state = GameStates.ENEMY_TURN
            elif take_stairs and game_state == GameStates.PLAYER_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,
                                                       constants)
                        fov_map = initialize_fov(game_map)
                        fov_recompute = True
                        con.clear(fg=(63, 127, 63))

                        break
                else:
                    message_log.add_message(
                        Message('There are no stairs here.', tcod.yellow))
            elif game_state == GameStates.LEVEL_UP:
                player.fighter.max_hp += DiceRoll("1d8").roll_dice()
                game_state = previous_game_state
            elif show_character_screen:
                previous_game_state = game_state
                game_state = GameStates.CHARACTER_SCREEN
            if leave:
                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 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')
                entity_identified = player_turn_result.get("entity_identified")
                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')
                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 entity_identified:
                    game_state = GameStates.PLAYER_TURN

                if targeting:
                    previous_game_state = GameStates.PLAYER_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) + '!',
                                tcod.yellow))
                        player.fighter.cr = str(player.level.current_level / 4)
                        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.PLAYER_TURN
Exemple #28
0
def play_game(player, entities, game_map, message_log, game_state,
              root_console, con, panel, constants):
    tdl.set_font('arial10x10.png', greyscale=True, altLayout=True)

    fov_recompute = True

    mouse_coordinates = (0, 0)

    previous_game_state = game_state

    targeting_item = None

    while not tdl.event.is_window_closed():
        if fov_recompute:
            game_map.compute_fov(player.x,
                                 player.y,
                                 fov=constants['fov_algorithm'],
                                 radius=constants['fov_radius'],
                                 light_walls=constants['fov_light_walls'])
        render_all(con, panel, entities, player, game_map, fov_recompute,
                   root_console, message_log, constants['screen_width'],
                   constants['screen_height'], constants['bar_width'],
                   constants['panel_height'], constants['panel_y'],
                   mouse_coordinates, constants['colors'], game_state)
        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
            elif event.type == 'MOUSEDOWN':
                user_mouse_input = event
                break
        else:
            user_input = None
            user_mouse_input = None

        if not (user_input or user_mouse_input):
            continue

        action = handle_keys(user_input, game_state)
        mouse_action = handle_mouse(user_mouse_input)

        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')
        take_stairs = action.get('take_stairs')
        level_up = action.get('level_up')
        show_character_screen = action.get('show_character_screen')
        exit = action.get('exit')
        fullscreen = action.get('fullscreen')

        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 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

        elif wait:
            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, constants['colors'])
                    player_turn_results.extend(pickup_results)

                    break
            else:
                message_log.add_message(
                    Message('There is nothing here to pick up.',
                            constants['colors'].get('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,
                                         constants['colors'],
                                         entities=entities,
                                         game_map=game_map))
            elif game_state == GameStates.DROP_INVENTORY:
                player_turn_results.extend(
                    player.inventory.drop_item(item, constants['colors']))

        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:
                    game_map, entities = next_floor(player, message_log,
                                                    entity.stairs.floor,
                                                    constants)
                    fov_recompute = True
                    con.clear()

                    break
            else:
                message_log.add_message(
                    Message('There are no stairs here.',
                            constants['colors'].get('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,
                                                        constants['colors'],
                                                        entities=entities,
                                                        game_map=game_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:
                save_game(player, entities, game_map, message_log, game_state)

                return True

        if 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')
            item_added = 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,
                                                      constants['colors'])
                else:
                    message = kill_monster(dead_entity, constants['colors'])

                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 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 dequipped the {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 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) + '!',
                            constants['colors'].get('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, 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, constants['colors'])
                            else:
                                message = kill_monster(dead_entity,
                                                       constants['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
Exemple #29
0
def main():
    """
    사전 준비 작업
    """
    SYS_LOG = init_data()

    player, entities = init_player_and_entities(SYS_LOG['player_name'])

    game_map, fov_map, fov_radius, \
    fov_algorithm, fov_recompute, light_recompute, camera = init_game_map(player, entities)

    message_log, game_state, previous_game_state, targeting_item = init_message_and_states(
    )

    root, console, panel, animation, context = init_console()

    debug, mouse, keyboard = init_others()

    quit = False
    """
    메인 루프
    """
    while not quit:
        #root = tcod.Console(*context.recommended_console_size())
        """
        화면 표시
        """
        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, fov_radius,
                          fov_light_walls, fov_algorithm)

        if light_recompute:
            light_map = initialize_light(game_map, fov_map, entities)
        render_all(
            game_state,
            root,
            console,
            panel,
            entities,
            player,
            mouse,
            game_map,
            fov_map,
            light_map,
            camera,
            message_log,
            fov_recompute,
        )

        context.present(root, keep_aspect=True,
                        align=(0.5,
                               0.5))  # integer_scaling=True align=(0.5,1))

        #print(*context.recommended_console_size())
        clear_all_entities(console, entities, camera)

        fov_recompute = False
        light_recompute = False
        """
        입력에 대한 상호작용
        """

        action = handle_input_per_state(keyboard, mouse, context, game_state)
        #print(f'Mx:{mouse.x} My:{mouse.y} Clk:{mouse.click}')

        #Ridiculous failsafe
        if action == None:
            action = {}

        move = action.get('move')
        rest = action.get('rest')
        pickup = action.get('pickup')

        show_inventory = action.get('show_inventory')
        inventory_index = action.get('inventory_index')
        drop_inventory = action.get('drop_inventory')
        show_character_screen = action.get('show_character_screen')

        toggle_light = action.get('toggle_light')
        create_luminary = action.get('create_light')
        toggle_wall = action.get('toggle_wall')

        exit = action.get('exit')
        quit = action.get('quit')

        #print(action)
        player_turn_results = []

        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:
                pass

        # 최대화면이 True일 시, 전체화면이 아니라면 콘솔을 전체화면으로 전환함
        if action.get('fullscreen'):
            toggle_fullscreen(context)

        #print(f'center x{CENTER_X},y{CENTER_Y}')
        """
        플레이어 차례에 플레이어가 할 수 있는 행동들
        """
        # move변수에 대입된 값이 있을 시 이동
        if move and game_state == GameStates.PLAYERS_TURN:
            dx, dy = action.get('move')
            destix = player.x + dx
            destiy = player.y + dy

            if debug.passwall == False:
                # 가려는 곳이 지형으로 안 막혀있으면
                if not game_map.is_blocked(destix, destiy):
                    # 거기에 이미 엔티티가 있나 확인
                    target = get_blocking_entities_at_location(
                        entities, destix, destiy)

                    if target:

                        battle = target._Fighter

                        if target.name == "메리":
                            pass
                        elif battle:
                            attack_results = player._Fighter.attack(target)
                            player_turn_results.extend(attack_results)
                        else:
                            """
                            다음 층으로
                            """
                            if target._Portal:
                                entities = game_map.next_depth(
                                    player, message_log)
                                fov_map = initialize_fov(game_map)
                                fov_recompute = True
                                light_recompute = True
                                console.clear()
                            else:
                                print(
                                    "This is the weirdest bug I've ever seen")

                    else:
                        player.move(dx, dy)
                        camera.update(player)
                        fov_recompute = True
                        light_recompute = True

                    game_state = GameStates.ENEMY_TURN
            else:
                if game_map.is_blocked(player.x + dx, player.y + dy):
                    debug.dbg_msg("You magically pass through solid wall.")
                player.move(dx, dy)
                camera.update(player)

        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.log(
                    Message(SYS_LOG['cannot_get_item'], tcod.yellow))

        if toggle_light:
            if player._Luminary.luminosity:
                player._Luminary.luminosity = 0
                fov_radius = 1
                fov_algorithm = fov_algorithm_dark
            else:
                player._Luminary.luminosity = player._Luminary.init_luminosity
                fov_radius = max_fov_radius
                fov_algorithm = fov_algorithm_lit

            fov_recompute = True
            light_recompute = True

            game_state = GameStates.ENEMY_TURN

        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,
                                          camera=camera,
                                          entities=entities,
                                          animation=animation,
                                          root=root,
                                          context=context,
                                          fov_map=fov_map,
                                          game_map=game_map))
            elif game_state == GameStates.DROP_INVENTORY:
                player_turn_results.extend(player._Inventory.drop_item(item))

        if game_state == GameStates.TARGETING:
            if mouse.click == "L":
                target_x = mouse.x - camera.x - CENTER_X
                target_y = mouse.y - camera.y - CENTER_Y
                #print(f"타게팅 x,y: {target_x},{target_y}")

                item_use_results = player._Inventory.use(targeting_item,
                                                         entities=entities,
                                                         fov_map=fov_map,
                                                         camera=camera,
                                                         animation=animation,
                                                         root=root,
                                                         context=context,
                                                         target_x=target_x,
                                                         target_y=target_y)

                player_turn_results.extend(item_use_results)
            elif mouse.click == "R":
                player_turn_results.append({'targeting_cancelled': True})

        if rest:
            game_state = GameStates.ENEMY_TURN

        if show_character_screen:
            previous_game_state = game_state
            game_state = GameStates.CHARACTER_SCREEN

        if player._Fighter.sanity <= 0:
            message, game_state = insane_player(player)
            message_log.log(message)

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

            equip = r.get('equip')
            item_added = r.get('item_added')
            item_consumed = r.get('consumed')
            item_used = r.get('used')
            item_dropped = r.get('item_dropped')
            targeting = r.get('targeting')
            targeting_cancelled = r.get('targeting_cancelled')

            if message:
                message_log.log(message)

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

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

                message_log.log(message)

            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')

                    equip_log = SYS_LOG['equip_log']

                    if equipped:
                        way = equipped._Equippable.slot.name
                        msg = cout(equip_log, equip_log['ways_to_wear'][way],
                                   받침(equipped.name, 1))
                        message_log.log(Message(msg))

                    if dequipped:
                        way = dequipped._Equippable.slot.name
                        msg = cout(equip_log, equip_log['ways_to_unwear'][way],
                                   받침(dequipped.name, 1))
                        message_log.log(Message(msg))

                game_state = GameStates.ENEMY_TURN

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

            if item_consumed or item_used:
                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.TARGETING
                targeting_item = targeting
                message_log.log(targeting_item._Item.targeting_message)
        """
        적의 차례에 적이 할 수 있는 행동들
        """
        if game_state == GameStates.ENEMY_TURN:
            # 정신력 고갈 기능. 따로 변수로 넣던가 Gamemap에 넣어야 하나.
            if not game_map.monsters == 0:

                clear_message_shown = False
                """
                정신력 피해 계산
                """
                sanity_damage = random.randint(
                    int(-30 / math.sqrt(game_map.depth)), game_map.monsters)
                s_resist_percent = int(
                    (100 + 3 * (fov_radius - 1) +
                     player._Equipment.total_sanity_resist) / 100)
                sanity_resistance = random.randint(0,
                                                   int(10 * s_resist_percent))
                sanity_damage -= sanity_resistance  #광기저항을 계산 안 했네

                if sanity_damage < 0:
                    sanity_damage = 0
                else:
                    sanity_damage = int(math.sqrt(sanity_damage))
                player._Fighter.heal_sanity(-sanity_damage)
                if sanity_damage > 3:
                    log = SYS_LOG['enemies_exist']
                    message_log.log(
                        Message(log[random.randint(0,
                                                   len(log) - 1)],
                                tcod.dark_chartreuse))
            else:
                if not clear_message_shown:
                    clear_message_shown = True
                    message_log.log(
                        Message(SYS_LOG['enemies_nonexistant'], tcod.green))

            for entity in entities:
                if entity.name == 'light source':
                    pass
                    #message_log.log(f"The {entity.name} is glowing")
                elif entity._Ai:
                    enemy_turn_results = entity._Ai.take_turn(
                        player, fov_map, game_map, entities)

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

                        if game_won:
                            message_log.log(
                                Message(SYS_LOG['found_mary_log'], tcod.green))
                            message_log.log(
                                Message(SYS_LOG['game_won_log'], tcod.green))
                            game_state = GameStates.GOOD_ENDING

                        if message:
                            message_log.log(message)

                        if player._Fighter.sanity <= 0:
                            message, game_state = insane_player(player)
                            message_log.log(message)

                        if dead_entity:
                            if dead_entity == player:
                                message, game_state = kill_player(dead_entity)
                            else:
                                message = kill_monster(dead_entity)
                                game_map.monsters -= 1

                            message_log.log(message)

                            if game_state == GameStates.PLAYER_DEAD:
                                break

                    if game_state == GameStates.PLAYER_DEAD:
                        break

            else:
                if not game_state == GameStates.GOOD_ENDING:
                    game_state = GameStates.PLAYERS_TURN
        """
        디버그 기능들
        """
        # 플레이어 위치 표시
        if debug.showpos: debug.show_pos(player, 'player')

        # 벽 설치
        if toggle_wall:
            game_map.toggle_wall(player.x, player.y)
            # 지형이 변했으니 새로 지형 맵을 짜야 함
            fov_map = initialize_fov(game_map)
            light_recompute = True

        if create_luminary:
            game_map.create_luminary(entities, player.x, player.y, 15)
            # 광원이 새로 생겼으니 다시 계산
            light_recompute = True
Exemple #30
0
def play_game(player, entities, game_map, message_log, game_state, con,
              message_panel, char_info_panel, area_info_panel,
              under_mouse_panel, constants, floor_index, original_entity_index,
              entity_index, fov_index):
    fov_recompute = True
    fov_map = initialize_fov(game_map)
    key = libtcod.Key()
    mouse = libtcod.Mouse()

    game_state = GameStates.PLAYERS_TURN
    previous_game_state = game_state

    mouse_x = mouse.cx
    old_mouse_x = mouse_x

    mouse_y = mouse.cy
    old_mouse_y = mouse_y

    #attack_animation_x = 0
    #attack_animation_y = 0

    clean_map = False

    #attacked = False

    #animation_time = 200
    #animation_distance = 0

    targeting_item = None

    equipment_choice = 0

    npc = None

    item = None

    while not libtcod.console_is_window_closed():
        libtcod.sys_check_for_event(
            libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, key, mouse)
        """
		if animation_time == 0:
			if attacked:
				animation_distance += 1
			animation_time = 200

		if animation_distance == 5:
			animation_distance = 0
			attacked = False
		"""

        if clean_map == True:
            fov_recompute = True
            clean_map = False

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

        render_all(con, message_panel, char_info_panel, area_info_panel,
                   under_mouse_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['tiles'], constants['colors'], game_state, npc,
                   targeting_item, item, equipment_choice)

        fov_recompute = False

        libtcod.console_flush()

        clear_all(con, entities, fov_map, game_map)

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

        ############################################
        if game_state == GameStates.EQUIPMENT_SCREEN and not action.get(
                'exit'):
            for equipment in action:
                if equipment:
                    equipment_choice = equipment
                    break

        ############################################

        move = action.get('move')
        ranged_attack = action.get('ranged_attack')
        interact = action.get('interact')
        inspect_item = action.get('inspect_item')
        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')
        take_stairs = action.get('take_stairs')
        level_up = action.get('level_up')
        show_character_screen = action.get('show_character_screen')
        show_equipment_screen = action.get('show_equipment_screen')
        exit = action.get('exit')
        fullscreen = action.get('fullscreen')

        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 and not target.invulnerable:
                    attack_results = player.combat_class.attack(target)
                    player_turn_results.extend(attack_results)

                    clean_map = True

                elif not target:
                    player.move(dx, dy)

                    if player.combat_class.turns_until_rest == 0:
                        pass
                    else:
                        player.combat_class.turns_until_rest -= 1

                    fov_recompute = True

                game_state = GameStates.ENEMY_TURN

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

            if not game_map.is_blocked(destination_x, destination_y):
                blocking_target = get_blocking_entities_at_location(
                    entities, destination_x, destination_y)
                non_blocking_target = get_non_blocking_entities_at_location(
                    entities, destination_x, destination_y)

                if blocking_target:
                    try:
                        if blocking_target.dialogue.dialogue:
                            npc = blocking_target
                    except (AttributeError):
                        pass
                    if blocking_target.bonfire is not None:
                        message_log.add_message(
                            Message(
                                'You see a mysterious bonfire. You cannot resist touching it',
                                libtcod.light_violet))
                        entity_index = blocking_target.bonfire.reset_entities(
                            game_map, original_entity_index, entity_index)
                        game_state = GameStates.PLAYERS_TURN
                    else:
                        message_log.add_message(
                            Message('You see {0}'.format(blocking_target.name),
                                    libtcod.white))

                elif non_blocking_target:
                    message_log.add_message(
                        Message('You see {0}'.format(non_blocking_target.name),
                                libtcod.white))

                else:
                    message_log.add_message(
                        Message('There is nothing to inspect here.',
                                libtcod.white))

        elif wait:
            if player.combat_class.turns_until_rest == 0:
                pass
            else:
                player.combat_class.turns_until_rest -= 1

            message = player.combat_class.rest()
            message_log.add_message(Message(message, libtcod.green))
            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.white))

        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 interact:
            previous_game_state = GameStates.PLAYERS_TURN
            game_state = GameStates.INTERACT
            message_log.add_message(Message('You begin to look around.'))

        if ranged_attack:
            if player.equipment.main_hand.equippable.ranged:
                previous_game_state = GameStates.PLAYERS_TURN
                game_state = GameStates.TARGETING
                message_log.add_message(Message('Choose a target to attack.'))
            else:
                message_log.add_message(
                    Message('This weapon cannot attack at range.'))

        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))

            elif game_state == GameStates.CHOOSE_ITEM_TO_INSPECT:
                previous_game_state = GameStates.CHOOSE_ITEM_TO_INSPECT
                game_state = GameStates.INSPECT_ITEM
                message_log.add_message(
                    Message('You inspect the {0}.'.format(item.name)))

        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:
                    if entity.name == 'Stairs Down':
                        if len(floor_index) == game_map.dungeon_level:
                            entities = game_map.new_floor(
                                player, message_log, constants)
                            fov_map = initialize_fov(game_map)
                            floor_index.append(game_map.tiles)
                            entity_index.append(entities)
                            original_entity_index.append(entities)
                            fov_index.append(fov_map)
                            fov_recompute = True
                            libtcod.console_clear(con)
                            break

                        elif len(floor_index) > game_map.dungeon_level:
                            # Update the entity index with the floors NEW entity list
                            entity_index[game_map.dungeon_level - 1] = entities
                            entities, player, fov_map = game_map.next_floor(
                                player, entity_index, floor_index, fov_index,
                                message_log, constants)
                            fov_recompute = True
                            libtcod.console_clear(con)
                            break

                    elif entity.name == 'Stairs Up':
                        entity_index[game_map.dungeon_level - 1] = entities
                        entities, player, fov_map = game_map.previous_floor(
                            player, entity_index, floor_index, fov_index,
                            message_log, constants)
                        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 == 'str':
                player.combat_class.base_strength += 1
            elif level_up == 'dex':
                player.combat_class.base_dexterity += 1
            elif level_up == 'sta':
                player.combat_class.base_stamina += 1
            elif level_up == 'int':
                player.combat_class.base_intelligence += 1

            game_state = previous_game_state

        if show_character_screen:
            previous_game_state = game_state
            game_state = GameStates.CHARACTER_SCREEN

        if show_equipment_screen:
            previous_game_state = game_state
            game_state = GameStates.EQUIPMENT_SCREEN

        if game_state == GameStates.TARGETING:
            mouse_x = mouse.cx
            mouse_y = mouse.cy

            if (old_mouse_y != mouse_y
                    or old_mouse_x != mouse_x) and libtcod.map_is_in_fov(
                        fov_map, mouse_x, mouse_y):
                fov_recompute = True
            elif libtcod.map_is_in_fov(
                    fov_map, old_mouse_x,
                    old_mouse_y) and not libtcod.map_is_in_fov(
                        fov_map, mouse_x, mouse_y):
                clean_map = True

            old_mouse_x = mouse_x
            old_mouse_y = mouse_y
            if left_click and targeting_item != None:
                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)
                fov_recompute = True

            elif right_click:
                player_turn_results.append({'targeting_cancelled': True})
                fov_recompute = True

            elif left_click and targeting_item == None:
                target_x, target_y = left_click
                if not game_map.tiles[target_x][target_y].blocked:
                    target = get_blocking_entities_at_location(
                        entities, target_x, target_y)
                else:
                    message_log.add_message(
                        Message('You can\'t attack that.', libtcod.yellow))

                if target and not target.invulnerable:
                    attack_results = player.combat_class.attack(target)
                    player_turn_results.extend(attack_results)
                    fov_recompute = True
                    game_state = GameStates.ENEMY_TURN

        if game_state == GameStates.SHOW_INVENTORY:
            if inspect_item:
                previous_game_state = game_state
                game_state = GameStates.CHOOSE_ITEM_TO_INSPECT
                message_log.add_message(
                    Message('Choose an item to inspect.', libtcod.yellow))

        if game_state == GameStates.EQUIPMENT_SCREEN:
            if equipment_choice:
                previous_game_state = game_state
                game_state = GameStates.EQUIPMENT_DETAILS

        if exit:
            if game_state in (GameStates.SHOW_INVENTORY,
                              GameStates.DROP_INVENTORY,
                              GameStates.CHARACTER_SCREEN,
                              GameStates.INTERACT):
                if game_state == (GameStates.INTERACT):
                    player_turn_results.append({'interacting_cancelled': True})
                    game_state = previous_game_state
                    npc = None
                else:
                    game_state = previous_game_state

            elif game_state == GameStates.CHOOSE_ITEM_TO_INSPECT:
                game_state = GameStates.SHOW_INVENTORY
                previous_game_state = GameStates.PLAYERS_TURN
                message_log.add_message(
                    Message('Item inspection cancelled.', libtcod.yellow))

            elif game_state == GameStates.INSPECT_ITEM:
                game_state = previous_game_state

            elif game_state == GameStates.EQUIPMENT_SCREEN:
                game_state = GameStates.PLAYERS_TURN

            elif game_state == GameStates.EQUIPMENT_DETAILS:
                game_state = previous_game_state
                equipment_choice = False

            elif game_state == GameStates.TARGETING:
                player_turn_results.append({'targeting_cancelled': True})
                game_state = previous_game_state
                fov_recompute = True

            else:
                libtcod.console_clear(0)
                save_game(player, entities, game_map, message_log, game_state,
                          floor_index, original_entity_index, entity_index,
                          fov_index)

                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')
            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')
            interacting_cancelled = player_turn_result.get(
                'interacting_cancelled')

            if message:
                message_log.add_message(message)

            if dead_entity:
                if dead_entity == player:
                    message, game_state = kill_player(dead_entity)
                else:
                    dead_entity.alive = False
                    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 equip:
                equip_results = player.equipment.toggle_equip(equip)

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

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

                    if unequipped:
                        message_log.add_message(
                            Message('You unequipped the {0}.'.format(
                                unequipped.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 targeting_cancelled:
                game_state = previous_game_state
                message_log.add_message(Message('Targeting cancelled.'))

            if interacting_cancelled:
                game_state = previous_game_state
                message_log.add_message(Message('You stop looking around.'))

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

                if leveled_up:
                    message_log.add_message(
                        Message(
                            'Your skills grow more honed. You reach 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 game_state == GameStates.ENEMY_TURN:
            for entity in entities:
                if entity.ai:
                    if wait:
                        enemy_turn_results = entity.ai.approach_player_on_wait(
                            player, fov_map, game_map, entities)
                    else:
                        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
Exemple #31
0
def play_game(player, entities, game_map, message_log, game_state, con, panel, constants):
	# Intialize FOV map.
	fov_recompute = True # Recompute FOV after the player moves
	fov_map = initialize_fov(game_map)
	target_fov_map = initialize_fov(game_map)
	fov_map_no_walls = initialize_fov(game_map)


	# Capture keyboard and mouse input
	key = libtcod.Key()
	mouse = libtcod.Mouse()
	game_state = GameStates.PLAYERS_TURN
	previous_game_state = game_state

	# Store the item that the player used to enter targeting mode (ie lightning scroll). This is so that we know what item we need to remove from inventory etc.
	targeting_item = None
	cursor_radius = 1

	# For showing object descriptions
	description_recompute = True
	description_list = []
	description_index = 0	
	prev_mouse_y = None
	prev_mouse_x = None

	# Start music
	mixer.init()
	mixer.music.load(os.path.join(definitions.ROOT_DIR, 'data', 'music', 'bgm2.mp3'))
	#mixer.music.play(loops=-1)

	#Our main loop
	while not libtcod.console_is_window_closed():
		# Check for input
		libtcod.sys_check_for_event(libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, key, mouse)
		for animator in Animator.animators:
			animator.update()
		if Animator.blocking > 0:
			if not game_state == GameStates.BLOCKING_ANIMATION:
				previous_game_state = game_state
			game_state = GameStates.BLOCKING_ANIMATION

		if Animator.blocking == 0 and game_state == GameStates.BLOCKING_ANIMATION:
				game_state = previous_game_state

		# Recompute FOV
		if fov_recompute:
			recompute_fov(fov_map, player.x, player.y, constants['fov_radius'], constants['fov_light_walls'], constants['fov_algorithm'])
			recompute_fov(fov_map_no_walls, player.x, player.y, constants['fov_radius'], light_walls=False, algorithm=constants['fov_algorithm'])
		
	
		# Show object descriptions
		if description_recompute == True:

			for entity in entities:

				if (prev_mouse_x != mouse.cx) or (prev_mouse_y != mouse.cy):
					description_list = []
					description_index = 0
				if entity.x == mouse.cx and entity.y == mouse.cy:
					description_list.append(entity)
					prev_mouse_x = mouse.cx
					prev_mouse_y = mouse.cy

			
		if len(description_list) > 0:
			description_recompute = False
			# We need to check to see if the mouse position changed and then clear our description list if it did, otherwise it will keep growing
			if (prev_mouse_x != mouse.cx) or (prev_mouse_y != mouse.cy):
				description_list = []
				description_index = 0
				description_recompute = True
			if mouse.lbutton_pressed:
				description_index += 1
			if description_index > (len(description_list) - 1):
				description_index = 0


		
		# Draw our scene
		render_all(con, panel, mouse, 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'], constants['colors'], game_state, description_list, description_index, cursor_radius, target_fov_map, fov_map_no_walls)
		fov_recompute = False
		libtcod.console_flush()

		# Clear our 'drawing consoles' so we dont leave a trail on the main console screen
		clear_all(con, entities)


		# Store input results
		action = handle_keys(key, game_state)
		mouse_action = handle_mouse(mouse)
		key = libtcod.Key()
		mouse = libtcod.Mouse()
		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')
		take_stairs = action.get('take_stairs')
		level_up = action.get('level_up')
		show_character_screen = action.get('show_character_screen')
		ability_1 = action.get('ability_1')
		exit = action.get('exit')
		fullscreen = action.get('fullscreen')
		left_click = mouse_action.get('left_click')
		right_click = mouse_action.get('right_click')
		


		#Instatiate our message queue for the players turn
		player_turn_results = []

		# Player Actions
		# Move
		if move and game_state == GameStates.PLAYERS_TURN:
			if not move == 'wait':
				dx, dy = move
				destination_x = player.x + dx
				destination_y = player.y + dy

				# Check to see if the location we want to move to is blocked by a wall or inhabited by a creature
				if not game_map.is_blocked(destination_x, destination_y):
					target = get_blocking_entities_at_location(entities, destination_x, destination_y)

					# If blocked by a creature, attack
					if target:
						attack_results = player.fighter.attack(target)
						player_turn_results.extend(attack_results)
					# Otherwise, move.
					else:
						player.move(dx, dy)
						fov_recompute = True
					game_state = GameStates.ENEMY_TURN
			else:
				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))
		#Ability complete checks:
		for ability in player.abilities:
			if player.animator.caller == ability and player.animator.complete:
				player_turn_results.extend(ability.use(complete=True))
				player.animator.caller = None
				player.animator.complete = None

		if ability_1:
			player_turn_results.extend(player.abilities[0].use())


		if show_inventory:
			if game_state != GameStates.SHOW_INVENTORY:
				previous_game_state = game_state
			player.inventory.sort_items()
			game_state = GameStates.SHOW_INVENTORY

		if drop_inventory:
			if game_state != GameStates.DROP_INVENTORY:
				previous_game_state = game_state
			game_state = GameStates.DROP_INVENTORY

		#Use or drop item in 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, constants)
					fov_map = initialize_fov(game_map)
					target_fov_map = initialize_fov(game_map)
					fov_map_no_walls = 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.con += 1
				message_log.add_message(Message('Your Constitution has increased by 1!', libtcod.yellow))
			elif level_up == 'str':
				player.fighter.base_power += 1
				message_log.add_message(Message('Your Strength has increased by 1!', libtcod.yellow))
			elif level_up == 'def':
				player.fighter.base_defense += 1
				message_log.add_message(Message('Your Defense has increased by 1!', libtcod.yellow))

			hp_increase = randint(player.fighter.hitdie[0], player.fighter.hitdie[1]) + int((player.fighter.con - 10) / 2)
			player.fighter.base_max_hp += hp_increase
			player.fighter.hp += hp_increase
			message_log.add_message(Message('Your HP has increased by {0}'.format(hp_increase) + '!', libtcod.yellow))
			game_state = previous_game_state

		if show_character_screen:
			if not game_state == GameStates.CHARACTER_SCREEN:
				previous_game_state = game_state
			game_state = GameStates.CHARACTER_SCREEN

		if game_state == GameStates.TARGETING:

			if hasattr(targeting_item, 'item'):
				cursor_radius = targeting_item.item.function_kwargs.get('radius')
			else:
				cursor_radius = targeting_item.function_kwargs.get('radius')
			if left_click:
				target_x, target_y = left_click
				if hasattr(targeting_item, 'item'):
					item_use_results = player.inventory.use(targeting_item, entities=entities, fov_map=fov_map, target_fov_map=target_fov_map,target_x=target_x, target_y=target_y)
				else:
					item_use_results = targeting_item.use(entities=entities, fov_map=fov_map, target_fov_map=target_fov_map,target_x=target_x, target_y=target_y)
				player_turn_results.extend(item_use_results)
				cursor_radius = 1
			
			elif right_click:
				player_turn_results.append({'targeting_cancelled': True})
				cursor_radius = 1		
						
		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})
				cursor_radius = 1
			else:
				save_game(player, entities, game_map, message_log, game_state)
				return True


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

		# Check player message queue and react accordingly
		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')
			equip = player_turn_result.get('equip')
			targeting = player_turn_result.get('targeting')
			targeting_cancelled = player_turn_result.get('targeting_cancelled')
			ability_used = player_turn_result.get("ability_used")
			xp = player_turn_result.get('xp')

			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
				if hasattr(targeting_item, 'item'):
					message_log.add_message(targeting_item.item.targeting_message)
				else:
					message_log.add_message(targeting_item.targeting_message)

			if ability_used:
				if Animator.blocking == 0:
					game_state = GameStates.ENEMY_TURN

			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 removed the {0}'.format(dequipped.name)))

				game_state = GameStates.ENEMY_TURN

			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))
					if (player.level.current_level % 2) == 0:
						previous_game_state = game_state
						game_state = GameStates.LEVEL_UP
					else:
						hp_increase = randint(player.fighter.hitdie[0], player.fighter.hitdie[1]) + int((player.fighter.con - 10) / 2)
						player.fighter.base_max_hp += hp_increase
						player.fighter.hp += hp_increase
						message_log.add_message(Message('Your HP has increased by {0}'.format(hp_increase) + '!', libtcod.yellow))


		# 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)

					# Capture enemy turn message queue, analyze and react accordingly.
					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