Пример #1
0
def get_targeting_radius(con, panel, x, y, entities, player, game_map, fov_map,
                         fov_recompute, message_log, screen_width,
                         screen_height, bar_width, panel_height, panel_y,
                         mouse, colors, game_state, camera, left_click,
                         right_click, animation_console):

    #여기서부터 커서
    libtcod.console_set_char_background(animation_console, x, y,
                                        libtcod.dark_yellow)
    libtcod.console_blit(animation_console, 0, 0, screen_width, screen_height,
                         0, 0, 0)
    libtcod.console_flush()

    #마우스 위치 변경 감지시 클리어

    if mouse.dcx != 0 or mouse.dcy != 0 or mouse.dcx != 0 and mouse.dcy != 0:
        libtcod.console_clear(animation_console)

    #왼클릭 올 오른클릭 감지시 좌표 리턴
    if handle_mouse(mouse).get('left_click'):
        left_click = (x, y)
        return left_click
    elif handle_mouse(mouse).get('right_click'):
        right_click = (x, y)
        return right_click
    #다음 좌표 변경까지 0.1초 대기(깜빡임 방지)
    sleep(0.1)
    libtcod.console_clear(animation_console)
Пример #2
0
def main():
    # Sets font to file path, this specifies the chars we are able to use
    libtcod.console_set_custom_font('../font_custom.png', libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_ASCII_INROW)

    # create the screen
    libtcod.console_init_root(SCREEN_WIDTH, SCREEN_HEIGHT, 'Map Creator', False, vsync=False)

    # create a console
    con = libtcod.console.Console(SCREEN_WIDTH, SCREEN_HEIGHT)

    # limit fps so the game doesn't take up 100% cpu
    libtcod.sys_set_fps(60)

    # don't show mouse
    libtcod.mouse_show_cursor(False)

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

    # game loop
    while not libtcod.console_is_window_closed():
        # update key and mouse variables for event
        libtcod.sys_check_for_event(libtcod.EVENT_KEY_PRESS, key, mouse)

        # draws the JSON map that's defined already
        draw_all_map_objects(con)

        # also draws borders, handles JSON map drawing
        handle_mouse(con, mouse)

        libtcod.console_flush()

        # check for keyboard input
        action = handle_keys(con, key)

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

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

        if exit_game:
            return True
Пример #3
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()

    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
Пример #4
0
def main():
    screen_width = 80
    screen_height = 50

    bar_width = 20
    panel_height = 7
    panel_y = screen_height - panel_height

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

    map_width = 80
    map_height = 43

    room_max_size = 10
    room_min_size = 6
    max_rooms = 50

    fov_algorithm = 5
    fov_light_walls = True
    fov_radius = 10

    max_monster_per_room = 3
    max_items_per_room = 2

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

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

    tcod.console_set_custom_font(
        "BBT\\fonts\\arial12x12.png",
        tcod.FONT_TYPE_GRAYSCALE | tcod.FONT_LAYOUT_TCOD)
    tcod.console_init_root(screen_width, screen_height, 'Battle Theater',
                           False)

    con = tcod.console_new(screen_width, screen_height)
    panel = tcod.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_monster_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 = tcod.Key()
    mouse = tcod.Mouse()

    game_state = GameStates.PLAYERS_TURN
    previous_game_state = game_state

    targeting_item = None

    # 游戏主循环
    while not tcod.console_is_window_closed():

        tcod.sys_check_for_event(tcod.EVENT_KEY_PRESS | tcod.EVENT_MOUSE, key,
                                 mouse)

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

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

        fov_recompute = False

        tcod.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_clikc = mouse_action.get('right_click')

        player_turn_results = []

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

                    fov_recompute = True

                game_state = GameStates.ENEMY_TURN

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

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

        if show_inventory:
            previous_game_state = game_state
            game_state = GameStates.SHOW_INVENTORY

        if drop_inventory:
            previous_game_state = game_state
            game_state = GameStates.DROP_INVENTORY

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

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

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

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

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

            if message:
                message_log.add_message(message)

            if targeting_cancelled:
                game_state = previous_game_state

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

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

            if item_added:
                entities.remove(item_added)

                game_state = GameStates.ENEMY_TURN

            if item_consumed:
                game_state = GameStates.ENEMY_TURN

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

                targeting_item = targeting

                message_log.add_message(targeting_item.item.targeting_message)

            if item_dropped:
                entities.append(item_dropped)

                game_state = GameStates.ENEMY_TURN

        if game_state == GameStates.ENEMY_TURN:
            for entity in entities:
                if entity.ai:
                    enemy_turn_results = entity.ai.take_turn(
                        player, fov_map, game_map, entities)
                    for enemy_turn_result in enemy_turn_results:
                        message = enemy_turn_result.get('message')
                        dead_entity = enemy_turn_result.get('dead')

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

                            if game_state == GameStates.PLAYER_DEAD:
                                break
                    if game_state == GameStates.PLAYER_DEAD:
                        break
            else:
                game_state = GameStates.PLAYERS_TURN
Пример #5
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.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
Пример #6
0
def play_game(player, entities, game_map, message_log, game_state, constants,
              con, panel):
    fov_recompute = True

    fov_map = initialize_fov(game_map)

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

    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["colours"], 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")
        inventory_index = action.get("inventory_index")
        drop_inventory = action.get("drop_inventory")
        take_stairs = action.get("take_stairs")
        level_up = action.get("level_up")
        show_character_screen = action.get("show_character_screen")
        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.ENEMIES_TURN

        elif wait:
            game_state = GameStates.ENEMIES_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 pick up here!",
                            libtcod.yellow))

        if show_inventory:
            previous_game_state = game_state
            game_state = GameStates.SHOWING_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.SHOWING_INVENTORY:
                player_turn_results.extend(
                    player.inventory.use(item,
                                         entities=entities,
                                         fov_map=fov_map))
            elif game_state == GameStates.DROPPING_INVENTORY:
                player_turn_results.extend(player.inventory.drop_item(item))

        if drop_inventory:
            previous_game_state = game_state
            game_state = GameStates.DROPPING_INVENTORY

        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.SHOWING_INVENTORY,
                              GameStates.DROPPING_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("equipped")
            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.ENEMIES_TURN

            if item_dropped:
                entities.append(item_dropped)

                game_state = GameStates.ENEMIES_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.ENEMIES_TURN

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

                targeting_item = targeting

                message_log.add_message(targeting_item.item.targeting_message)

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

            if item_consumed:
                game_state = GameStates.ENEMIES_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(
                            "You leveled up to level {0}".format(
                                player.level.current_level) + "!",
                            libtcod.yellow))
                    previous_game_state = game_state
                    game_state = GameStates.LEVELED_UP

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

                    if enemy_turn_results:
                        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
Пример #7
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
Пример #8
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
Пример #9
0
def main():
    # Screen size
    screen_width = 80
    screen_height = 50
    # UI settings
    bar_width = 20
    panel_height = 7
    panel_y = screen_height - panel_height
    message_x = bar_width + 2
    message_width = screen_width - bar_width - 2
    message_height = panel_height - 1
    # Map size
    map_width = 80
    map_height = 43
    # Room definitions
    max_rooms = 30
    room_min_size = 6
    room_max_size = 10
    # FoV configurations
    fov_algorithm = 0  # use defualt algorithm
    fov_light_walls = True  # light up walls we can see
    fov_radius = 10  # radius of view
    fov_recompute = True  # flag to trigger FoV computations
    # Monster spawning settings
    max_monsters_per_room = 3
    # Define colors to be used in FoV
    colors = {
        "dark_wall": libtcod.Color(0, 0, 100),
        "dark_ground": libtcod.Color(50, 50, 150),
        "light_wall": libtcod.Color(130, 110, 50),
        "light_ground": libtcod.Color(200, 180, 50),
    }
    # Font settings
    libtcod.console_set_custom_font(
        "arial10x10.png",
        libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD)

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

    # For item targeting
    targeting_item = None

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

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

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

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

        # Clear all entities
        clear_all(console, entities)

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

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

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

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

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

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

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

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

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

            else:
                game_state = GameStates.PLAYERS_TURN
