def sacrifice_menu(player, powers, post_power_gain_function):
    game_state = player.game_state.value
    state_stack = game_state.menu_prompt_stack
    context_options = []
    stack_pop_function = menu.BackToGameFunction(state_stack)
    width = 24

    for power in powers:
        power_caption = power.description.name + str(power.buy_cost).rjust(width - len(power.description.name))
        power_option = menu.MenuOption(power_caption, [lambda p=power: player.set_child(p),
                                                       lambda p=power: p.on_power_gained(),
                                                       lambda p=power: sacrifice.sacrifice_health(player, p.buy_cost),
                                                       lambda: player.actor.add_energy_spent(gametime.single_turn),
                                                       post_power_gain_function,
                                                       stack_pop_function],
                                       (lambda: player.health.hp.value > power.buy_cost), payload=power)
        context_options.append(power_option)

    cancel_option = menu.MenuOption("Cancel", [stack_pop_function], (lambda: True))
    context_options.append(cancel_option)

    tmp = (0, 0)
    menu_stack_panel = gui.StackPanelVertical(tmp, style.menu_theme.margin, vertical_space=0,
                                              alignment=gui.StackPanelVertical.ALIGN_CENTER)

    heading_stack_panel = gui.StackPanelHorizontal((0, 0), (0, 0), horizontal_space=2)
    menu_stack_panel.append(heading_stack_panel)
    if any(powers):
        power_caption = "Power" + str("Cost").rjust(width - len("Cost   "))
        heading_stack_panel.append(gui.TextBox(power_caption, (1, 0), colors.GRAY))
        heading_stack_panel.append(gui.SymbolUIElement((0, 0), graphic.GraphicChar(colors.DARK_BLUE, colors.HP_BAR_FULL, icon.HEALTH_STAT)))
        menu_stack_panel.append(gui.VerticalSpace(2))
    else:
        power_caption = "There are no more powers."
        menu_stack_panel.append(gui.VerticalSpace(4))
        heading_stack_panel.append(gui.TextBox(power_caption, (1, 0), colors.GRAY))

    item_description_card = gui.new_item_description_card()
    resulting_menu = menu.StaticMenu((0, 0), context_options, state_stack, selected_payload_callback=(lambda item: item_description_card.set_item(item)))
    menu_stack_panel.append(resulting_menu)

    context_menu_rect = rectfactory.center_of_screen_rect(max(menu_stack_panel.total_width, 24),
                                                          max(menu_stack_panel.total_height, 6))
    menu_stack_panel.offset = context_menu_rect.top_left
    background_rect = get_menu_background(context_menu_rect, style.sacrifice_menu_theme.rect_style)

    dock = gui.UIDock(rectfactory.full_screen_rect())
    dock.bottom = item_description_card

    ui_elements = [background_rect, menu_stack_panel, dock]
    ui_state = state.UIState(gui.UIElementList(ui_elements))
    return ui_state
def inventory_menu(player, state_stack):
    menu_stack_panel = get_item_menu_stack_panel_template("Inventory",
                                                          graphic.GraphicChar(None, colors.INVENTORY_HEADING,
                                                                              icon.INVENTORY_ICON))
    item_description_card = gui.new_item_description_card()
    menu_items = []
    for item in player.inventory.get_items_sorted():
        menu_option = _get_item_action_menu_option(item, player, state_stack)
        menu_items.append(menu_option)

    inventory_menu = menu.StaticMenu((0, 1), menu_items, state_stack, (0, 0), vertical_space=0,
                                     selected_payload_callback=(lambda item: item_description_card.set_item(item)))
    menu_stack_panel.append(inventory_menu)

    return _get_item_menu_composition(item_description_card, menu_stack_panel)
def filtered_by_action_item_menu(player, state_stack, item_action_tag, heading_text):
    menu_stack_panel = get_item_menu_stack_panel_template(heading_text,
                                                          graphic.GraphicChar(None,
                                                                              colors.INVENTORY_HEADING,
                                                                              icon.INVENTORY_ICON))
    item_description_card = gui.new_item_description_card()
    stack_pop_function = menu.BackToGameFunction(state_stack)
    menu_items = []
    for item in player.inventory.get_items_sorted():
        if len(item.get_children_with_tag(item_action_tag)) > 0:
            item_action = item.get_children_with_tag(item_action_tag)[0]
            item_action_option = _get_item_action_option(item, item_action, player, stack_pop_function)
            menu_items.append(item_action_option)

    action_menu = menu.StaticMenu((0, 1), menu_items, state_stack,
                                  (0, 0), vertical_space=0, selected_payload_callback=(lambda item: item_description_card.set_item(item)))
    menu_stack_panel.append(action_menu)
    return _get_item_menu_composition(item_description_card, menu_stack_panel)
def item_type_menu_callback_menu(player, state_stack, item_type, heading_text, item_callback,
                                 can_callback_activate=(lambda: True)):
    menu_stack_panel = get_item_menu_stack_panel_template(heading_text,
                                                          graphic.GraphicChar(None,
                                                                              colors.INVENTORY_HEADING,
                                                                              icon.INVENTORY_ICON))
    item_description_card = gui.new_item_description_card()
    stack_pop_function = menu.BackToGameFunction(state_stack)
    menu_items = []
    for item in player.inventory.get_items_sorted():
        if item.item_type.value == item_type:
            item_action_option = _get_item_callback_option(item, item_callback, can_callback_activate,
                                                           player, stack_pop_function)
            menu_items.append(item_action_option)

    _equip_menu = menu.StaticMenu((0, 1), menu_items, state_stack, (0, 0), vertical_space=0,
                                  selected_payload_callback=(lambda item: item_description_card.set_item(item)))
    menu_stack_panel.append(_equip_menu)
    return _get_item_menu_composition(item_description_card, menu_stack_panel)