Пример #10
0
def get_player_tooltip(animation_console, x, y, mouse, screen_width,
                       screen_height):
    libtcod.console_set_default_background(animation_console, (0, 0, 0))

    if (x, y) in [(6, 10), (7, 10), (8, 10), (9, 10), (10, 10), (11, 10),
                  (12, 10), (13, 10), (14, 10), (15, 10), (16, 10)]:
        libtcod.console_print_frame(animation_console, x + 1, y + 1, 30, 13, 5,
                                    False, 'SP는 인간성을 유지할 수 있게 하는        ')
        libtcod.console_print_frame(animation_console, x + 1, y + 2, 30, 13,
                                    13, False, '정신적인 힘입니다. 0이 되면 죽습니다.       ')
        libtcod.console_print_frame(animation_console, x + 1, y + 3, 30, 13,
                                    13, False, '얻음:오락,음식,종교물,귀중품,선행,시체에서 흡수  ')
        libtcod.console_print_frame(animation_console, x + 1, y + 4, 30, 13,
                                    13, False, '잃음:마법/전투기술 시전, 탐험하며 천천히      ')

    if (x, y) in [(6, 11), (7, 11), (8, 11), (9, 11), (10, 11), (11, 11),
                  (12, 11), (13, 11), (14, 11), (15, 11), (16, 11)]:
        libtcod.console_print_frame(animation_console, x + 1, y + 1, 20, 13, 5,
                                    False, 'DT는 캐릭터에게 가해지는 피해량을')
        libtcod.console_print_frame(animation_console, x + 1, y + 2, 20, 13,
                                    13, False, '고정된 수치만큼 감소시킵니다.   ')
    elif (x, y) in [(6, 12), (7, 12), (8, 12), (9, 12), (10, 12), (11, 12),
                    (12, 12), (13, 12), (14, 12), (15, 12), (16, 12)]:
        libtcod.console_print_frame(animation_console, x + 1, y + 1, 20, 13, 5,
                                    False, 'AC는 얼마나 적의 공격을 얼마나')
        libtcod.console_print_frame(animation_console, x + 1, y + 2, 20, 13,
                                    13, False, '잘 피할 수 있는지를 말합니다.  ')
        libtcod.console_print_frame(animation_console, x + 1, y + 3, 20, 13,
                                    13, False, '기본 수치는 10+민첩입니다.   ')

    elif (x, y) in [(6, 13), (7, 13), (8, 13), (9, 13), (10, 13), (11, 13),
                    (12, 13), (13, 13), (14, 13), (15, 13), (16, 13)]:
        libtcod.console_print_frame(animation_console, x + 1, y + 1, 20, 13, 5,
                                    False, '인내 방어는 독,몸싸움,감염 등의')
        libtcod.console_print_frame(animation_console, x + 1, y + 2, 20, 13,
                                    13, False, '난관들을 신체적인 강인함으로   ')
        libtcod.console_print_frame(animation_console, x + 1, y + 3, 20, 13,
                                    13, False, '극복할 수 있는 정도를 말합니다.   ')
        libtcod.console_print_frame(animation_console, x + 1, y + 4, 20, 13,
                                    13, False, '기본 수치는 (힘+건강)/2입니다.')

    elif (x, y) in [(6, 14), (7, 14), (8, 14), (9, 14), (10, 14), (11, 14),
                    (12, 14), (13, 14), (14, 14), (15, 14), (16, 14)]:
        libtcod.console_print_frame(animation_console, x + 1, y + 1, 21, 13, 5,
                                    False, '반사 신경은 폭발 등의 공격    ')
        libtcod.console_print_frame(animation_console, x + 1, y + 2, 21, 13,
                                    13, False, '들을 빠른 발걸음과 반응속도로   ')
        libtcod.console_print_frame(animation_console, x + 1, y + 3, 21, 13,
                                    13, False, '회피할 수 있는 정도를 말합니다.    ')
        libtcod.console_print_frame(animation_console, x + 1, y + 4, 21, 13,
                                    13, False, '기본 수치는 (민첩+건강)/2입니다.')

    elif (x, y) in [(6, 15), (7, 15), (8, 15), (9, 15), (10, 15), (11, 15),
                    (12, 15), (13, 15), (14, 15), (15, 15), (16, 15)]:
        libtcod.console_print_frame(animation_console, x + 1, y + 1, 21, 13, 5,
                                    False, '의지 방어는 캐릭터에게 부정적인   ')
        libtcod.console_print_frame(animation_console, x + 1, y + 2, 21, 13,
                                    13, False, '영향을 끼치는 마법들을 저항할   ')
        libtcod.console_print_frame(animation_console, x + 1, y + 3, 21, 13,
                                    13, False, '수 있는 정도를 말합니다.     ')
        libtcod.console_print_frame(animation_console, x + 1, y + 4, 21, 13,
                                    13, False, '기본 수치는 (지능+건강)/2입니다.')

    libtcod.console_blit(animation_console, 0, 0, screen_width, screen_height,
                         0, 0, 0)
    libtcod.console_flush()

    if mouse.dcx != 0 or mouse.dcy != 0 or mouse.dcx != 0 and mouse.dcy != 0:
        libtcod.console_clear(animation_console)

    if handle_mouse(mouse).get('left_click'):
        left_click = (x, y)
        return left_click

    sleep(0.3)
    libtcod.console_clear(animation_console)
Пример #11
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
Пример #12
0
def play_game(player, entities, game_map, message_log, game_state, con, panel,
              constants):
    # Whether to recompute the fov (Would be false if the player didn't move that turn).
    # True by default because we have to compute it when the game starts.
    fov_recompute = True
    # Computes the fov_map
    fov_map = initialise_fov(game_map)

    # Stores the keyboard and mouse input. This will be updated throughout the game loop.
    key = libtcod.Key()
    mouse = libtcod.Mouse()

    # Stores the previous game state. Used for changing gamestate and reverting without wasting a turn.
    # e.g when opening the inventory.
    previous_game_state = game_state

    # Stores which item requires targeting.
    targeting_item = None

    ############################################################
    # GAME LOOP
    ############################################################
    while not libtcod.console_is_window_closed():
        # Captures input - will update key and mouse variables with the input.
        libtcod.sys_check_for_event(
            libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, key, mouse)

        # Recomputes the FOV if necessary.
        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, constants["fov_radius"],
                          constants["fov_light_walls"],
                          constants["fov_algorithm"])

        # Draws all entities to the off-screen console and blits the console to the root.
        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)

        # Don't recompute the fov/repaint the tiles until after the player moves.
        fov_recompute = False

        # Flushes/draws the screen.
        libtcod.console_flush()

        # Erases all characters on the off-screen console.
        clear_all(con, entities)

        ##### REACTS TO A KEY PRESS OR A MOUSE CLICK #####
        action = handle_keys(key, game_state)
        mouse_action = handle_mouse(mouse)

        # Stores the value/s returned from dictionary key.
        # Performs an action if one of the variables is not empty.

        # Key presses:
        move = action.get("move")
        wait = action.get("wait")
        pickup = action.get("pickup")
        show_inventory = action.get("show_inventory")
        drop_inventory = action.get(
            "drop_inventory"
        )  # An inventory screen where you can only drop items.
        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")

        # Mouse clicks:
        left_click = mouse_action.get("left_click")
        right_click = mouse_action.get("right_click")

        ########## PLAYER'S TURN ##########

        # Stores the results from the player's turn.
        # Each index defines what action should be taken.
        player_turn_results = []

        if move and game_state == GameStates.PLAYERS_TURN:
            # Stores the coordinates to move to.
            dx, dy = move
            destination_x = player.x + dx
            destination_y = player.y + dy
            # Alters the player's position by dx/dy amount if the destination is not a blocked tile.
            if not game_map.is_blocked(destination_x, destination_y):
                # Stores the blocking entity if the destination if there is one.
                target = get_blocking_entities_at_location(
                    entities, destination_x, destination_y)
                # If there is a blocking entity:
                if target:
                    # Stores the attack results.
                    attack_results = player.fighter.attack(target)
                    player_turn_results.extend(attack_results)
                # If there is no blocking entity the player will move.
                else:
                    player.move(dx, dy)
                    # Recomputes the FOV map now the player has moved.
                    fov_recompute = True

            # Sets the game state to the enemy's turn.
            game_state = GameStates.ENEMY_TURN

        elif wait:
            game_state = GameStates.ENEMY_TURN  # Skips the player's turn.

        # If the pickup button was pressed (g).
        elif pickup and game_state == GameStates.PLAYERS_TURN:
            for entity in entities:
                # If the overlapping entity can be picked up.
                if entity.item and entity.x == player.x and entity.y == player.y:
                    # Adds the item to the inventory and results the results.
                    # Results include a Message and the grabbed Item object.
                    pickup_results = player.inventory.add_item(entity)
                    player_turn_results.extend(pickup_results)

                    # Breaks so we can only pickup one item at a time.
                    break
            else:
                message_log.add_message(
                    Message("There is nothing here to pick up",
                            libtcod.yellow))

        # If 'i' was pressed for inventory it changes the gamestate while storing the previous state.
        if show_inventory:
            previous_game_state = game_state
            game_state = GameStates.SHOW_INVENTORY
        # If 'd' was pressed for the drop inventory.
        if drop_inventory:
            previous_game_state = game_state
            game_state = GameStates.DROP_INVENTORY

        # Selects an item in the inventory using the index value of the 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 the SHOW_INVENTORY state, the item will be used.
            if game_state == GameStates.SHOW_INVENTORY:
                player_turn_results.extend(
                    player.inventory.use(item,
                                         entities=entities,
                                         fov_map=fov_map))
            # If the DROP_INVENTORY state, the item will be dropped.
            elif game_state == GameStates.DROP_INVENTORY:
                player_turn_results.extend(player.inventory.drop_item(item))

        # If the player has attempted to move down some stairs.
        if take_stairs and game_state == GameStates.PLAYERS_TURN:
            for entity in entities:
                # If the player IS on the same tile as the stairs.
                if entity.stairs and entity.x == player.x and entity.y == player.y:
                    # Creates a new dungeon floor and returns and stores a new set of entities for the new floor.
                    entities = game_map.next_floor(player, message_log,
                                                   constants)
                    # Initialises the fov mapf or the new floor.
                    fov_map = initialise_fov(game_map)
                    fov_recompute = True
                    # Clears the console of the old game map.
                    libtcod.console_clear(con)
                    # Prevents other entities from being checked.
                    break
                else:
                    message_log.add_message(
                        Message("There are no stairs here.", libtcod.yellow))

        # Upgrades one of the player's stats on level up then return to previous game state.
        if level_up:
            if level_up == "hp":
                player.fighter.base_max_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 the game state has bene set to tarrgeting mode it will check if any left or right clicks have been made
        # Left clicks use the item stored in 'targeting_item' and will extend the results to player_turn_results.
        # Right click appends 'targeting_cancelled'. to the player results.
        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})

        # Exits the game. UNLESS a menu is open then it just closes the menu.
        if exit:
            if game_state in (GameStates.SHOW_INVENTORY,
                              GameStates.DROP_INVENTORY,
                              GameStates.CHARACTER_SCREEN):
                game_state = previous_game_state
            # If the user is targeting ESC only exist the targeting game state.
            elif game_state == GameStates.TARGETING:
                player_turn_results.append({'targeting_cancelled': True})
            # Saves the game and exits the game.
            else:
                save_game(player, entities, game_map, message_log, game_state)
                return True

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

        ### Acts on player's turn results including adding to message log. ###
        for player_turn_result in player_turn_results:
            message = player_turn_result.get("message")
            dead_entity = player_turn_result.get("dead")
            item_added = player_turn_result.get("item_added")
            item_consumed = player_turn_result.get("consumed")
            item_dropped = player_turn_result.get("item_dropped")
            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 the dead entity is the player.
                # Gamestate will be set to PLAYER_DEAD
                if dead_entity == player:
                    message, game_state = kill_player(dead_entity)

                # If the dead entity is not the player it will be killed.
                else:
                    message = kill_monster(dead_entity)

                # Prints one of the messages.
                message_log.add_message(message)

            # If an item was picked up it removes it from the entity list and sets the game state to enemy turn.
            # (The entity is no longer on the map so it is removed)
            if item_added:
                entities.remove(item_added)

                game_state = GameStates.ENEMY_TURN

            # Consuming an item triggers the enemy turn.
            if item_consumed:
                game_state = GameStates.ENEMY_TURN

            # Switches the game state to TARGETING, stores the targeting item and adds the targeting message to the log.
            if targeting:
                # Changes the previous game state to PLAYERS_TURN rather than INVENTORY so that cancelling the targeting
                # mode (with ESC) returns the playher back to the main console rather than the inventory screen.
                previous_game_state = GameStates.PLAYERS_TURN
                game_state = GameStates.TARGETING
                targeting_item = targeting
                message_log.add_message(targeting_item.item.targeting_message)

            # If the user cancelled targeting the previous state will be reverted.
            if targeting_cancelled:
                game_state = previous_game_state
                message_log.add_message(Message("Targeting cancelled"))

            if xp:
                leveled_up = player.level.add_xp(
                    xp)  # Will be True if the player leveled up.
                message_log.add_message(
                    Message("You gain {0} experience points".format(xp)))

                if leveled_up:
                    message_log.add_message(
                        Message(
                            "Your experience enhances your abilities - you reached level {0}!"
                            .format(player.level.current_level),
                            libtcod.yellow))
                    previous_game_state = game_state
                    game_state = GameStates.LEVEL_UP

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

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

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

                    if equipped:
                        message_log.add_message(
                            Message("You equipped the {}".format(
                                equipped.name)))
                    if dequipped:
                        message_log.add_message(
                            Message("You dequipped the {}".format(
                                dequipped.name)))

                game_state = GameStates.ENEMY_TURN  # Equipping or dequipping uses a turn.

        ########## ENEMY's TURN ##########
        if game_state == GameStates.ENEMY_TURN:
            for entity in entities:
                # If the entity has the ai component.
                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 the dead entity is the player.
                            # Gamestate will be set to PLAYER_DEAD
                            if dead_entity == player:
                                message, game_state = kill_player(dead_entity)
                            # If the monster killed another monster.
                            else:
                                message = kill_monster(dead_entity)

                            # Prints one of the death messages.
                            message_log.add_message(message)

                            # Prevents the else/player's turn from occurring again by breaking the for loop.
                            if game_state == GameStates.PLAYER_DEAD:
                                break

                    # Prevents the else/player's turn from occurring again by breaking the for loop.
                    if game_state == GameStates.PLAYER_DEAD:
                        break
            # If break wasn't called do this:
            else:
                # Sets the game state to the player's turn.
                game_state = GameStates.PLAYERS_TURN