def player_status_menu(player):
    split_width = 27
    content_padding = (2, 2)
    player_status_stack_panel = gui.StackPanelVertical(geo.add_2d((0, 0), content_padding),
                                                       alignment=gui.StackPanelVertical.ALIGN_LEFT,
                                                       vertical_space=1)
    player_status_stack_panel_row_1 = gui.StackPanelHorizontal((0, 0), alignment=gui.StackPanelHorizontal.ALIGN_TOP,
                                                               horizontal_space=1)
    player_status_stack_panel.append(player_status_stack_panel_row_1)
    player_status_stack_panel_row_1.append(gui.BigSymbolUIElement((0, 0), player.graphic_char))
    player_description_stack = gui.StackPanelVertical((0, 0), alignment=gui.StackPanelVertical.ALIGN_LEFT,
                                                      vertical_space=1)
    player_status_stack_panel_row_1.append(player_description_stack)
    player_description_stack.append(gui.TextBox(player.description.name, (2, 0), colors.WHITE))
    player_description_stack.append(gui.TextBox(player.race.value + "\n" + player.job.value, (2, 0), colors.WHITE))

    player_description_stack.append(gui.new_player_hp_bar(12, player.health.hp))
    player_description_stack.append(gui.new_player_sanity_bar(12, Counter(10, 10)))

    player_status_stack_panel_row_2 = gui.StackPanelHorizontal((0, 0), alignment=gui.StackPanelHorizontal.ALIGN_TOP,
                                                               horizontal_space=3)
    player_status_stack_panel.append(player_status_stack_panel_row_2)
    player_status_stack_panel_row_2.append(new_player_status_stack(player, 8))
    player_status_stack_panel_row_2.append(new_player_weapon_table(player, 8))

    description_card = gui.new_item_description_card()
    power_list = get_power_list(player, description_card)
    if len(power_list.menu_items) > 0:
        player_status_stack_panel.append(gui.VerticalSpace(1))
    player_status_stack_panel.append(power_list)

    bg_rect_height = (player_status_stack_panel.total_height + 4)
    bg_rect = rectfactory.center_of_screen_rect(split_width, bg_rect_height)

    player_status_stack_panel.offset = geo.add_2d(bg_rect.top_left, (2, 2))

    styled_bg_rect = get_menu_background(bg_rect, style.rogue_classic_theme.rect_style)

    dock = gui.UIDock(rectfactory.full_screen_rect())
    dock.bottom = description_card
    return state.UIState(gui.UIElementList([styled_bg_rect, player_status_stack_panel, dock]))
def equipment_menu(player, state_stack):
    menu_stack_panel = gui.StackPanelVertical((0, 0), margin=(0, 0))
    heading = gui.TextBox("Equipment", (2, 1), colors.INVENTORY_HEADING, (2, 2))
    menu_stack_panel.append(heading)

    equipment_menu_bg = gui.StyledRectangle(rectfactory.right_side_menu_rect(),
                                            style.rogue_classic_theme.rect_style)

    item_description_card = gui.new_item_description_card()
    resulting_menu = menu.EquipmentMenu((0, 0), player, state_stack, selected_payload_callback=(lambda item: item_description_card.set_item(item)), margin=(2, 1))
    menu_stack_panel.append(resulting_menu)

    equipment_gui = gui.UIElementList([equipment_menu_bg, menu_stack_panel])

    equipment_stack_panel = gui.StackPanelHorizontal((0, 0), alignment=gui.StackPanelHorizontal.ALIGN_BOTTOM)
    equipment_stack_panel.append(item_description_card)
    equipment_stack_panel.append(equipment_gui)

    dock = gui.UIDock(rectfactory.full_screen_rect())
    dock.bottom_right = equipment_stack_panel
    return state.UIState(dock)
def equipment_slot_menu(player, equipment_slot, state_stack):
    """
    Creates a menu which shows the possible actions
    that can be taken on a given equipment_slot.
    """
    menu_stack_panel = gui.StackPanelVertical((0, 0), margin=(0, 0))
    heading = gui.TextBox("Change " + equipment_slot.name, (2, 1), colors.INVENTORY_HEADING, (2, 2))
    menu_stack_panel.append(heading)

    item_description_card = gui.new_item_description_card()
    resulting_menu = menu.EquipSlotMenu((0, 0), player, equipment_slot, state_stack, (lambda item: item_description_card.set_item(item)), (2, 1))
    menu_stack_panel.append(resulting_menu)

    equipment_menu_bg = gui.StyledRectangle(rectfactory.right_side_menu_rect(),
                                            style.rogue_classic_theme.rect_style)
    equipment_slot_gui = gui.UIElementList([equipment_menu_bg, menu_stack_panel])

    equipment_slot_stack_panel = gui.StackPanelHorizontal((0, 0), alignment=gui.StackPanelHorizontal.ALIGN_BOTTOM)
    equipment_slot_stack_panel.append(item_description_card)
    equipment_slot_stack_panel.append(equipment_slot_gui)

    dock = gui.UIDock(rectfactory.full_screen_rect())
    dock.bottom_right = equipment_slot_stack_panel
    return state.UIState(dock)