Пример #13
0
def play_game(player, entities, game_map, message_log, game_state, con, panel,
              constants):
    fov_recompute = True  #bool so that we only update fov when we need to
    fov_map = initalize_fov(game_map)
    key = libtcod.Key()
    mouse = libtcod.Mouse()

    previous_game_state = game_state
    targeting_item = None

    ########    GAME LOOP STARTS HERE   #######################################################################################################################################################
    while not libtcod.console_is_window_closed(
    ):  # while the console window is....open??? MAIN GAME LOOP
        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']
                          )  # this is where we do the FOV stuff!

        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['colours'], game_state)
        fov_recompute = False

        libtcod.console_flush(
        )  # this is what actually tells the window to draw I guess

        clear_all(con, entities)
        #####   Action handler   #####
        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 = [
        ]  ## this is the container for the results of the players action during their turn
        ########################################################################################################################################
        if move and game_state == GameStates.PLAYER_TURN:
            dx, dy = move
            destination_x = player.x + dx
            destination_y = player.y + dy
            if not game_map.is_blocked(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  # recalculate feild of view whenver the player moves

                game_state = GameStates.ENEMY_TURN
                ##########################
        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 to pick up.', libtcod.amber))

                ####################################################################################
        if show_inventory:
            previous_game_state = game_state
            game_state = GameStates.SHOW_INVENTORY
            ####################################################################################
        if drop_inventory:
            previous_game_state = game_state
            game_state = GameStates.DROP_INVENTORY
            ####################################################################################
        if inventory_index is not None and previous_game_state != GameStates.PLAYER_DEAD and inventory_index < len(
                player.inventory.items):
            item = player.inventory.items[inventory_index]
            if game_state == GameStates.SHOW_INVENTORY:
                player_turn_results.extend(
                    player.inventory.use(item,
                                         entities=entities,
                                         fov_map=fov_map))
            elif game_state == GameStates.DROP_INVENTORY:
                player_turn_results.extend(player.inventory.drop_item(item))
                ####################################################################################
        if game_state == GameStates.TARGETING:
            if left_click:
                target_x, target_y = left_click
                item_use_results = player.inventory.use(targeting_item,
                                                        entities=entities,
                                                        fov_map=fov_map,
                                                        target_x=target_x,
                                                        target_y=target_y)
                player_turn_results.extend(item_use_results)

            elif right_click:
                player_turn_result.append({'targeting_canceled': True})
                ####################################################################################
        if exit:
            if game_state in (GameStates.SHOW_INVENTORY,
                              GameStates.DROP_INVENTORY):
                game_state = previous_game_state
            elif game_state == GameStates.TARGETING:
                player_turn_results.append({'targeting_canceled': 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_canceled = player_turn_result.get('targeting canceled')

            if message:
                message_log.add_message(message)
            if targeting_canceled:
                game_state = previous_game_state
                message_log.add_message(Message('Targeting canceled'))
            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.PLAYER_TURN  #prev is set ot player turn so that canceling targeting doesnt put you bakc into the inventory
                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.PLAYER_TURN
Пример #14
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")
        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(destination_x, destination_y):
                target = get_blocking_entities_at_location(
                    entities, destination_x, destination_y
                )

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

                    fov_recompute = True

                game_state = GameStates.ENEMY_TURN

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

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

        if show_inventory:
            previous_game_state = game_state
            game_state = GameStates.SHOW_INVENTORY

        if drop_inventory:
            previous_game_state = game_state
            game_state = GameStates.DROP_INVENTORY

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

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

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

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

        if exit:
            if game_state in (GameStates.SHOW_INVENTORY, GameStates.DROP_INVENTORY):
                game_state = previous_game_state
            elif game_state == GameStates.TARGETING:
                player_turn_results.append({"targeting_cancelled": True})
            else:
                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")

            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 game_state == GameStates.ENEMY_TURN:
            for entity in entities:
                if entity.ai:
                    enemy_turn_results = entity.ai.take_turn(
                        player, fov_map, game_map, entities
                    )

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

                        if message:
                            message_log.add_message(message)

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

                            message_log.add_message(message)

                            if game_state == GameStates.PLAYER_DEAD:
                                break

                    if game_state == GameStates.PLAYER_DEAD:
                        break
            else:
                game_state = GameStates.PLAYERS_TURN
Пример #15
0
def play_game(game_map, map_surf, camera, player, entities, screen, manager,
              screen_health_bar, entity_info, game_state):
    fov_radius = 8
    fov_recompute = True
    fov_map = initialize_fov(game_map)

    clock = pygame.time.Clock()

    previous_game_state = game_state

    targeting_item = None

    running = True
    while (running):
        time_delta = clock.tick(60) / 1000.0

        #check events
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                save_game(player, entities, game_map, camera, game_state)
                running = False

            manager.gui.process_events(event)

            action = handle_keys(event, game_state)
            mouse_action = handle_mouse(event)
            button_action = handle_inventory_buttons(event, game_state,
                                                     manager.inventory_menu)
            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")
            if inventory_index is None:
                inventory_index = button_action.get("inventory_index")
            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 = action["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

            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:
                    manager.add_to_message_log(
                        Message('There is nothing here to pick up.'))

            elif show_inventory:
                previous_game_state = game_state
                game_state = GameStates.SHOW_INVENTORY

            elif 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
                    target_x, target_y = get_map_coords(
                        target_x, target_y, map_surf.width // camera.width,
                        map_surf.height // camera.height, camera, map_surf)

                    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 action.get("exit"):
                if game_state in (GameStates.SHOW_INVENTORY,
                                  GameStates.DROP_INVENTORY):
                    game_state = previous_game_state
                elif game_state == GameStates.TARGETING:
                    player_turn_results.append({'targeting_cancelled': True})
                else:
                    save_game(player, entities, game_map, camera, game_state)
                    running = False

            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:
                    manager.add_to_message_log(message)

                if dead_entity:
                    if dead_entity == player:
                        message, game_state = kill_player(dead_entity)
                        game_state = GameStates.PLAYER_DEAD
                    else:
                        message = kill_monster(dead_entity)
                    manager.add_to_message_log(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

                    manager.add_to_message_log(
                        targeting_item.item.targeting_message)

                if targeting_cancelled:
                    game_state = previous_game_state

                    manager.add_to_message_log(Message('Targeting cancelled'))

            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:
                                manager.add_to_message_log(message)
                            if dead_entity:
                                if dead_entity == player:
                                    message, game_state = kill_player(
                                        dead_entity)
                                else:
                                    message = kill_monster(dead_entity)

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

        # TO DO: process events

        # reset fov and render
        if fov_recompute:
            fov_map = recompute_fov(game_map, player.x, player.y, fov_radius)

        fov_recompute = False

        manager.update(time_delta)

        camera.update()

        render_all(game_map, map_surf, camera, fov_map, fov_radius, player,
                   entities, screen, manager, screen_health_bar, entity_info,
                   game_state)
Пример #16
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
Пример #17
0
def play_game():
    screen_width = 70
    screen_height = 45

    bar_width = 20

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

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

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

    map_width = 47
    map_height = panel_horiz_y

    room_max_size = 8
    room_min_size = 3
    max_rooms = 30

    fov_algorithm = 0
    fov_light_walls = True
    fov_radius = 10

    max_monsters_per_room = 3
    max_items_per_room = 2

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

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

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

    entities = [player]

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

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

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

    con = libtcod.console_new(screen_width, screen_height)

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

    fov_recompute = True

    fov_map = initialize_fov(game_map)

    message_log = MessageLog(message_x, message_width, message_height)

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

    game_state = GameStates.PLAYERS_TURN
    previous_game_state = game_state

    targeting_item = None

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

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

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

        fov_recompute = False

        libtcod.console_flush()

        clear_all(con, entities)

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

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

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

        player_turn_results = []

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

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

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

                        fov_recompute = True
                    game_state = GameStates.ENEMY_TURN

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

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

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

        if show_inventory:
            previous_game_state = game_state
            game_state = GameStates.SHOW_INVENTORY

        if drop_inventory:
            previous_game_state = game_state
            game_state = GameStates.DROP_INVENTORY

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

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

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

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

            game_state = previous_game_state

        if show_character_screen:
            previous_game_state = game_state
            game_state = GameStates.CHARACTER_SCREEN

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

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

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

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

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

            if message:
                message_log.add_message(message)

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

                message_log.add_message(message)

            if item_added:
                entities.remove(item_added)

                game_state = GameStates.ENEMY_TURN

            if item_consumed:
                game_state = GameStates.ENEMY_TURN

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

                targeting_item = targeting

                message_log.add_message(targeting_item.item.targeting_message)

            if targeting_cancelled:
                game_state = previous_game_state

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

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

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

            if item_dropped:
                entities.append(item_dropped)

                game_state = GameStates.ENEMY_TURN

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

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

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

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

                game_state = GameStates.ENEMY_TURN

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

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

                        if message:
                            message_log.add_message(message)

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

                            message_log.add_message(message)

                            if game_state == GameStates.PLAYER_DEAD:
                                break

                    if game_state == GameStates.PLAYER_DEAD:
                        break
            else:
                game_state = GameStates.PLAYERS_TURN
Пример #18
0
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
Пример #19
0
def play_game(player, entities, game_map, message_log, game_state, con,
            panel, constants):
    '''
    Main engine and executor of code
    '''
    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():

        if game_map.dungeon_level == 51:
            end_game(player)

        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)

        # checks for actions
        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')
        show_rules_screen = action.get('show_rules_screen')
        shop = action.get('shop')
        shop_sell = action.get('shop_sell')
        shop_buy = action.get('shop_buy')
        sell_index = action.get('sell_index')
        buy_index = action.get('buy_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 = []

        # player moving
        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

        # player waiting
        elif wait:
            game_state = GameStates.ENEMY_TURN

        # player tries to pick up item
        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))

        # player shows inventory menu
        if show_inventory:
            previous_game_state = game_state
            game_state = GameStates.SHOW_INVENTORY

        # player shows inventory menu
        if drop_inventory:
            previous_game_state = game_state
            game_state = GameStates.DROP_INVENTORY

        # player selects object from 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))

        # player tries to take stairs
        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))
        # player levels up
        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

        # player opens character screen
        if show_character_screen:
            previous_game_state = game_state
            game_state = GameStates.CHARACTER_SCREEN

        # player opens rules screen
        if show_rules_screen:
            previous_game_state = game_state
            game_state = GameStates.RULES

        # player tries to target
        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})

        # player tries to enter shop
        if shop and game_state == GameStates.PLAYERS_TURN:
            for entity in entities:
                if entity.shopkeep and entity.x == player.x and entity.y == player.y:
                    previous_game_state = game_state
                    game_state = GameStates.ENTER_SHOP

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

        # player tries to sell
        if shop_sell:
            game_state = GameStates.SELLING

        # player tries to sell item at shop
        if sell_index is not None and previous_game_state != GameStates.PLAYER_DEAD and\
                game_state == GameStates.SELLING and sell_index < len(player.inventory.items):

            for entity in entities:
                if entity.shopkeep:
                    item_cost = player.inventory.items[sell_index].cashable.coin
                    player.fighter.coin += (item_cost // 10)
                    message_log.add_message(Message('You sell {0}for {1} coins.'\
                        .format(player.inventory.items[sell_index].name.split('(')[0],
                        (item_cost // 10)), libtcod.blue))
                    player.inventory.remove_item(player.inventory.items[sell_index])

                    break

        # player tries to buy
        if shop_buy:
            game_state = GameStates.BUYING

        # player tries to buy item at shop
        if buy_index is not None and previous_game_state != GameStates.PLAYER_DEAD and\
                game_state == GameStates.BUYING and buy_index < 25:

            for entity in entities:
                if entity.shopkeep:
                    player_coin = player.fighter.coin
                    item_cost = entity.inventory.items[buy_index].cashable.coin
                    if player_coin >= item_cost:
                        player.inventory.add_item(entity.inventory.items[buy_index])
                        player.fighter.coin -= item_cost
                        message_log.add_message(Message('You buy {0}for {1} coins.'\
                            .format(entity.inventory.items[buy_index].name.split('(')[0],
                            item_cost), libtcod.blue))
                    else:
                        message_log.add_message(Message('Not enough coins!',
                            libtcod.yellow))

                    break

        # exit menu or game
        if exit:
            if game_state in (GameStates.SHOW_INVENTORY, GameStates.DROP_INVENTORY,
                    GameStates.CHARACTER_SCREEN, GameStates.RULES):
                game_state = previous_game_state
            elif game_state == GameStates.TARGETING:
                player_turn_results.append({'targeting_cancelled': True})
            elif game_state == GameStates.ENTER_SHOP:
                game_state = GameStates.PLAYERS_TURN
            elif game_state in (GameStates.SELLING, GameStates.BUYING):
                game_state = GameStates.ENTER_SHOP
            else:
                save_game(player, entities, game_map, message_log, game_state)

                return True

        # toggle fullscreen
        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')
            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')
            coin = player_turn_result.get('coin')

            # adds message to log
            if message:
                message_log.add_message(message)

            # deals with dead entity
            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)

            # item picked up
            if item_added:
                entities.remove(item_added)

                game_state = GameStates.ENEMY_TURN

            # item used
            if item_consumed:
                game_state = GameStates.ENEMY_TURN

            # item dropped
            if item_dropped:
                entities.append(item_dropped)

                game_state = GameStates.ENEMY_TURN

            # item equip toggled
            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.split('(')[0])))

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

                game_state = GameStates.ENEMY_TURN

            # something targeted
            if targeting:
                previous_game_state = GameStates.PLAYERS_TURN
                game_state = GameStates.TARGETING

                targeting_item = targeting

                message_log.add_message(targeting_item.item.targeting_message)

            # targeting cancelled
            if targeting_cancelled:
                game_state = previous_game_state

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

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

                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

            # gained coins
            if coin:
                player.fighter.add_coin(coin)
                message_log.add_message(Message('You gain {0} coins.'\
                    .format(coin), libtcod.orange))
        # enemy takes 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')

                        # adds message to log
                        if message:
                            message_log.add_message(message)

                        # checks for dead entity
                        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 player is dead, we're done
                            if game_state == GameStates.PLAYER_DEAD:
                                break

                    # if player is dead, we're done
                    if game_state == GameStates.PLAYER_DEAD:
                        break
            # player's turn again
            else:
                game_state = GameStates.PLAYERS_TURN
Пример #20
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
Пример #21
0
def main():
    # Needed Variables
    screen_width = 80
    screen_height = 50
    map_width = 80
    map_height = 43

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

    # rooms
    room_max_size = 10
    room_min_size = 6
    max_rooms = 30

    # fov
    fov_algorithm = 0
    fov_light_walls = True
    fov_radius = 10

    # monsters
    max_monsters_per_room = 3

    # items
    max_items_per_room = 10

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

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

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

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

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

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

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

    fov_recompute = True
    fov_map = initialize_fov(game_map)

    message_log = MessageLog(message_x, message_width, message_height)

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

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

    targeting_item = None

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

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

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

        fov_recompute = False

        libtcod.console_flush()

        clear_all(console, entities)

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

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

        player_turn_results = []

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

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

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

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

                    fov_recompute = True

                game_state = GameStates.ENEMY_TURN

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

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

        if show_inventory:
            previous_game_state = game_state
            game_state = GameStates.SHOW_INVENTORY

        if drop_inventory:
            previous_game_state = game_state
            game_state = GameStates.DROP_INVENTORY

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

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

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

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

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

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

            if message:
                message_log.add_message(message)

            if targeting_cancelled:
                game_state = previous_game_state

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

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

                message_log.add_message(message)

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

            if item_consumed:
                game_state = GameStates.ENEMY_TURN

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

                targeting_item = targeting

                message_log.add_message(targeting_item.item.targeting_message)

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

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

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

                        if message:
                            message_log.add_message(message)

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

                            message_log.add_message(message)

                        if game_state == GameStates.PLAYER_DEAD:
                            break

                    if game_state == GameStates.PLAYER_DEAD:
                        break

                    else:
                        game_state = GameStates.PLAYERS_TURN
Пример #22
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
Пример #23
0
def play_game(player: Entity, entities: List[Entity], game_map: GameMap,
              message_log: MessageLog, game_state: GameStates,
              root_console: tcod.console.Console, con: tcod.console.Console,
              panel: tcod.console.Console) -> None:
    fov_recompute = True

    fov_map = initialize_fov(game_map)

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

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

    targeting_item = None

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

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

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

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

        fov_recompute = False

        tcod.console_flush()

        clear_all(con, entities)

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

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

        player_turn_results: ActionResults = []

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

                game_state = GameStates.ENEMY_TURN

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

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

        if show_inventory:
            previous_game_state = game_state
            game_state = GameStates.SHOW_INVENTORY

        if drop_inventory:
            previous_game_state = game_state
            game_state = GameStates.DROP_INVENTORY

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

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

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

        if show_character_screen:
            previous_game_state = game_state
            game_state = GameStates.CHARACTER_SCREEN

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

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

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

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

            if message:
                message_log.add_message(message)

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

                message_log.add_message(message)

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

            if item_consumed:
                game_state = GameStates.ENEMY_TURN

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

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

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

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

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

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

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

                        if message:
                            message_log.add_message(message)

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

                            message_log.add_message(message)

                            if game_state == GameStates.PLAYER_DEAD:
                                break

                    if game_state == GameStates.PLAYER_DEAD:
                        break
            else:
                game_state = GameStates.PLAYERS_TURN
Пример #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
Пример #25
0
def play_game(player, entities, game_map, message_log, game_state, con, panel,
              cursor, constants):
    colors = constants['colors']

    fov_recompute = True
    fov_map = initialize_fov(game_map)

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

    game_state = GameStates.PLAYER_TURN
    previous_game_state = game_state

    # Keep track of targeting item
    targeting_item = None

    # === MAIN GAME LOOP ===
    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, cursor, entities, player, game_map, fov_map,
                   fov_recompute, message_log, constants['screen_width'],
                   constants['screen_height'], constants['bar_width'],
                   constants['panel_width'], constants['panel_x'], mouse,
                   constants['colors'], game_state, targeting_item, key)

        fov_recompute = False

        libtcod.console_flush()

        clear_all(con, entities)

        # === PLAYER TURN ===
        # Handle player action
        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')
        show_equipment = action.get('show_equipment')
        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 = []

        # Check what player did this turn
        if move and game_state == GameStates.PLAYER_TURN:
            dx, dy = move
            destination_x = player.x + dx
            destination_y = player.y + dy
            # Check if tile is passable
            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.take_step(dx, dy, game_map)

                    # Recompute FOV everytime the player moves
                    fov_recompute = True

                game_state = GameStates.ENEMY_TURN

        elif wait:
            game_state = GameStates.ENEMY_TURN

        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.',
                            colors['text_warning']))

        if show_inventory:
            previous_game_state = game_state
            game_state = GameStates.SHOW_INVENTORY

        if show_equipment:
            previous_game_state = game_state
            game_state = GameStates.SHOW_EQUIPMENT

        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.SHOW_EQUIPMENT:
                item = player.equipment.equipped[inventory_index]
                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.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)
                    libtcod.console_clear(con)

                    break
            else:
                message_log.add_message(
                    Message('There are no stairs here.',
                            colors['text_warning']))

        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 select_target:
            #     current_x, current_y = player.x, player.y
            #     dx, dy = select_target
            #     new_x, new_y = current_x + dx, current_y + dy

            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.SHOW_EQUIPMENT,
                    GameStates.DROP_INVENTORY, GameStates.CHARACTER_SCREEN
            }:
                game_state = previous_game_state
            elif game_state == GameStates.TARGETING:
                player_turn_results.append({'targeting_cancelled': True})
            elif game_state == GameStates.PLAYER_DEAD:
                # Delete save file if player exits after dying
                if os.path.isfile('savegame.dat'):
                    os.remove('savegame.dat')
                return 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())  # toggle on/off

        # At the end of the player's turn, evaluate results and print messages to log
        for player_turn_result in player_turn_results:
            message = player_turn_result.get('message')
            dead_entity = player_turn_result.get('dead')
            item_added = player_turn_result.get('item_added')
            item_consumed = player_turn_result.get('consumed')
            item_dropped = player_turn_result.get('item_dropped')
            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'))

            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:
                # Remove item from map (now in inventory)
                entities.remove(item_added)
                # Takes a turn
                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')
                    dequipped = equip_result.get('dequipped')

                    if equipped:
                        message_log.add_message(
                            Message(
                                'You equipped the {0}'.format(equipped.name),
                                colors['text_equip']))

                    if dequipped:
                        message_log.add_message(
                            Message(
                                'You dequipped the {0}'.format(dequipped.name),
                                colors['text_unequip']))

                game_state = GameStates.ENEMY_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 item_dropped:
                entities.append(item_dropped)

                game_state = GameStates.ENEMY_TURN

            if xp:
                leveled_up = player.level.add_xp(xp)
                message_log.add_message(
                    Message('You gain {0} experience'.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

        # === MONSTER 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.PLAYER_TURN
Пример #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
Пример #27
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 = tc.Key()
    mouse = tc.Mouse()
    targeting_item = None
    visible_enemies = []
    room_enemies_index = 0
    room_enemies_length = 0
    event = tc.event.get()

    while event != "QUIT":
        # while not tc.console_is_window_closed():
        tc.sys_check_for_event(tc.EVENT_KEY_PRESS | tc.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
        tc.console_flush()
        clear_all(con, entities)

        action = handle_keys(key, game_state)
        mouse_action = handle_mouse(mouse)
        mouse_teleport_action = handle_mouse_teleport(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')
        ranged_index = action.get('ranged_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')
        god_mode = action.get('god_mode')
        show_help_menu = action.get('show_help_menu')
        close_help_menu = action.get('close_help_menu')
        cycle_target = action.get('cycle_target')
        cycle_target_right = action.get('right_target')
        cycle_target_left = action.get('left_target')
        poisoned = action.get('poisoned')
        burning = action.get('burning')
        reveal_map = action.get('reveal_map')
        decrease_limb_damage = action.get('decrease_limb_damage')
        increase_limb_damage = action.get('increase_limb_damage')
        teleport = action.get('teleport')
        mouse_teleport = mouse_teleport_action.get('mouse_teleport')
        ranged = action.get('ranged')
        spawn_enemy_at = action.get('spawn_enemy_at')
        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

                if player.fighter.turns_since_special <= 5:
                    player.fighter.turns_since_special += 1

                game_state = GameStates.ENEMY_TURN

        elif wait:

            if player.fighter.turns_since_special <= 5:
                player.fighter.turns_since_special += 1

            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.', tc.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 show_help_menu:
            previous_game_state = game_state
            game_state = GameStates.SHOW_HELP_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))

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

            if game_state == GameStates.RANGED:
                player_turn_results.extend(
                    player.inventory.use(item,
                                         entities=entities,
                                         fov_map=fov_map))

        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 and entity.stairs.direction == 'down':
                    entities = game_map.next_floor(player, message_log,
                                                   constants)
                    fov_map = initialize_fov(game_map)
                    fov_recompute = True
                    con.clear()
                    break

                elif entity.stairs and entity.x == player.x and entity.y == player.y and entity.stairs.direction == 'up':
                    entities = game_map.previous_floor(player, message_log,
                                                       constants)
                    fov_map = initialize_fov(game_map)
                    fov_recompute = True
                    con.clear()
                    break

                elif entity.area and entity.x == player.x and entity.y == player.y:
                    entities = game_map.load_area(player, message_log,
                                                  constants)
                    fov_map = initialize_fov(game_map)
                    fov_recompute = True
                    con.clear()
                    break

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

        if cycle_target:
            previous_game_state = game_state
            game_state = GameStates.CYCLE_TARGET
            visible_enemies.clear()

            for entity in entities:

                if entity.ai != None:

                    if tc.map_is_in_fov(fov_map, entity.x, entity.y):
                        visible_enemies.append([
                            cycle_target_distance_to(player, entity), entity.x,
                            entity.y, entity.name
                        ])

            if len(visible_enemies) != 0:
                con.default_fg = tc.black
                con.default_fg = tc.white
                con.print(
                    int(constants['screen_width'] / 2), 1,
                    'Press RIGHT arrow or LEFT arrow key to cycle targets or ESCAPE to cancel targeting'
                    .format(), (255, 255, 255), (0, 0, 0), 1, tc.CENTER)
                tc.console_blit(con, 0, 0, constants['screen_width'],
                                constants['screen_height'], 0, 0, 0)
                visible_enemies.sort()
                room_enemies_length = len(visible_enemies)

            else:
                con.print(
                    int(constants['screen_width'] / 2), 1,
                    'There are no enemies present! Press ESCAPE to cancel targeting'
                    .format(), (255, 255, 255), (0, 0, 0), 1, tc.CENTER)

        if cycle_target_right:

            if len(visible_enemies) != 0:
                fov_recompute = True

                con.clear()
                con.default_fg = tc.black
                con.default_fg = tc.white

                con.print(
                    int(constants['screen_width'] / 2), 1,
                    'Press RIGHT arrow or LEFT arrow key to cycle targets or ESCAPE to cancel targeting'
                    .format(), (255, 255, 255), (0, 0, 0), 1, tc.CENTER)
                tc.console_blit(con, 0, 0, constants['screen_width'],
                                constants['screen_height'], 0, 0, 0)

                con.draw_frame((visible_enemies[room_enemies_index][1]) - 1,
                               (visible_enemies[room_enemies_index][2]) - 1,
                               3,
                               3,
                               "",
                               True,
                               fg=tc.white,
                               bg=tc.black)
                con.print((visible_enemies[room_enemies_index][1]) + 1,
                          (visible_enemies[room_enemies_index][2]) - 2,
                          '{0}'.format(visible_enemies[room_enemies_index][3]),
                          (255, 255, 255), (0, 0, 0), 1, tc.CENTER)

                for entity in entities:

                    if tc.map_is_in_fov(fov_map, entity.x, entity.y):

                        if visible_enemies[room_enemies_index][
                                3] == entity.name:
                            names = entity.name
                            names = names + ' ' + Mage.get_stats(
                                entity) + Fighter.get_stats(entity)
                            con.print(
                                (visible_enemies[room_enemies_index][1]) + 1,
                                (visible_enemies[room_enemies_index][2]) - 2,
                                '{0}'.format(names, tc.white), (255, 255, 255),
                                (0, 0, 0), 1, tc.CENTER)

                if room_enemies_index == room_enemies_length - 1:
                    room_enemies_index = 0

                else:
                    room_enemies_index += 1

        if cycle_target_left:

            if len(visible_enemies) != 0:
                fov_recompute = True

                con.clear()

                con.default_fg = tc.black
                con.default_fg = tc.white
                con.print(
                    int(constants['screen_width'] / 2), 1,
                    'Press RIGHT arrow or LEFT arrow key to cycle targets or ESCAPE to cancel targeting'
                    .format(), (255, 255, 255), (0, 0, 0), 1, tc.CENTER)

                tc.console_blit(con, 0, 0, constants['screen_width'],
                                constants['screen_height'], 0, 0, 0)
                con.draw_frame((visible_enemies[room_enemies_index][1]) - 1,
                               (visible_enemies[room_enemies_index][2]) - 1,
                               3,
                               3,
                               "",
                               True,
                               fg=tc.white,
                               bg=tc.black)
                con.print((visible_enemies[room_enemies_index][1]) + 1,
                          (visible_enemies[room_enemies_index][2]) - 2,
                          '{0}'.format(visible_enemies[room_enemies_index][3]),
                          (255, 255, 255), (0, 0, 0), 1, tc.CENTER)

                for entity in entities:

                    if tc.map_is_in_fov(fov_map, entity.x, entity.y):

                        if visible_enemies[room_enemies_index][
                                3] == entity.name:
                            names = entity.name
                            names = names + ' ' + Mage.get_stats(
                                entity) + Fighter.get_stats(entity)
                            con.print(
                                (visible_enemies[room_enemies_index][1]) + 1,
                                (visible_enemies[room_enemies_index][2]) - 2,
                                '{0}'.format(names, tc.white), (255, 255, 255),
                                (0, 0, 0), 1, tc.CENTER)

                if room_enemies_index == 0:
                    room_enemies_index = room_enemies_length - 1

                else:
                    room_enemies_index -= 1

        if god_mode:
            player.fighter.hp = 2500

        if poisoned:

            if player.fighter.is_poisoned == False:
                player.fighter.is_poisoned = True
                player.fighter.poison_turns_remaining = 5
                player.color = tc.green

        if burning:

            if player.fighter.is_burning == False:
                player.fighter.is_burning = True
                player.fighter.burning_turns_remaining = 5
                player.color = tc.red

        if reveal_map:

            if constants['fov_radius'] == 8:
                constants['fov_radius'] = 250

                for i in range(len(game_map.tiles)):

                    for j in range(len(game_map.tiles[i])):

                        if not game_map.tiles[i][j].blocked:
                            game_map.tiles[i][j].explored = True
                            game_map.tiles[i][j].block_sight = False

                fov_map = initialize_fov(game_map)
                fov_recompute = True

                con.default_fg = tc.black
                con.default_fg = tc.white

                for entity in entities:
                    #ALL ENTITIES
                    # con.draw_frame(entity.x - 1, entity.y - 1 , 3, 3, "", False, fg=tc.black, bg=tc.black)
                    #ENEMIES ONLY
                    if entity.ai != None:
                        #ENEMY SEEING POWER
                        con.draw_frame(entity.x - 1,
                                       entity.y - 1,
                                       3,
                                       3,
                                       "",
                                       False,
                                       fg=tc.black,
                                       bg=tc.black)

            elif constants['fov_radius'] != 8:
                constants['fov_radius'] = 8

                fov_recompute = True
                con.clear()

        if spawn_enemy_at:
            mouse_x = mouse.cx
            mouse_y = mouse.cy
            spawn_enemy(mouse_x, mouse_y, entities, game_map.dungeon_level)

        if increase_limb_damage:
            player.fighter.take_limb_damge(randint(1, 12))

        if decrease_limb_damage:
            player.fighter.heal(randint(1, 12))

        if teleport:

            for entity in entities:

                if entity.name == "Stairs Down":
                    player.x = entity.x
                    player.y = entity.y + 1

        if mouse_teleport:
            player.x = mouse.cx
            player.y = mouse.cy

        if ranged:
            previous_game_state = game_state
            game_state = GameStates.RANGED

        if level_up:

            if level_up == 'hp':
                player.fighter.base_max_hp += 20
                player.fighter.hp += 20

            elif level_up == 'str':
                player.fighter.base_strength += 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, GameStates.RANGED,
                              GameStates.TARGETING, GameStates.SHOW_TUTORIAL,
                              GameStates.SHOW_HELP_MENU):
                game_state = previous_game_state

            elif game_state == GameStates.CYCLE_TARGET:
                game_state = previous_game_state
                con.clear()
                clear_all(con, entities)
                fov_map = initialize_fov(game_map)
                fov_recompute = True
                con.clear()

            elif game_state == GameStates.TARGETING:
                game_state = previous_game_state
                player_turn_results.append({'targeting_cancelled': True})
                con.clear()
                clear_all(con, entities)
                fov_map = initialize_fov(game_map)
                fov_recompute = True
                con.clear()

            else:
                save_game(player, entities, game_map, message_log, game_state)

                return True

        if fullscreen:
            tc.console_set_fullscreen(not tc.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')
            god_mode = player_turn_result.get('god_mode')

            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)
                    last_index = len(entities)
                    pre_dead_name = dead_entity.name.replace('remains of ', '')

                    if dead_entity.inventory != None:

                        for items in dead_entity.inventory.items:
                            items.x = dead_entity.x
                            items.y = dead_entity.y
                            entities.insert(last_index, items)
                            message_log.add_message(
                                Message('{0}'.format(pre_dead_name) +
                                        ' dropped' +
                                        ' {0}'.format(items.name)))

                message_log.add_message(message)

            if item_added:
                entities.remove(item_added)

            if item_consumed:
                game_state = GameStates.ENEMY_TURN

            if item_dropped:
                entities.append(item_dropped)

            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')
                    failed = equip_result.get('failed')

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

                    if failed:
                        message_log.add_message(
                            Message(
                                'You failed to equip the {0} due to your injuries'
                                .format(failed.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:
                    # #TRACK ENEMY SPECIAL TURNS
                    # if tc.map_is_in_fov(fov_map, entity.x, entity.y):
                    #     print(entity.name + ":" + " " + str(entity.fighter.turns_since_special))
                    enemy_turn_results = entity.ai.take_turn(
                        player, fov_map, game_map, entities)

                    if entity.fighter.is_poisoned == True:
                        message = entity.fighter.take_poison_damage()
                        message_log.add_message(message)

                    elif entity.fighter.is_burning == True:
                        message = entity.fighter.take_burning_damage()
                        message_log.add_message(message)

                    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:

                if player.fighter.is_poisoned == True:
                    message = player.fighter.take_poison_damage()
                    message_log.add_message(message)

                elif player.fighter.is_burning == True:
                    message = player.fighter.take_burning_damage()
                    message_log.add_message(message)

                game_state = GameStates.PLAYERS_TURN

        if game_state == GameStates.SHOW_TUTORIAL:
            action = handle_tutorial_menu(key)
            close_tutorial = action.get('close_tutorial')

            if close_tutorial:
                con.clear()
                clear_all(con, entities)
                fov_map = initialize_fov(game_map)
                fov_recompute = True
                con.clear()
                game_state = GameStates.PLAYERS_TURN

        if game_state == GameStates.SHOW_HELP_MENU:
            action = handle_help_menu(key)
            close_help_menu = action.get('close_help_menu')

            if close_help_menu:
                con.clear()
                clear_all(con, entities)
                fov_map = initialize_fov(game_map)
                fov_recompute = True
                con.clear()
                game_state = GameStates.PLAYERS_TURN
Пример #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
Пример #29
0
def main():

    """
    객체 생성
    """
    # 플레이어 객체 생성. 위치는 맵 중앙.

    fighter_component = Fighter(hp=30, defense=2, power=5)
    luminary_component = Luminary(luminosity=10)
    inventory_component = Inventory(26)
    player = Entity(int(map_width/2),int(map_height/2),'@',tcod.white, 'You', blocks=True, render_order=RenderOrder.ACTOR, _Luminary=luminary_component, _Fighter=fighter_component, _Inventory=inventory_component)
    entities = [player]

    i_comp = Item(use_function=read,about='about activities of you and your best friend, Mary')
    Journal = Entity(player.x,player.y, ':', tcod.darkest_red,
                     'Swallowstone Journal', render_order=RenderOrder.ITEM, _Item = i_comp)

    i_comp = Item(use_function=talisman)
    Talisman = Entity(player.x,player.y, '*', tcod.lighter_purple,
                      'Passionflower Talisman', render_order=RenderOrder.ITEM, _Item = i_comp)

    player._Inventory.items.append(Journal)
    player._Inventory.items.append(Talisman)

    # 지도 객체 생성: y,x 순서는 game_map 객체에서 알아서 처리
    game_map = GameMap(map_width,map_height)
    game_map.create_map_cave(entities, 3, 10, 10)

    # FOV
    fov_radius = max_fov_radius
    fov_algorithm = fov_algorithm_lit
    fov_recompute = True
    fov_map = initialize_fov(game_map)

    # 광원, light_map은 numpy 리스트

    light_recompute = True

    light_map = initialize_light(game_map, fov_map, entities)

    # 카메라 객체 생성
    camera = Camera(0,0, map_width, map_height, True)

    camera.update(player)

    """
    디버그 명령 목록
    passwall: 벽 통과 가능
    showpos: 플레이어 x,y좌표 표시. 다른 엔티티 좌표도 표시할 수 있게 고칠 것
    """
    # 디버그용 객체 생성. 디버그 기능들은 기본적으로 꺼져 있고, 인자를 넣으면 활성화
    debug = Debug()

    # 메세지 출력용 객체 생성.
    message_log = MessageLog(message_x, message_width, message_height)

    # 키보드, 마우스 입력 처리용 객체 생성
    key = tcod.Key()
    mouse = tcod.Mouse()

    # 순서 결정용 객체 생성
    game_state = GameStates.PLAYERS_TURN
    previous_game_state = game_state
    targeting_item = None

    # 콘솔, 패널 생성
    con = tcod.console.Console(screen_width, screen_height)
    panel = tcod.console_new(screen_width, panel_height)

    # 폰트 설정: 10x10파일, 이미지 파일은 그레이스케일, 배열 방식은 TCOD
    # tcod.console_set_custom_font('arial10x10.png', tcod.FONT_TYPE_GREYSCALE | tcod.FONT_LAYOUT_TCOD)

    # 폰트 설정: 32x32파일, 이미지 파일은 그레이스케일, 배열 방식은 CP437
    tcod.console_set_custom_font('terminal16x16.png', tcod.FONT_TYPE_GREYSCALE | tcod.FONT_LAYOUT_CP437)

    # 스크린 생성: 스크린 가로/세로, 이름, 전체화면 여부
    tcod.console_init_root(screen_width, screen_height, 'Mary', False, vsync=True)


    # TCOD 루프
    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)


        if light_recompute:
            light_map = initialize_light(game_map, fov_map, entities)

        """
        화면 표시
        """
        # 화면 초기화
        clear_all_entities(con, entities, camera)

        # 표시할 모든 객체를 화면에 배치함
        render_all(game_state, con, panel, mouse, entities, player,
                   game_map, fov_map, light_map, camera, message_log, fov_recompute,
                   screen_width, screen_height,
                   bar_width, panel_height, panel_y, colors)

        fov_recompute = False
        light_recompute = False

        # 화면 출력
        tcod.console_flush(keep_aspect=True)

        # 화면 초기화
        clear_all_entities(con, entities, camera)

        """
        입력에 대한 상호작용
        """
        # action 변수에 키보드 입력값을 사전 형태로 받아옴
        action = handle_keys(key, game_state)
        mouse_action = handle_mouse(mouse)

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

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

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

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

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

        """
        플레이어 차례에 플레이어가 할 수 있는 행동들
        """
        player_turn_results = []

        # 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:
                        attack_results = player._Fighter.attack(target)
                        player_turn_results.extend(attack_results)

                    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('There is nothing here to pick up.', 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, fov_map=fov_map,
                                                                 screen_width = screen_width,
                                                                 screen_height = screen_height))
            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,
                                                        camera=camera, screen_width = screen_width, screen_height = screen_height,
                                                        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 rest:
            game_state = GameStates.ENEMY_TURN

        for r in player_turn_results:
            message = r.get('message')
            dead_entity = r.get('dead')
            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)

                message_log.log(message)

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

                        if message:
                            message_log.log(message)

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

                            message_log.log(message)

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

            else:
                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
Пример #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
Пример #31
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)