Esempio n. 1
0
/**
 * Handle input and update display
 *
 */
void uilist::query( bool loop, int timeout )
{
    keypress = 0;
    if( entries.empty() ) {
        ret = UILIST_ERROR;
        return;
    }
    ret = UILIST_WAIT_INPUT;

    input_context ctxt( input_category );
    ctxt.register_updown();
    ctxt.register_action( "PAGE_UP" );
    ctxt.register_action( "PAGE_DOWN" );
    ctxt.register_action( "SCROLL_UP" );
    ctxt.register_action( "SCROLL_DOWN" );
    if( allow_cancel ) {
        ctxt.register_action( "QUIT" );
    }
    ctxt.register_action( "CONFIRM" );
    ctxt.register_action( "FILTER" );
    ctxt.register_action( "ANY_INPUT" );
    ctxt.register_action( "HELP_KEYBINDINGS" );
    for( const auto &additional_action : additional_actions ) {
        ctxt.register_action( additional_action.first, additional_action.second );
    }
    hotkeys = ctxt.get_available_single_char_hotkeys( hotkeys );

    show();

#if defined(__ANDROID__)
    for( const auto &entry : entries ) {
        if( entry.hotkey > 0 && entry.enabled ) {
            ctxt.register_manual_key( entry.hotkey, entry.txt );
        }
    }
#endif

    do {
        const auto action = ctxt.handle_input( timeout );
        const auto event = ctxt.get_raw_input();
        keypress = event.get_first_input();
        const auto iter = keymap.find( keypress );

        if( scrollby( scroll_amount_from_action( action ) ) ) {
            /* nothing */
        } else if( action == "HELP_KEYBINDINGS" ) {
            /* nothing, handled by input_context */
        } else if( filtering && action == "FILTER" ) {
            inputfilter();
        } else if( iter != keymap.end() ) {
            selected = iter->second;
            if( entries[ selected ].enabled ) {
                ret = entries[ selected ].retval; // valid
            } else if( allow_disabled ) {
                ret = entries[selected].retval; // disabled
            }
        } else if( !fentries.empty() && action == "CONFIRM" ) {
            if( entries[ selected ].enabled ) {
                ret = entries[ selected ].retval; // valid
            } else if( allow_disabled ) {
                ret = entries[selected].retval; // disabled
            }
        } else if( allow_cancel && action == "QUIT" ) {
            ret = UILIST_CANCEL;
        } else if( action == "TIMEOUT" ) {
            ret = UILIST_TIMEOUT;
        } else {
            bool unhandled = callback == nullptr || !callback->key( ctxt, event, selected, this );
            if( unhandled && allow_anykey ) {
                ret = UILIST_UNBOUND;
            }
        }

        show();
    } while( loop && ret == UILIST_WAIT_INPUT );
}
Esempio n. 2
0
void player::power_bionics()
{
    std::vector <bionic *> passive = filtered_bionics( my_bionics, TAB_PASSIVE );
    std::vector <bionic *> active = filtered_bionics( my_bionics, TAB_ACTIVE );
    bionic *bio_last = NULL;
    bionic_tab_mode tab_mode = TAB_ACTIVE;

    //added title_tab_height for the tabbed bionic display
    int TITLE_HEIGHT = 2;
    int TITLE_TAB_HEIGHT = 3;

    // Main window
    /** Total required height is:
     * top frame line:                                         + 1
     * height of title window:                                 + TITLE_HEIGHT
     * height of tabs:                                         + TITLE_TAB_HEIGHT
     * height of the biggest list of active/passive bionics:   + bionic_count
     * bottom frame line:                                      + 1
     * TOTAL: TITLE_HEIGHT + TITLE_TAB_HEIGHT + bionic_count + 2
     */
    const int HEIGHT = std::min( TERMY,
                                 std::max( FULL_SCREEN_HEIGHT,
                                           TITLE_HEIGHT + TITLE_TAB_HEIGHT +
                                           ( int )my_bionics.size() + 2 ) );
    const int WIDTH = FULL_SCREEN_WIDTH + ( TERMX - FULL_SCREEN_WIDTH ) / 2;
    const int START_X = ( TERMX - WIDTH ) / 2;
    const int START_Y = ( TERMY - HEIGHT ) / 2;
    //wBio is the entire bionic window
    WINDOW *wBio = newwin( HEIGHT, WIDTH, START_Y, START_X );
    WINDOW_PTR wBioptr( wBio );

    const int LIST_HEIGHT = HEIGHT - TITLE_HEIGHT - TITLE_TAB_HEIGHT - 2;

    const int DESCRIPTION_WIDTH = WIDTH - 2 - 40;
    const int DESCRIPTION_START_Y = START_Y + TITLE_HEIGHT + TITLE_TAB_HEIGHT + 1;
    const int DESCRIPTION_START_X = START_X + 1 + 40;
    //w_description is the description panel that is controlled with ! key
    WINDOW *w_description = newwin( LIST_HEIGHT, DESCRIPTION_WIDTH,
                                    DESCRIPTION_START_Y, DESCRIPTION_START_X );
    WINDOW_PTR w_descriptionptr( w_description );

    // Title window
    const int TITLE_START_Y = START_Y + 1;
    const int HEADER_LINE_Y = TITLE_HEIGHT + TITLE_TAB_HEIGHT + 1;
    WINDOW *w_title = newwin( TITLE_HEIGHT, WIDTH - 2, TITLE_START_Y, START_X + 1 );
    WINDOW_PTR w_titleptr( w_title );

    const int TAB_START_Y = TITLE_START_Y + 2;
    //w_tabs is the tab bar for passive and active bionic groups
    WINDOW *w_tabs = newwin( TITLE_TAB_HEIGHT, WIDTH - 2, TAB_START_Y, START_X + 1 );
    WINDOW_PTR w_tabsptr( w_tabs );

    int scroll_position = 0;
    int cursor = 0;

    //generate the tab title string and a count of the bionics owned
    bionic_menu_mode menu_mode = ACTIVATING;
    // offset for display: bionic with index i is drawn at y=list_start_y+i
    // drawing the bionics starts with bionic[scroll_position]
    const int list_start_y = HEADER_LINE_Y;// - scroll_position;
    int half_list_view_location = LIST_HEIGHT / 2;
    int max_scroll_position = std::max( 0, ( tab_mode == TAB_ACTIVE ?
                                        ( int )active.size() :
                                        ( int )passive.size() ) - LIST_HEIGHT );

    input_context ctxt( "BIONICS" );
    ctxt.register_updown();
    ctxt.register_action( "ANY_INPUT" );
    ctxt.register_action( "TOGGLE_EXAMINE" );
    ctxt.register_action( "REASSIGN" );
    ctxt.register_action( "REMOVE" );
    ctxt.register_action( "NEXT_TAB" );
    ctxt.register_action( "PREV_TAB" );
    ctxt.register_action( "CONFIRM" );
    ctxt.register_action( "HELP_KEYBINDINGS" );

    bool recalc = false;
    bool redraw = true;

    for( ;; ) {
        if( recalc ) {
            passive = filtered_bionics( my_bionics, TAB_PASSIVE );
            active = filtered_bionics( my_bionics, TAB_ACTIVE );

            if( active.empty() && !passive.empty() ) {
                tab_mode = TAB_PASSIVE;
            }

            if( --cursor < 0 ) {
                cursor = 0;
            }
            if( scroll_position > max_scroll_position &&
                cursor - scroll_position < LIST_HEIGHT - half_list_view_location ) {
                scroll_position--;
            }

            recalc = false;
            // bionics were modified, so it's necessary to redraw the screen
            redraw = true;
        }

        //track which list we are looking at
        std::vector<bionic *> *current_bionic_list = ( tab_mode == TAB_ACTIVE ? &active : &passive );
        max_scroll_position = std::max( 0, ( int )current_bionic_list->size() - LIST_HEIGHT );

        if( redraw ) {
            redraw = false;

            werase( wBio );
            draw_border( wBio, BORDER_COLOR, _( " BIONICS " ) );
            // Draw symbols to connect additional lines to border
            mvwputch( wBio, HEADER_LINE_Y - 1, 0, BORDER_COLOR, LINE_XXXO ); // |-
            mvwputch( wBio, HEADER_LINE_Y - 1, WIDTH - 1, BORDER_COLOR, LINE_XOXX ); // -|

            if( current_bionic_list->empty() ) {
                std::string msg;
                switch( tab_mode ) {
                    case TAB_ACTIVE:
                        msg = _( "No activatable bionics installed." );
                        break;
                    case TAB_PASSIVE:
                        msg = _( "No passive bionics installed." );
                        break;
                }
                fold_and_print( wBio, list_start_y, 2, WIDTH - 3, c_ltgray, msg );
            } else {
                for( size_t i = scroll_position; i < current_bionic_list->size(); i++ ) {
                    if( list_start_y + static_cast<int>( i ) - scroll_position == HEIGHT - 1 ) {
                        break;
                    }
                    const bool is_highlighted = cursor == static_cast<int>( i );
                    const nc_color col = get_bionic_text_color( *( *current_bionic_list )[i],
                                         is_highlighted );
                    const std::string desc = string_format( "%c %s", ( *current_bionic_list )[i]->invlet,
                                                            build_bionic_powerdesc_string(
                                                                    *( *current_bionic_list )[i] ).c_str() );
                    trim_and_print( wBio, list_start_y + i - scroll_position, 2, WIDTH - 3, col,
                                    "%s", desc.c_str() );
                    // draw bodyparts
                    if( is_highlighted && menu_mode != EXAMINING ) {
                        int max_width = 0;
                        std::vector<std::string>bps;
                        for( int i = 0; i < num_bp; ++i ) {
                            const body_part bp = bp_aBodyPart[i];
                            const int total = get_total_bionics_slots( bp );
                            const std::string s = string_format( "%s: %d/%d",
                                                                 body_part_name_as_heading( bp, 1 ).c_str(),
                                                                 total - get_free_bionics_slots( bp ),
                                                                 total );
                            bps.push_back( s );
                            max_width = std::max( max_width, utf8_width( s ) );
                        }
                        const int pos_x = WIDTH - 2 - max_width;
                        const std::string bio_id = ( *current_bionic_list )[i]->id;
                        draw_connectors( wBio, list_start_y + i - scroll_position, utf8_width( desc ) + 3,
                                         pos_x - 2, bio_id );

                        for( int i = 0; i < num_bp; ++i ) {
                            mvwprintz( wBio, i + list_start_y, pos_x,
                                       bionic_info( bio_id ).occupied_bodyparts.count( bp_aBodyPart[i] ) > 0 ?
                                       c_yellow : c_ltgray, "%s", bps[i].c_str() );
                        }
                    }

                }
            }

            draw_scrollbar( wBio, cursor, LIST_HEIGHT, current_bionic_list->size(), list_start_y );
        }
        wrefresh( wBio );
        draw_bionics_tabs( w_tabs, active.size(), passive.size(), tab_mode );
        draw_bionics_titlebar( w_title, this, menu_mode );
        if( menu_mode == EXAMINING && !current_bionic_list->empty() ) {
            draw_description( w_description, *( *current_bionic_list )[cursor] );
        }

        const std::string action = ctxt.handle_input();
        const long ch = ctxt.get_raw_input().get_first_input();
        bionic *tmp = NULL;
        bool confirmCheck = false;
        if( menu_mode == REASSIGNING ) {
            menu_mode = ACTIVATING;
            tmp = bionic_by_invlet( ch );
            if( tmp == nullptr ) {
                // Selected an non-existing bionic (or escape, or ...)
                continue;
            }
            redraw = true;
            const long newch = popup_getkey( _( "%s; enter new letter." ),
                                             bionic_info( tmp->id ).name.c_str() );
            wrefresh( wBio );
            if( newch == ch || newch == ' ' || newch == KEY_ESCAPE ) {
                continue;
            }
            if( !bionic_chars.valid( newch ) ) {
                popup( _( "Invalid bionic letter. Only those characters are valid:\n\n%s" ),
                       bionic_chars.get_allowed_chars().c_str() );
                continue;
            }
            bionic *otmp = bionic_by_invlet( newch );
            if( otmp != nullptr ) {
                std::swap( tmp->invlet, otmp->invlet );
            } else {
                tmp->invlet = newch;
            }
            // TODO: show a message like when reassigning a key to an item?
        } else if( action == "NEXT_TAB" ) {
            redraw = true;
            scroll_position = 0;
            cursor = 0;
            if( tab_mode == TAB_ACTIVE ) {
                tab_mode = TAB_PASSIVE;
            } else {
                tab_mode = TAB_ACTIVE;
            }
        } else if( action == "PREV_TAB" ) {
            redraw = true;
            scroll_position = 0;
            cursor = 0;
            if( tab_mode == TAB_PASSIVE ) {
                tab_mode = TAB_ACTIVE;
            } else {
                tab_mode = TAB_PASSIVE;
            }
        } else if( action == "DOWN" ) {
            redraw = true;
            if( static_cast<size_t>( cursor ) < current_bionic_list->size() - 1 ) {
                cursor++;
            }
            if( scroll_position < max_scroll_position &&
                cursor - scroll_position > LIST_HEIGHT - half_list_view_location ) {
                scroll_position++;
            }
        } else if( action == "UP" ) {
            redraw = true;
            if( cursor > 0 ) {
                cursor--;
            }
            if( scroll_position > 0 && cursor - scroll_position < half_list_view_location ) {
                scroll_position--;
            }
        } else if( action == "REASSIGN" ) {
            menu_mode = REASSIGNING;
        } else if( action == "TOGGLE_EXAMINE" ) { // switches between activation and examination
            menu_mode = menu_mode == ACTIVATING ? EXAMINING : ACTIVATING;
            redraw = true;
        } else if( action == "REMOVE" ) {
            menu_mode = REMOVING;
            redraw = true;
        } else if( action == "HELP_KEYBINDINGS" ) {
            redraw = true;
        } else if( action == "CONFIRM" ) {
            confirmCheck = true;
        } else {
            confirmCheck = true;
        }
        //confirmation either occurred by pressing enter where the bionic cursor is, or the hotkey was selected
        if( confirmCheck ) {
            auto &bio_list = tab_mode == TAB_ACTIVE ? active : passive;
            if( action == "CONFIRM" && !current_bionic_list->empty() ) {
                tmp = bio_list[cursor];
            } else {
                tmp = bionic_by_invlet( ch );
                if( tmp && tmp != bio_last ) {
                    // new bionic selected, update cursor and scroll position
                    int temp_cursor = 0;
                    for( temp_cursor = 0; temp_cursor < ( int )bio_list.size(); temp_cursor++ ) {
                        if( bio_list[temp_cursor] == tmp ) {
                            break;
                        }
                    }
                    // if bionic is not found in current list, ignore the attempt to view/activate
                    if( temp_cursor >= ( int )bio_list.size() ) {
                        continue;
                    }
                    //relocate cursor to the bionic that was found
                    cursor = temp_cursor;
                    scroll_position = 0;
                    while( scroll_position < max_scroll_position &&
                           cursor - scroll_position > LIST_HEIGHT - half_list_view_location ) {
                        scroll_position++;
                    }
                }
            }
            if( !tmp ) {
                // entered a key that is not mapped to any bionic,
                // -> leave screen
                break;
            }
            bio_last = tmp;
            const std::string &bio_id = tmp->id;
            const bionic_data &bio_data = bionic_info( bio_id );
            if( menu_mode == REMOVING ) {
                recalc = uninstall_bionic( bio_id );
                redraw = true;
                continue;
            }
            if( menu_mode == ACTIVATING ) {
                if( bio_data.activated ) {
                    int b = tmp - &my_bionics[0];
                    if( tmp->powered ) {
                        deactivate_bionic( b );
                    } else {
                        activate_bionic( b );
                    }
                    // update message log and the menu
                    g->refresh_all();
                    redraw = true;
                    continue;
                } else {
                    popup( _( "You can not activate %s!\n"
                              "To read a description of %s, press '!', then '%c'." ), bio_data.name.c_str(),
                           bio_data.name.c_str(), tmp->invlet );
                    redraw = true;
                }
            } else if( menu_mode == EXAMINING ) { // Describing bionics, allow user to jump to description key
                redraw = true;
                if( action != "CONFIRM" ) {
                    for( size_t i = 0; i < active.size(); i++ ) {
                        if( active[i] == tmp ) {
                            tab_mode = TAB_ACTIVE;
                            cursor = static_cast<int>( i );
                            int max_scroll_check = std::max( 0, ( int )active.size() - LIST_HEIGHT );
                            if( static_cast<int>( i ) > max_scroll_check ) {
                                scroll_position = max_scroll_check;
                            } else {
                                scroll_position = i;
                            }
                            break;
                        }
                    }
                    for( size_t i = 0; i < passive.size(); i++ ) {
                        if( passive[i] == tmp ) {
                            tab_mode = TAB_PASSIVE;
                            cursor = static_cast<int>( i );
                            int max_scroll_check = std::max( 0, ( int )passive.size() - LIST_HEIGHT );
                            if( static_cast<int>( i ) > max_scroll_check ) {
                                scroll_position = max_scroll_check;
                            } else {
                                scroll_position = i;
                            }
                            break;
                        }
                    }
                }
            }
        }
    }
}
Esempio n. 3
0
void construction_menu()
{
    static bool hide_unconstructable = false;
    // only display constructions the player can theoretically perform
    std::vector<std::string> available;
    std::map<std::string, std::vector<std::string>> cat_available;
    load_available_constructions( available, cat_available, hide_unconstructable );

    if( available.empty() ) {
        popup( _( "You can not construct anything here." ) );
        return;
    }

    int w_height = TERMY;
    if( ( int )available.size() + 2 < w_height ) {
        w_height = available.size() + 2;
    }
    if( w_height < FULL_SCREEN_HEIGHT ) {
        w_height = FULL_SCREEN_HEIGHT;
    }

    const int w_width = std::max( FULL_SCREEN_WIDTH, TERMX * 2 / 3);
    const int w_y0 = ( TERMY > w_height ) ? ( TERMY - w_height ) / 2 : 0;
    const int w_x0 = ( TERMX > w_width ) ? ( TERMX - w_width ) / 2 : 0;
    WINDOW_PTR w_con_ptr {newwin( w_height, w_width, w_y0, w_x0 )};
    WINDOW *const w_con = w_con_ptr.get();

    const int w_list_width = int( .375 * w_width );
    const int w_list_height = w_height - 4;
    const int w_list_x0 = 1;
    WINDOW_PTR w_list_ptr {newwin( w_list_height, w_list_width, w_y0 + 3, w_x0 + w_list_x0 )};
    WINDOW *const w_list = w_list_ptr.get();

    draw_grid( w_con, w_list_width + w_list_x0 );

    //tabcount needs to be increased to add more categories
    int tabcount = 10;
    std::string construct_cat[] = {_( "All" ), _( "Constructions" ), _( "Furniture" ),
                                   _( "Digging and Mining" ), _( "Repairing" ),
                                   _( "Reinforcing" ), _( "Decorative" ),
                                   _( "Farming and Woodcutting" ), _( "Others" ),
                                   _( "Filter" )
                                  };

    bool update_info = true;
    bool update_cat = true;
    bool isnew = true;
    int tabindex = 0;
    int select = 0;
    int offset = 0;
    bool exit = false;
    std::string category_name = "";
    std::vector<std::string> constructs;
    //storage for the color text so it can be scrolled
    std::vector< std::vector < std::string > > construct_buffers;
    std::vector<std::string> full_construct_buffer;
    std::vector<int> construct_buffer_breakpoints;
    int total_project_breakpoints = 0;
    int current_construct_breakpoint = 0;
    bool previous_hide_unconstructable = false;
    //track the cursor to determine when to refresh the list of construction recipes
    int previous_tabindex = -1;
    int previous_select = -1;

    const inventory &total_inv = g->u.crafting_inventory();

    input_context ctxt( "CONSTRUCTION" );
    ctxt.register_action( "UP", _( "Move cursor up" ) );
    ctxt.register_action( "DOWN", _( "Move cursor down" ) );
    ctxt.register_action( "RIGHT", _( "Move tab right" ) );
    ctxt.register_action( "LEFT", _( "Move tab left" ) );
    ctxt.register_action( "PAGE_UP" );
    ctxt.register_action( "PAGE_DOWN" );
    ctxt.register_action( "CONFIRM" );
    ctxt.register_action( "TOGGLE_UNAVAILABLE_CONSTRUCTIONS" );
    ctxt.register_action( "QUIT" );
    ctxt.register_action( "HELP_KEYBINDINGS" );
    ctxt.register_action( "FILTER" );

    std::string filter;
    int previous_index = 0;
    do {
        if( update_cat ) {
            update_cat = false;
            switch( tabindex ) {
                case 0:
                    category_name = "ALL";
                    break;
                case 1:
                    category_name = "CONSTRUCT";
                    break;
                case 2:
                    category_name = "FURN";
                    break;
                case 3:
                    category_name = "DIG";
                    break;
                case 4:
                    category_name = "REPAIR";
                    break;
                case 5:
                    category_name = "REINFORCE";
                    break;
                case 6:
                    category_name = "DECORATE";
                    break;
                case 7:
                    category_name = "FARM_WOOD";
                    break;
                case 8:
                    category_name = "OTHER";
                    break;
                case 9:
                    category_name = "FILTER";
                    break;
            }

            if( category_name == "ALL" ) {
                constructs = available;
                previous_index = tabindex;
            } else if( category_name == "FILTER" ) {
                constructs.clear();
                std::copy_if( available.begin(), available.end(),
                    std::back_inserter( constructs ),
                    [&](const std::string &a){
                        return lcmatch(a, filter);
                    } );
            } else {
                constructs = cat_available[category_name];
                previous_index = tabindex;
            }
            if( isnew ){
                if( !uistate.last_construction.empty() ){
                    select = std::distance(constructs.begin(),
                                            std::find( constructs.begin(),
                                                        constructs.end(),
                                                        uistate.last_construction ));
                }
                filter = uistate.construction_filter;
            }
        }
        // Erase existing tab selection & list of constructions
        mvwhline( w_con, 1, 1, ' ', w_list_width );
        werase( w_list );
        // Print new tab listing
        mvwprintz( w_con, 1, 1, c_yellow, "<< %s >>", construct_cat[tabindex].c_str() );
        // Determine where in the master list to start printing
        calcStartPos( offset, select, w_list_height, constructs.size() );
        // Print the constructions between offset and max (or how many will fit)
        for( size_t i = 0; ( int )i < w_list_height && ( i + offset ) < constructs.size(); i++ ) {
            int current = i + offset;
            std::string con_name = constructs[current];
            bool highlight = ( current == select );

            trim_and_print( w_list, i, 0, w_list_width,
                            construction_color( con_name, highlight ), "%s",
                            con_name.c_str() );
        }

        if( update_info ) {
            update_info = false;
            // Clear out lines for tools & materials
            const int pos_x = w_list_width + w_list_x0 + 2;
            const int available_window_width = w_width - pos_x - 1;
            for( int i = 1; i < w_height - 1; i++ ) {
                mvwhline( w_con, i, pos_x, ' ', available_window_width );
            }

            nc_color color_stage = c_white;
            std::vector<std::string> notes;
            notes.push_back( string_format( _( "Press %s or %s to tab." ),
                             ctxt.get_desc( "LEFT" ).c_str(), ctxt.get_desc( "RIGHT" ).c_str() ) );
            notes.push_back( string_format( _( "Press %s to search." ),
                             ctxt.get_desc( "FILTER" ).c_str() ) );
            notes.push_back( string_format( _( "Press %s to toggle unavailable constructions." ),
                            ctxt.get_desc( "TOGGLE_UNAVAILABLE_CONSTRUCTIONS" ).c_str() ) );
            notes.push_back( string_format( _( "Press %s to view and edit key-bindings." ),
                            ctxt.get_desc( "HELP_KEYBINDINGS" ).c_str() ) );

            //leave room for top and bottom UI text
            const int available_buffer_height = w_height - 3 - 3 - (int)notes.size();

            // print the hotkeys regardless of if there are constructions
            for( size_t i = 0; i < notes.size(); ++i ) {
                trim_and_print( w_con, w_height - 1 - (int)notes.size() + (int)i, pos_x,
                                available_window_width, c_white, "%s", notes[i].c_str() );
            }

            if( !constructs.empty() ) {
                if( select >= (int) constructs.size() ){
                    select = 0;
                }
                std::string current_desc = constructs[select];
                // Print construction name
                trim_and_print( w_con, 1, pos_x, available_window_width, c_white,
                                "%s", current_desc.c_str() );

                //only reconstruct the project list when moving away from the current item, or when changing the display mode
                if( previous_select != select || previous_tabindex != tabindex ||
                    previous_hide_unconstructable != hide_unconstructable ) {
                    previous_select = select;
                    previous_tabindex = tabindex;
                    previous_hide_unconstructable = hide_unconstructable;

                    //construct the project list buffer

                    // Print stages and their requirement.
                    std::vector<construction *> options = constructions_by_desc( current_desc );

                    construct_buffers.clear();
                    total_project_breakpoints = 0;
                    current_construct_breakpoint = 0;
                    construct_buffer_breakpoints.clear();
                    full_construct_buffer.clear();
                    int stage_counter = 0;
                    for( std::vector<construction *>::iterator it = options.begin();
                         it != options.end(); ++it ) {
                        stage_counter++;
                        construction *current_con = *it;
                        if( hide_unconstructable && !can_construct( *current_con ) ) {
                            continue;
                        }
                        // Update the cached availability of components and tools in the requirement object
                        current_con->requirements->can_make_with_inventory( total_inv );

                        std::vector<std::string> current_buffer;
                        std::ostringstream current_line;

                        // display result only if more than one step.
                        // Assume single stage constructions should be clear
                        // in their description what their result is.
                        if( current_con->post_terrain != "" && options.size() > 1 ) {
                            //also print out stage number when multiple stages are available
                            current_line << _( "Stage #" ) << stage_counter;
                            current_buffer.push_back( current_line.str() );
                            current_line.str( "" );

                            std::string result_string;
                            if( current_con->post_is_furniture ) {
                                result_string = furn_str_id( current_con->post_terrain ).obj().name;
                            } else {
                                result_string = ter_str_id( current_con->post_terrain ).obj().name;
                            }
                            current_line << "<color_" << string_from_color( color_stage ) << ">" << string_format(
                                             _( "Result: %s" ), result_string.c_str() ) << "</color>";
                            std::vector<std::string> folded_result_string = foldstring( current_line.str(),
                                    available_window_width );
                            current_buffer.insert( current_buffer.end(), folded_result_string.begin(),
                                                   folded_result_string.end() );
                        }

                        current_line.str( "" );
                        // display required skill and difficulty
                        int pskill = g->u.get_skill_level( current_con->skill );
                        int diff = ( current_con->difficulty > 0 ) ? current_con->difficulty : 0;

                        current_line << "<color_" << string_from_color( ( pskill >= diff ? c_white : c_red ) ) << ">" <<
                                     string_format( _( "Skill Req: %d (%s)" ), diff,
                                                    current_con->skill.obj().name().c_str() ) << "</color>";
                        current_buffer.push_back( current_line.str() );
                        // TODO: Textify pre_flags to provide a bit more information.
                        // Example: First step of dig pit could say something about
                        // requiring diggable ground.
                        current_line.str( "" );
                        if( current_con->pre_terrain != "" ) {
                            std::string require_string;
                            if( current_con->pre_is_furniture ) {
                                require_string = furn_str_id( current_con->pre_terrain ).obj().name;
                            } else {
                                require_string = ter_str_id( current_con->pre_terrain ).obj().name;
                            }
                            current_line << "<color_" << string_from_color( color_stage ) << ">" << string_format(
                                             _( "Requires: %s" ), require_string.c_str() ) << "</color>";
                            std::vector<std::string> folded_result_string = foldstring( current_line.str(),
                                    available_window_width );
                            current_buffer.insert( current_buffer.end(), folded_result_string.begin(),
                                                   folded_result_string.end() );
                        }
                        // get pre-folded versions of the rest of the construction project to be displayed later

                        // get time needed
                        std::vector<std::string> folded_time = current_con->get_folded_time_string(
                                available_window_width );
                        current_buffer.insert( current_buffer.end(), folded_time.begin(), folded_time.end() );

                        std::vector<std::string> folded_tools = current_con->requirements->get_folded_tools_list(
                                available_window_width, color_stage, total_inv );
                        current_buffer.insert( current_buffer.end(), folded_tools.begin(), folded_tools.end() );

                        std::vector<std::string> folded_components = current_con->requirements->get_folded_components_list(
                                    available_window_width, color_stage, total_inv );
                        current_buffer.insert( current_buffer.end(), folded_components.begin(), folded_components.end() );

                        construct_buffers.push_back( current_buffer );
                    }

                    //determine where the printing starts for each project, so it can be scrolled to those points
                    size_t current_buffer_location = 0;
                    for( size_t i = 0; i < construct_buffers.size(); i++ ) {
                        construct_buffer_breakpoints.push_back( static_cast<int>( current_buffer_location ) );
                        full_construct_buffer.insert( full_construct_buffer.end(), construct_buffers[i].begin(),
                                                      construct_buffers[i].end() );

                        //handle text too large for one screen
                        if( construct_buffers[i].size() > static_cast<size_t>( available_buffer_height ) ) {
                            construct_buffer_breakpoints.push_back( static_cast<int>( current_buffer_location +
                                                                    static_cast<size_t>( available_buffer_height ) ) );
                        }
                        current_buffer_location += construct_buffers[i].size();
                        if( i < construct_buffers.size() - 1 ) {
                            full_construct_buffer.push_back( std::string( "" ) );
                            current_buffer_location++;
                        }
                    }
                    total_project_breakpoints = static_cast<int>( construct_buffer_breakpoints.size() );
                }
                if( current_construct_breakpoint > 0 ) {
                    // Print previous stage indicator if breakpoint is past the beginning
                    trim_and_print( w_con, 2, pos_x, available_window_width, c_white,
                                    _( "Press %s to show previous stage(s)." ),
                                    ctxt.get_desc( "PAGE_UP" ).c_str() );
                }
                if( static_cast<size_t>( construct_buffer_breakpoints[current_construct_breakpoint] +
                                         available_buffer_height ) < full_construct_buffer.size() ) {
                    // Print next stage indicator if more breakpoints are remaining after screen height
                    trim_and_print( w_con, w_height - 2 - (int)notes.size(), pos_x, available_window_width,
                                    c_white, _( "Press %s to show next stage(s)." ),
                                    ctxt.get_desc( "PAGE_DOWN" ).c_str() );
                }
                // Leave room for above/below indicators
                int ypos = 3;
                nc_color stored_color = color_stage;
                for( size_t i = static_cast<size_t>( construct_buffer_breakpoints[current_construct_breakpoint] );
                     i < full_construct_buffer.size(); i++ ) {
                    //the value of 3 is from leaving room at the top of window
                    if( ypos > available_buffer_height + 3 ) {
                        break;
                    }
                    print_colored_text( w_con, ypos++, ( w_list_width + w_list_x0 + 2 ), stored_color, color_stage, full_construct_buffer[i] );
                }
            }
        } // Finished updating

        draw_scrollbar( w_con, select, w_list_height, constructs.size(), 3 );
        wrefresh( w_con );
        wrefresh( w_list );

        const std::string action = ctxt.handle_input();
        if( action == "FILTER" ){
            filter = string_input_popup( _( "Search" ), 50, filter, "", _( "Filter" ), 100, false );
            if( !filter.empty() ){
                update_info = true;
                update_cat = true;
                tabindex = 9;
                select = 0;
            }else if( previous_index !=9 ){
                tabindex = previous_index;
                update_info = true;
                update_cat = true;
                select = 0;
            }
            uistate.construction_filter = filter;
        } else if( action == "DOWN" ) {
            update_info = true;
            if( select < ( int )constructs.size() - 1 ) {
                select++;
            } else {
                select = 0;
            }
        } else if( action == "UP" ) {
            update_info = true;
            if( select > 0 ) {
                select--;
            } else {
                select = constructs.size() - 1;
            }
        } else if( action == "LEFT" ) {
            update_info = true;
            update_cat = true;
            select = 0;
            tabindex--;
            if( tabindex < 0 ) {
                tabindex = tabcount - 1;
            }
        } else if( action == "RIGHT" ) {
            update_info = true;
            update_cat = true;
            select = 0;
            tabindex = ( tabindex + 1 ) % tabcount;
        } else if( action == "PAGE_UP" ) {
            update_info = true;
            if( current_construct_breakpoint > 0 ) {
                current_construct_breakpoint--;
            }
            if( current_construct_breakpoint < 0 ) {
                current_construct_breakpoint = 0;
            }
        } else if( action == "PAGE_DOWN" ) {
            update_info = true;
            if( current_construct_breakpoint < total_project_breakpoints - 1 ) {
                current_construct_breakpoint++;
            }
            if( current_construct_breakpoint >= total_project_breakpoints ) {
                current_construct_breakpoint = total_project_breakpoints - 1;
            }
        } else if( action == "QUIT" ) {
            exit = true;
        } else if( action == "HELP_KEYBINDINGS" ) {
            draw_grid( w_con, w_list_width + w_list_x0 );
        } else if( action == "TOGGLE_UNAVAILABLE_CONSTRUCTIONS" ) {
            update_info = true;
            update_cat = true;
            hide_unconstructable = !hide_unconstructable;
            select = 0;
            offset = 0;
            load_available_constructions( available, cat_available, hide_unconstructable );
        } else if( action == "CONFIRM" ) {
            if( constructs.empty() || select >= (int) constructs.size() ){
                continue;// Nothing to be done here
            }
            if( player_can_build( g->u, total_inv, constructs[select] ) ) {
                place_construction( constructs[select] );
                uistate.last_construction = constructs[select];
                exit = true;
            } else {
                popup( _( "You can't build that!" ) );
                draw_grid( w_con, w_list_width + w_list_x0 );
                update_info = true;
            }
        }
    } while( !exit );

    w_list_ptr.reset();
    w_con_ptr.reset();
    g->refresh_all();
}
Esempio n. 4
0
void input_context::display_help()
{
    inp_mngr.set_timeout(-1);
    // Shamelessly stolen from help.cpp
    WINDOW *w_help = newwin(FULL_SCREEN_HEIGHT - 2, FULL_SCREEN_WIDTH - 2,
                            1 + (int)((TERMY > FULL_SCREEN_HEIGHT) ? (TERMY - FULL_SCREEN_HEIGHT) / 2 : 0),
                            1 + (int)((TERMX > FULL_SCREEN_WIDTH) ? (TERMX - FULL_SCREEN_WIDTH) / 2 : 0));

    // has the user changed something?
    bool changed = false;
    // keybindings before the user changed anything.
    input_manager::t_action_contexts old_action_contexts(inp_mngr.action_contexts);
    // current status: adding/removing/showing keybindings
    enum { s_remove, s_add, s_add_global, s_show } status = s_show;
    // copy of registered_actions, but without the ANY_INPUT and COORDINATE, which should not be shown
    std::vector<std::string> org_registered_actions(registered_actions);
    std::vector<std::string>::iterator any_input = std::find(org_registered_actions.begin(),
            org_registered_actions.end(), ANY_INPUT);
    if (any_input != org_registered_actions.end()) {
        org_registered_actions.erase(any_input);
    }
    std::vector<std::string>::iterator coordinate = std::find(org_registered_actions.begin(),
            org_registered_actions.end(), COORDINATE);
    if (coordinate != org_registered_actions.end()) {
        org_registered_actions.erase(coordinate);
    }

    // colors of the keybindings
    static const nc_color global_key = c_ltgray;
    static const nc_color local_key = c_ltgreen;
    static const nc_color unbound_key = c_ltred;
    // (vertical) scroll offset
    size_t scroll_offset = 0;
    // height of the area usable for display of keybindings, excludes headers & borders
    const size_t display_height = FULL_SCREEN_HEIGHT - 2 - 2; // -2 for the border
    // width of the legend
    const size_t legwidth = FULL_SCREEN_WIDTH - 51 - 2;
    // keybindings help
    std::ostringstream legend;
    legend << "<color_" << string_from_color(unbound_key) << ">" << _("Unbound keys") << "</color>\n";
    legend << "<color_" << string_from_color(local_key) << ">" <<
           _("Keybinding active only on this screen") << "</color>\n";
    legend << "<color_" << string_from_color(global_key) << ">" << _("Keybinding active globally") <<
           "</color>\n";
    legend << _("Press - to remove keybinding\nPress + to add local keybinding\nPress = to add global keybinding\n");

    input_context ctxt("HELP_KEYBINDINGS");
    ctxt.register_action("UP", _("Scroll up"));
    ctxt.register_action("DOWN", _("Scroll down"));
    ctxt.register_action("PAGE_DOWN");
    ctxt.register_action("PAGE_UP");
    ctxt.register_action("REMOVE");
    ctxt.register_action("ADD_LOCAL");
    ctxt.register_action("ADD_GLOBAL");
    ctxt.register_action("QUIT");
    ctxt.register_action("ANY_INPUT");

    if (category != "HELP_KEYBINDINGS") {
        // avoiding inception!
        ctxt.register_action("HELP_KEYBINDINGS");
    }

    std::string hotkeys = ctxt.get_available_single_char_hotkeys(display_help_hotkeys);

    while(true) {
        werase(w_help);
        draw_border(w_help);
        draw_scrollbar(w_help, scroll_offset, display_height, org_registered_actions.size() - display_height, 1);
        mvwprintz(w_help, 0, (FULL_SCREEN_WIDTH - utf8_width(_("Keybindings"))) / 2 - 1,
                  c_ltred, " %s ", _("Keybindings"));

        fold_and_print(w_help, 1, 51, legwidth, c_white, legend.str());

        for (size_t i = 0; i + scroll_offset < org_registered_actions.size() && i < display_height; i++) {
            const std::string &action_id = org_registered_actions[i + scroll_offset];

            bool overwrite_default;
            const action_attributes &attributes = inp_mngr.get_action_attributes(action_id, category,
                                                  &overwrite_default);

            char invlet;
            if (i < hotkeys.size()) {
                invlet = hotkeys[i];
            } else {
                invlet = ' ';
            }

            if (status == s_add_global && overwrite_default) {
                // We're trying to add a global, but this action has a local
                // defined, so gray out the invlet.
                mvwprintz(w_help, i + 1, 2, c_dkgray, "%c ", invlet);
            } else if (status == s_add || status == s_add_global) {
                mvwprintz(w_help, i + 1, 2, c_blue, "%c ", invlet);
            } else if (status == s_remove) {
                mvwprintz(w_help, i + 1, 2, c_blue, "%c ", invlet);
            } else {
                mvwprintz(w_help, i + 1, 2, c_blue, "  ");
            }
            nc_color col;
            if (attributes.input_events.empty()) {
                col = unbound_key;
            } else if (overwrite_default) {
                col = local_key;
            } else {
                col = global_key;
            }
            mvwprintz(w_help, i + 1, 4, col, "%s: ", get_action_name(action_id).c_str());
            mvwprintz(w_help, i + 1, 30, col, "%s", get_desc(action_id).c_str());
        }
        wrefresh(w_help);
        refresh();

        // In addition to the modifiable hotkeys, we also check for hardcoded
        // keys, e.g. '+', '-', '=', in order to prevent the user from
        // entering an unrecoverable state.
        const std::string action = ctxt.handle_input();
        const long raw_input_char = ctxt.get_raw_input().get_first_input();
        if (action == "ADD_LOCAL" || raw_input_char == '+') {
            status = s_add;
        } else if (action == "ADD_GLOBAL" || raw_input_char == '=') {
            status = s_add_global;
        } else if (action == "REMOVE" || raw_input_char == '-') {
            status = s_remove;
        } else if (action == "ANY_INPUT") {
            const size_t hotkey_index = hotkeys.find_first_of(raw_input_char);
            if (status == s_show || hotkey_index == std::string::npos ) {
                continue;
            }
            const size_t action_index = hotkey_index + scroll_offset;
            if( action_index >= org_registered_actions.size() ) {
                continue;
            }
            const std::string &action_id = org_registered_actions[action_index];

            // Check if this entry is local or global.
            bool is_local = false;
            inp_mngr.get_action_attributes(action_id, category, &is_local);
            const std::string name = get_action_name(action_id);


            if (status == s_remove && (!OPTIONS["QUERY_KEYBIND_REMOVAL"] ||
                                       query_yn(_("Clear keys for %s?"), name.c_str()))) {

                // If it's global, reset the global actions.
                std::string category_to_access = category;
                if (!is_local) {
                    category_to_access = default_context_id;
                }

                inp_mngr.remove_input_for_action(action_id, category_to_access);
                changed = true;
            } else if (status == s_add_global && is_local) {
                // Disallow adding global actions to an action that already has a local defined.
                popup(_("There are already local keybindings defined for this action, please remove them first."));
            } else if (status == s_add || status == s_add_global) {
                const long newbind = popup_getkey(_("New key for %s:"), name.c_str());
                const input_event new_event(newbind, CATA_INPUT_KEYBOARD);
                const std::string conflicts = get_conflicts(new_event);
                const bool has_conflicts = !conflicts.empty();
                bool resolve_conflicts = false;

                if (has_conflicts) {
                    resolve_conflicts = query_yn(
                                            _("This key conflicts with %s. Remove this key from the conflicting command(s), and continue?"),
                                            conflicts.c_str());
                }

                if (!has_conflicts || resolve_conflicts) {
                    if (resolve_conflicts) {
                        clear_conflicting_keybindings(new_event);
                    }

                    // We might be adding a local or global action.
                    std::string category_to_access = category;
                    if (status == s_add_global) {
                        category_to_access = default_context_id;
                    }

                    inp_mngr.add_input_for_action(action_id, category_to_access, new_event);
                    changed = true;
                }
            }
            status = s_show;
        } else if (action == "DOWN") {
            if (scroll_offset < org_registered_actions.size() - display_height) {
                scroll_offset++;
            }
        } else if (action == "UP") {
            if (scroll_offset > 0) {
                scroll_offset--;
            }
        } else if (action == "PAGE_DOWN") {
            if( scroll_offset + display_height < org_registered_actions.size() ) {
                scroll_offset += std::min(display_height, org_registered_actions.size() -
                                          display_height - scroll_offset);
            } else if( org_registered_actions.size() > display_height ) {
                scroll_offset = 0;
            }
        } else if( action == "PAGE_UP" ) {
            if( scroll_offset >= display_height ) {
                scroll_offset -= display_height;
            } else if( scroll_offset > 0 ) {
                scroll_offset = 0;
            } else if( org_registered_actions.size() > display_height ) {
                scroll_offset = org_registered_actions.size() - display_height;
            }
        } else if (action == "QUIT") {
            if (status != s_show) {
                status = s_show;
            } else {
                break;
            }
        } else if (action == "HELP_KEYBINDINGS") {
            // update available hotkeys in case they've changed
            hotkeys = ctxt.get_available_single_char_hotkeys(display_help_hotkeys);
        }
    }

    if (changed && query_yn(_("Save changes?"))) {
        try {
            inp_mngr.save();
        } catch(std::exception &err) {
            popup(_("saving keybindings failed: %s"), err.what());
        } catch(std::string &err) {
            popup(_("saving keybindings failed: %s"), err.c_str());
        }
    } else if(changed) {
        inp_mngr.action_contexts.swap(old_action_contexts);
    }
    werase(w_help);
    wrefresh(w_help);
    delwin(w_help);
}
Esempio n. 5
0
SICALLBACK ToonixLighter_Term( CRef& in_ctxt )
{
	Context ctxt(in_ctxt);
	CleanUpLighterUserData(ctxt);
	return CStatus::OK;
}
Esempio n. 6
0
int worldfactory::show_worldgen_tab_modselection(WINDOW *win, WORLDPTR world)
{
    // Use active_mod_order of the world,
    // saves us from writting 'world->active_mod_order' all the time.
    std::vector<std::string> &active_mod_order = world->active_mod_order;
    {
        std::vector<std::string> tmp_mod_order;
        // clear active_mod_order and re-add all the mods, his ensures
        // that changes (like changing depencies) get updated
        tmp_mod_order.swap(active_mod_order);
        for(size_t i = 0; i < tmp_mod_order.size(); i++) {
            mman_ui->try_add(tmp_mod_order[i], active_mod_order);
        }
    }

    const int iOffsetX = (TERMX > FULL_SCREEN_WIDTH) ? (TERMX - FULL_SCREEN_WIDTH) / 2 : 0;
    const int iOffsetY = (TERMY > FULL_SCREEN_HEIGHT) ? (TERMY - FULL_SCREEN_HEIGHT) / 2 : 0;

    // lots of small windows so that each section can be drawn to independently of the others as necessary
    WINDOW *w_header1, *w_header2, *w_shift, *w_list, *w_active, *w_description;
    w_header1 = newwin(1, FULL_SCREEN_WIDTH / 2 - 5, 3 + iOffsetY, 1 + iOffsetX);
    w_header2 = newwin(1, FULL_SCREEN_WIDTH / 2 - 4, 3 + iOffsetY,
                       FULL_SCREEN_WIDTH / 2 + 3 + iOffsetX);
    w_shift   = newwin(13, 5, 3 + iOffsetY, FULL_SCREEN_WIDTH / 2 - 3 + iOffsetX);
    w_list    = newwin(11, FULL_SCREEN_WIDTH / 2 - 4, 5 + iOffsetY, iOffsetX);
    w_active  = newwin(11, FULL_SCREEN_WIDTH / 2 - 4, 5 + iOffsetY,
                       FULL_SCREEN_WIDTH / 2 + 2 + iOffsetX);
    w_description = newwin(4, FULL_SCREEN_WIDTH - 2, 19 + iOffsetY, 1 + iOffsetX);

    draw_modselection_borders(win);
    std::vector<std::string> headers;
    headers.push_back(_("Mod List"));
    headers.push_back(_("Mod Load Order"));
    std::vector<WINDOW *> header_windows;
    header_windows.push_back(w_header1);
    header_windows.push_back(w_header2);

    int tab_output = 0;
    int last_active_header = 0;
    size_t active_header = 0;
    size_t useable_mod_count = mman_ui->usable_mods.size();
    int startsel[2] = {0, 0};
    int cursel[2] = {0, 0};

    bool redraw_headers = true;
    bool redraw_shift = true;
    bool redraw_description = true;
    bool redraw_list = true;
    bool redraw_active = true;
    bool selection_changed = false;

    input_context ctxt("MODMANAGER_DIALOG");
    ctxt.register_cardinal();
    ctxt.register_action("HELP_KEYBINDINGS");
    ctxt.register_action("QUIT");
    ctxt.register_action("NEXT_TAB");
    ctxt.register_action("PREV_TAB");
    ctxt.register_action("CONFIRM");
    ctxt.register_action("ADD_MOD");
    ctxt.register_action("REMOVE_MOD");
    ctxt.register_action("SAVE_DEFAULT_MODS");

    while (tab_output == 0) {
        if (redraw_headers) {
            for (size_t i = 0; i < headers.size(); ++i) {
                werase(header_windows[i]);
                const int header_x = (getmaxx(header_windows[i]) - headers[i].size()) / 2;
                mvwprintz(header_windows[i], 0, header_x , c_cyan, "%s", headers[i].c_str());

                if (active_header == i) {
                    mvwputch(header_windows[i], 0, header_x - 3, c_red, '<');
                    mvwputch(header_windows[i], 0, header_x + headers[i].size() + 2, c_red, '>');
                }
                wrefresh(header_windows[i]);
            }
            redraw_list = true;
            redraw_active = true;
            redraw_shift = true;
            redraw_headers = false;
        }
        if (selection_changed) {
            if (active_header == 0) {
                redraw_list = true;
            }
            if (active_header == 1) {
                redraw_shift = true;
                redraw_active = true;
            }
            selection_changed = false;
            redraw_description = true;
        }
        if (redraw_description) {
            werase(w_description);

            MOD_INFORMATION *selmod = NULL;
            if (mman_ui->usable_mods.empty()) {
                // Do nothing, leave selmod == NULL
            } else if (active_header == 0) {
                selmod = mman->mod_map[mman_ui->usable_mods[cursel[0]]];
            } else if (!active_mod_order.empty()) {
                selmod = mman->mod_map[active_mod_order[cursel[1]]];
            }

            if (selmod != NULL) {
                fold_and_print(w_description, 0, 1, getmaxx(w_description) - 1,
                               c_white, mman_ui->get_information(selmod));
            }
            redraw_description = false;
            wrefresh(w_description);
        }
        if (redraw_list) {
            werase(w_list);
            calcStartPos(startsel[0], cursel[0], getmaxy(w_list), useable_mod_count);

            if (useable_mod_count == 0) {
                center_print(w_list, 0, c_red, _("--NO AVAILABLE MODS--"));
            } else {
                std::stringstream list_output;

                for (size_t i = startsel[0], c = 0; i < useable_mod_count && c < getmaxy(w_list); ++i, ++c) {
                    if ((ssize_t)i != cursel[0]) {
                        list_output << std::string(3, ' ');
                    } else {
                        if (active_header == 0) {
                            list_output << "<color_yellow>";
                        } else {
                            list_output << "<color_blue>";
                        }
                        list_output << ">></color> ";
                    }
                    list_output << mman->mod_map[mman_ui->usable_mods[i]]->name << "\n";
                }
                fold_and_print(w_list, 0, 1, getmaxx(w_list) - 1, c_white, list_output.str());
            }
            draw_scrollbar(w_list, cursel[0], getmaxy(w_list), useable_mod_count, 0, 0);

            wrefresh(w_list);
        }
        if (redraw_active) {
            werase(w_active);
            const int active_count = active_mod_order.size();
            calcStartPos(startsel[1], cursel[1], getmaxy(w_active), active_count);

            if (active_count == 0) {
                center_print(w_active, 0, c_red, _("--NO ACTIVE MODS--"));
            } else {
                std::stringstream list_output;

                for (int i = startsel[1], c = 0; i < active_count && c < getmaxy(w_active); ++i, ++c) {
                    if (i != cursel[1]) {
                        list_output << std::string(3, ' ');
                    } else {
                        if (active_header == 1) {
                            list_output << "<color_yellow>";
                        } else {
                            list_output << "<color_blue>";
                        }
                        list_output << ">></color> ";
                    }
                    list_output << mman->mod_map[active_mod_order[i]]->name << "\n";
                }
                fold_and_print(w_active, 0, 1, getmaxx(w_active) - 1, c_white, list_output.str());
            }

            draw_scrollbar(w_active, cursel[1], getmaxy(w_active), active_count, 0, 0);

            wrefresh(w_active);
        }
        if (redraw_shift) {
            werase(w_shift);
            if (active_header == 1) {
                std::stringstream shift_display;
                // get shift information for whatever is visible in the active list
                for (size_t i = startsel[1], c = 0; i < active_mod_order.size() && c < getmaxy(w_active); ++i, ++c) {
                    if (mman_ui->can_shift_up(i, active_mod_order)) {
                        shift_display << "<color_blue>+</color> ";
                    } else {
                        shift_display << "<color_dkgray>+</color> ";
                    }
                    if (mman_ui->can_shift_down(i, active_mod_order)) {
                        shift_display << "<color_blue>-</color>";
                    } else {
                        shift_display << "<color_dkgray>-</color>";
                    }
                    shift_display << "\n";
                }
                fold_and_print(w_shift, 2, 1, getmaxx(w_shift), c_white, shift_display.str());
            }
            redraw_shift = false;
            wrefresh(w_shift);
        }
        refresh();

        last_active_header = active_header;
        const int next_header = (active_header == 1) ? 0 : 1;
        const int prev_header = (active_header == 0) ? 1 : 0;

        int selection = (active_header == 0) ? cursel[0] : cursel[1];
        int last_selection = selection;
        unsigned int next_selection = selection + 1;
        int prev_selection = selection - 1;
        if (active_header == 0) {
            next_selection = (next_selection >= useable_mod_count) ? 0 : next_selection;
            prev_selection = (prev_selection < 0) ? useable_mod_count - 1 : prev_selection;
        } else {
            next_selection = (next_selection >= active_mod_order.size()) ? 0 : next_selection;
            prev_selection = (prev_selection < 0) ? active_mod_order.size() - 1 : prev_selection;
        }

        const std::string action = ctxt.handle_input();

        if (action == "DOWN") {
            selection = next_selection;
        } else if (action == "UP") {
            selection = prev_selection;
        } else if (action == "RIGHT") {
            active_header = next_header;
        } else if (action == "LEFT") {
            active_header = prev_header;
        } else if (action == "CONFIRM") {
                if (active_header == 0 && !mman_ui->usable_mods.empty()) {
                    // try-add
                    mman_ui->try_add(mman_ui->usable_mods[cursel[0]], active_mod_order);
                    redraw_active = true;
                    redraw_shift = true;
                } else if (active_header == 1 && !active_mod_order.empty()) {
                    // try-rem
                    mman_ui->try_rem(cursel[1], active_mod_order);
                    redraw_active = true;
                    redraw_shift = true;
                    if (active_mod_order.empty()) {
                        // switch back to other list, we can't change
                        // anything in the empty active mods list.
                        active_header = 0;
                    }
                }
        } else if (action == "ADD_MOD") {
                if (active_header == 1 && active_mod_order.size() > 1) {
                    mman_ui->try_shift('+', cursel[1], active_mod_order);
                    redraw_active = true;
                    redraw_shift = true;
                }
        } else if (action == "REMOVE_MOD") {
                if (active_header == 1 && active_mod_order.size() > 1) {
                    mman_ui->try_shift('-', cursel[1], active_mod_order);
                    redraw_active = true;
                    redraw_shift = true;
                }
        } else if (action == "NEXT_TAB") {
                tab_output = 1;
        } else if (action == "PREV_TAB") {
                tab_output = -1;
        } else if (action == "SAVE_DEFAULT_MODS") {
                if(mman->set_default_mods(active_mod_order)) {
                    popup(_("Saved list of active mods as default"));
                    draw_modselection_borders(win);
                    redraw_headers = true;
                }
        } else if (action == "QUIT") {
                tab_output = -999;
        }
        // RESOLVE INPUTS
        if (last_active_header != (ssize_t)active_header) {
            redraw_headers = true;
            redraw_shift = true;
            redraw_description = true;
        }
        if (last_selection != selection) {
            if (active_header == 0) {
                redraw_list = true;
                cursel[0] = selection;
            } else {
                redraw_active = true;
                redraw_shift = true;
                cursel[1] = selection;
            }
            redraw_description = true;
        }
        if (active_mod_order.empty()) {
            redraw_active = true;
            cursel[1] = 0;
        }

        if (active_header == 1) {
            if (active_mod_order.empty()) {
                cursel[1] = 0;
            } else {
                if (cursel[1] < 0) {
                    cursel[1] = 0;
                } else if (cursel[1] >= (ssize_t)active_mod_order.size()) {
                    cursel[1] = active_mod_order.size() - 1;
                }
            }
        }
        // end RESOLVE INPUTS
    }
    werase(w_header1);
    werase(w_header2);
    werase(w_shift);
    werase(w_list);
    werase(w_active);
    werase(w_description);

    delwin(w_header1);
    delwin(w_header2);
    delwin(w_shift);
    delwin(w_list);
    delwin(w_active);
    delwin(w_description);
    return tab_output;
}
Esempio n. 7
0
void safemode::show( const std::string &custom_name_in, bool is_safemode_in )
{
    auto global_rules_old = global_rules;
    auto character_rules_old = character_rules;

    const int header_height = 4;
    const int content_height = FULL_SCREEN_HEIGHT - 2 - header_height;

    const int offset_x = ( TERMX > FULL_SCREEN_WIDTH ) ? ( TERMX - FULL_SCREEN_WIDTH ) / 2 : 0;
    const int offset_y = ( TERMY > FULL_SCREEN_HEIGHT ) ? ( TERMY - FULL_SCREEN_HEIGHT ) / 2 : 0;

    enum Columns : int {
        COLUMN_RULE,
        COLUMN_ATTITUDE,
        COLUMN_PROXIMITY,
        COLUMN_WHITE_BLACKLIST,
    };

    std::map<int, int> column_pos;
    column_pos[COLUMN_RULE] = 4;
    column_pos[COLUMN_ATTITUDE] = 48;
    column_pos[COLUMN_PROXIMITY] = 59;
    column_pos[COLUMN_WHITE_BLACKLIST] = 66;

    const int num_columns = column_pos.size();

    catacurses::window w_help = catacurses::newwin( ( FULL_SCREEN_HEIGHT / 2 ) - 2,
                                FULL_SCREEN_WIDTH * 3 / 4, 7 + offset_y + ( FULL_SCREEN_HEIGHT / 2 ) / 2, offset_x + 19 / 2 );
    catacurses::window w_border = catacurses::newwin( FULL_SCREEN_HEIGHT, FULL_SCREEN_WIDTH,
                                  offset_y, offset_x );
    catacurses::window w_header = catacurses::newwin( header_height, FULL_SCREEN_WIDTH - 2,
                                  1 + offset_y, 1 + offset_x );
    catacurses::window w = catacurses::newwin( content_height, FULL_SCREEN_WIDTH - 2,
                           header_height + 1 + offset_y, 1 + offset_x );

    draw_border( w_border, BORDER_COLOR, custom_name_in );

    mvwputch( w_border, 3,  0, c_light_gray, LINE_XXXO ); // |-
    mvwputch( w_border, 3, 79, c_light_gray, LINE_XOXX ); // -|

    for( auto &column : column_pos ) {
        mvwputch( w_border, FULL_SCREEN_HEIGHT - 1, column.second + 1, c_light_gray,
                  LINE_XXOX ); // _|_
    }

    wrefresh( w_border );

    static const std::vector<std::string> hotkeys = {{
            _( "<A>dd" ), _( "<R>emove" ), _( "<C>opy" ), _( "<M>ove" ),
            _( "<E>nable" ), _( "<D>isable" ), _( "<T>est" )
        }
    };

    int tmpx = 0;
    for( auto &hotkey : hotkeys ) {
        tmpx += shortcut_print( w_header, 0, tmpx, c_white, c_light_green, hotkey ) + 2;
    }

    tmpx = 0;
    tmpx += shortcut_print( w_header, 1, tmpx, c_white, c_light_green, _( "<+-> Move up/down" ) ) + 2;
    tmpx += shortcut_print( w_header, 1, tmpx, c_white, c_light_green, _( "<Enter>-Edit" ) ) + 2;
    shortcut_print( w_header, 1, tmpx, c_white, c_light_green, _( "<Tab>-Switch Page" ) );

    for( int i = 0; i < 78; i++ ) {
        mvwputch( w_header, 2, i, c_light_gray, LINE_OXOX ); // Draw line under header
    }

    for( auto &pos : column_pos ) {
        mvwputch( w_header, 2, pos.second, c_light_gray, LINE_OXXX );
        mvwputch( w_header, 3, pos.second, c_light_gray, LINE_XOXO );
    }

    mvwprintz( w_header, 3, 1, c_white, "#" );
    mvwprintz( w_header, 3, column_pos[COLUMN_RULE] + 4, c_white, _( "Rules" ) );
    mvwprintz( w_header, 3, column_pos[COLUMN_ATTITUDE] + 2, c_white, _( "Attitude" ) );
    mvwprintz( w_header, 3, column_pos[COLUMN_PROXIMITY] + 2, c_white, _( "Dist" ) );
    mvwprintz( w_header, 3, column_pos[COLUMN_WHITE_BLACKLIST] + 2, c_white, _( "B/W" ) );

    wrefresh( w_header );

    int tab = GLOBAL_TAB;
    int line = 0;
    int column = 0;
    int start_pos = 0;
    bool changes_made = false;
    input_context ctxt( "SAFEMODE" );
    ctxt.register_cardinal();
    ctxt.register_action( "CONFIRM" );
    ctxt.register_action( "QUIT" );
    ctxt.register_action( "NEXT_TAB" );
    ctxt.register_action( "PREV_TAB" );
    ctxt.register_action( "ADD_DEFAULT_RULESET" );
    ctxt.register_action( "ADD_RULE" );
    ctxt.register_action( "REMOVE_RULE" );
    ctxt.register_action( "COPY_RULE" );
    ctxt.register_action( "ENABLE_RULE" );
    ctxt.register_action( "DISABLE_RULE" );
    ctxt.register_action( "MOVE_RULE_UP" );
    ctxt.register_action( "MOVE_RULE_DOWN" );
    ctxt.register_action( "TEST_RULE" );
    ctxt.register_action( "HELP_KEYBINDINGS" );

    if( is_safemode_in ) {
        ctxt.register_action( "SWITCH_SAFEMODE_OPTION" );
        ctxt.register_action( "SWAP_RULE_GLOBAL_CHAR" );
    }

    while( true ) {
        int locx = 17;
        locx += shortcut_print( w_header, 2, locx, c_white,
                                ( tab == GLOBAL_TAB ) ? hilite( c_white ) : c_white, _( "[<Global>]" ) ) + 1;
        shortcut_print( w_header, 2, locx, c_white,
                        ( tab == CHARACTER_TAB ) ? hilite( c_white ) : c_white, _( "[<Character>]" ) );

        locx = 55;
        mvwprintz( w_header, 0, locx, c_white, _( "Safe Mode enabled:" ) );
        locx += shortcut_print( w_header, 1, locx,
                                ( ( get_option<bool>( "SAFEMODE" ) ) ? c_light_green : c_light_red ), c_white,
                                ( ( get_option<bool>( "SAFEMODE" ) ) ? _( "True" ) : _( "False" ) ) );
        locx += shortcut_print( w_header, 1, locx, c_white, c_light_green, "  " );
        locx += shortcut_print( w_header, 1, locx, c_white, c_light_green, _( "<S>witch" ) );
        shortcut_print( w_header, 1, locx, c_white, c_light_green, "  " );

        wrefresh( w_header );

        // Clear the lines
        for( int i = 0; i < content_height; i++ ) {
            for( int j = 0; j < 79; j++ ) {
                mvwputch( w, i, j, c_black, ' ' );
            }

            for( auto &pos : column_pos ) {
                mvwputch( w, i, pos.second, c_light_gray, LINE_XOXO );
            }
        }

        auto &current_tab = ( tab == GLOBAL_TAB ) ? global_rules : character_rules;

        if( tab == CHARACTER_TAB && g->u.name.empty() ) {
            character_rules.clear();
            mvwprintz( w, 8, 15, c_white, _( "Please load a character first to use this page!" ) );
        } else if( empty() ) {
            mvwprintz( w, 8, 15, c_white, _( "Safe Mode manager currently inactive." ) );
            mvwprintz( w, 9, 15, c_white, _( "Default rules are used. Add a rule to activate." ) );
            mvwprintz( w, 10, 15, c_white, _( "Press ~ to add a default ruleset to get started." ) );
        }

        draw_scrollbar( w_border, line, content_height, current_tab.size(), 5 );
        wrefresh( w_border );

        calcStartPos( start_pos, line, content_height, current_tab.size() );

        // display safe mode
        for( int i = start_pos; i < static_cast<int>( current_tab.size() ); i++ ) {
            if( i >= start_pos &&
                i < start_pos + std::min( content_height, static_cast<int>( current_tab.size() ) ) ) {

                auto rule = current_tab[i];

                nc_color line_color = ( rule.active ) ? c_white : c_light_gray;

                mvwprintz( w, i - start_pos, 1, line_color, "%d", i + 1 );
                mvwprintz( w, i - start_pos, 5, c_yellow, ( line == i ) ? ">> " : "   " );

                auto draw_column = [&]( Columns column_in, const std::string & text_in ) {
                    mvwprintz( w, i - start_pos, column_pos[column_in] + 2,
                               ( line == i && column == column_in ) ? hilite( line_color ) : line_color,
                               text_in
                             );
                };

                draw_column( COLUMN_RULE, ( rule.rule.empty() ) ? _( "<empty rule>" ) : rule.rule );
                draw_column( COLUMN_ATTITUDE, Creature::get_attitude_ui_data( rule.attitude ).first );
                draw_column( COLUMN_PROXIMITY, ( !rule.whitelist ) ? to_string( rule.proximity ) : "---" );
                draw_column( COLUMN_WHITE_BLACKLIST, ( rule.whitelist ) ? _( "Whitelist" ) : _( "Blacklist" ) );
            }
        }

        wrefresh( w );

        const std::string action = ctxt.handle_input();

        if( action == "NEXT_TAB" ) {
            tab++;
            if( tab >= MAX_TAB ) {
                tab = 0;
                line = 0;
            }
        } else if( action == "PREV_TAB" ) {
            tab--;
            if( tab < 0 ) {
                tab = MAX_TAB - 1;
                line = 0;
            }
        } else if( action == "QUIT" ) {
            break;
        } else if( tab == CHARACTER_TAB && g->u.name.empty() ) {
            //Only allow loaded games to use the char sheet
        } else if( action == "DOWN" ) {
            line++;
            if( line >= static_cast<int>( current_tab.size() ) ) {
                line = 0;
            }
        } else if( action == "UP" ) {
            line--;
            if( line < 0 ) {
                line = current_tab.size() - 1;
            }
        } else if( action == "ADD_DEFAULT_RULESET" ) {
            changes_made = true;
            current_tab.push_back( rules_class( "*", true, false, Creature::A_HOSTILE, 0 ) );
            line = current_tab.size() - 1;
        } else if( action == "ADD_RULE" ) {
            changes_made = true;
            current_tab.push_back( rules_class( "", true, false, Creature::A_HOSTILE,
                                                get_option<int>( "SAFEMODEPROXIMITY" ) ) );
            line = current_tab.size() - 1;
        } else if( action == "REMOVE_RULE" && !current_tab.empty() ) {
            changes_made = true;
            current_tab.erase( current_tab.begin() + line );
            if( line > static_cast<int>( current_tab.size() ) - 1 ) {
                line--;
            }
            if( line < 0 ) {
                line = 0;
            }
        } else if( action == "COPY_RULE" && !current_tab.empty() ) {
            changes_made = true;
            current_tab.push_back( current_tab[line] );
            line = current_tab.size() - 1;
        } else if( action == "SWAP_RULE_GLOBAL_CHAR" && !current_tab.empty() ) {
            if( ( tab == GLOBAL_TAB && !g->u.name.empty() ) || tab == CHARACTER_TAB ) {
                changes_made = true;
                //copy over
                auto &temp_rules_from = ( tab == GLOBAL_TAB ) ? global_rules : character_rules;
                auto &temp_rules_to = ( tab == GLOBAL_TAB ) ? character_rules : global_rules;

                temp_rules_to.push_back( temp_rules_from[line] );

                //remove old
                temp_rules_from.erase( temp_rules_from.begin() + line );
                line = temp_rules_from.size() - 1;
                tab = ( tab == GLOBAL_TAB ) ? CHARACTER_TAB : GLOBAL_TAB;
            }
        } else if( action == "CONFIRM" && !current_tab.empty() ) {
            changes_made = true;
            if( column == COLUMN_RULE ) {
                fold_and_print( w_help, 1, 1, 999, c_white,
                                _(
                                    "* is used as a Wildcard. A few Examples:\n"
                                    "\n"
                                    "human          matches every NPC\n"
                                    "zombie         matches the monster name exactly\n"
                                    "acidic zo*     matches monsters beginning with 'acidic zo'\n"
                                    "*mbie          matches monsters ending with 'mbie'\n"
                                    "*cid*zo*ie     multiple * are allowed\n"
                                    "AcI*zO*iE      case insensitive search" )
                              );

                draw_border( w_help );
                wrefresh( w_help );
                current_tab[line].rule = wildcard_trim_rule( string_input_popup()
                                         .title( _( "Safe Mode Rule:" ) )
                                         .width( 30 )
                                         .text( current_tab[line].rule )
                                         .query_string() );
            } else if( column == COLUMN_WHITE_BLACKLIST ) {
                current_tab[line].whitelist = !current_tab[line].whitelist;
            } else if( column == COLUMN_ATTITUDE ) {
                auto &attitude = current_tab[line].attitude;
                switch( attitude ) {
                    case Creature::A_HOSTILE:
                        attitude = Creature::A_NEUTRAL;
                        break;
                    case Creature::A_NEUTRAL:
                        attitude = Creature::A_FRIENDLY;
                        break;
                    case Creature::A_FRIENDLY:
                        attitude = Creature::A_ANY;
                        break;
                    case Creature::A_ANY:
                        attitude = Creature::A_HOSTILE;
                }
            } else if( column == COLUMN_PROXIMITY && !current_tab[line].whitelist ) {
                const auto text = string_input_popup()
                                  .title( _( "Proximity Distance (0=max view distance)" ) )
                                  .width( 4 )
                                  .text( to_string( current_tab[line].proximity ) )
                                  .description( _( "Option: " ) + to_string( get_option<int>( "SAFEMODEPROXIMITY" ) ) +
                                                " " + get_options().get_option( "SAFEMODEPROXIMITY" ).getDefaultText() )
                                  .max_length( 3 )
                                  .only_digits( true )
                                  .query_string();
                if( text.empty() ) {
                    current_tab[line].proximity = get_option<int>( "SAFEMODEPROXIMITY" );
                } else {
                    //Let the options class handle the validity of the new value
                    auto temp_option = get_options().get_option( "SAFEMODEPROXIMITY" );
                    temp_option.setValue( text );
                    current_tab[line].proximity = atoi( temp_option.getValue().c_str() );
                }
            }
        } else if( action == "ENABLE_RULE" && !current_tab.empty() ) {
            changes_made = true;
            current_tab[line].active = true;
        } else if( action == "DISABLE_RULE" && !current_tab.empty() ) {
            changes_made = true;
            current_tab[line].active = false;
        } else if( action == "LEFT" ) {
            column--;
            if( column < 0 ) {
                column = num_columns - 1;
            }
        } else if( action == "RIGHT" ) {
            column++;
            if( column >= num_columns ) {
                column = 0;
            }
        } else if( action == "MOVE_RULE_UP" && !current_tab.empty() ) {
            changes_made = true;
            if( line < static_cast<int>( current_tab.size() ) - 1 ) {
                std::swap( current_tab[line], current_tab[line + 1] );
                line++;
                column = 0;
            }
        } else if( action == "MOVE_RULE_DOWN" && !current_tab.empty() ) {
            changes_made = true;
            if( line > 0 ) {
                std::swap( current_tab[line],  current_tab[line - 1] );
                line--;
                column = 0;
            }
        } else if( action == "TEST_RULE" && !current_tab.empty() ) {
            test_pattern( tab, line );
        } else if( action == "SWITCH_SAFEMODE_OPTION" ) {
            get_options().get_option( "SAFEMODE" ).setNext();
            get_options().save();
        }
    }

    if( !changes_made ) {
        return;
    }

    if( query_yn( _( "Save changes?" ) ) ) {
        if( is_safemode_in ) {
            save_global();
            if( !g->u.name.empty() ) {
                save_character();
            }
        } else {
            create_rules();
        }
    } else {
        global_rules = global_rules_old;
        character_rules = character_rules_old;
    }
}
Esempio n. 8
0
// Update =============================================================================
CStatus gStretchOp2Multi_Update( CRef& in_ctxt )
{

	OperatorContext ctxt( in_ctxt );

		// User Datas ------------------------------------
		CValue::siPtrType pUserData = ctxt.GetUserData();
		OpUserData* pOpState = (OpUserData*)pUserData;

		if ( pOpState == NULL || pOpState->index >= 2)
		{
			// First time called
			pOpState = new OpUserData();
			ctxt.PutUserData( (CValue::siPtrType)pOpState );

			// Inputs ---------------------------------------
			KinematicState kRoot(ctxt.GetInputValue(0));
			KinematicState kCtrl(ctxt.GetInputValue(1));
			CTransformation tRoot(kRoot.GetTransform());
			CTransformation tCtrl(kCtrl.GetTransform());
			CVector3 vRoot = tRoot.GetTranslation();
			CVector3 vCtrl = tCtrl.GetTranslation();
			CMatrix4 mRoot = tRoot.GetMatrix4();
			CMatrix4 mRootNeg;
			mRootNeg.Invert(mRoot);

			double dRestLength = ctxt.GetParameterValue(L"restlength");
			double dScale      = ctxt.GetParameterValue(L"scale");
			double dSoftness   = ctxt.GetParameterValue(L"soft");
			double dMaxStretch = ctxt.GetParameterValue(L"maxstretch");

			// Distance with MaxStretch ---------------------
			dRestLength = dRestLength * dScale - .00001;
			CVector3 vDistance;
			vDistance.MulByMatrix4(vCtrl, mRootNeg);
			double dDistance = vDistance.GetLength();
			double dDistance2 = dDistance;
			if (dDistance > (dRestLength * dMaxStretch))
			{
				vDistance.NormalizeInPlace();
				vDistance.ScaleInPlace(dRestLength * dMaxStretch);
				dDistance = dRestLength * dMaxStretch;
			}

			Application app;
			app.LogMessage(L"dist : "+CString(dDistance));
			app.LogMessage(L"dist2 : "+CString(dDistance2));

			// Adapt Softness value to chain length --------
			dSoftness = dSoftness * dRestLength *.1;

			// Stretch and softness ------------------------
			/// We use the real distance from root to controler to calculate the softness
			/// This way we have softness working even when there is no stretch
			double dStretch = dDistance/dRestLength;
			if (dStretch < 1)
				dStretch = 1;
			double da = dRestLength - dSoftness;
			if (dSoftness > 0 && dDistance2 > da)
			{
				double newlen = dSoftness*(1.0 - exp(-(dDistance2 -da)/dSoftness)) + da;
				dStretch = dDistance / newlen;
			}

			double dScaleX = dStretch * dScale;
			app.LogMessage(L"scalex : "+CString(dScaleX));

			// Effector Position ----------------------------
			CTransformation t;
			vDistance.MulByMatrix4(vDistance, mRoot);
			t.SetTranslation(vDistance);

			pOpState->index = 0;
			pOpState->t = t;
			pOpState->dLength0 = dScaleX;
		}

	// Outputs -------------------------------------
	CRef outputPortRef=ctxt.GetOutputPort();
	OutputPort OutPort(outputPortRef);

	// Effector Transform
	if (OutPort.GetIndex() == 2)
	{
		KinematicState kOut = ctxt.GetOutputTarget();
		kOut.PutTransform(pOpState->t);
	}
	// Bone 0 Length
	else if (OutPort.GetIndex() == 3)
	{
		OutPort.PutValue(pOpState->dLength0);
	}

	pOpState->index += 1;

	return CStatus::OK;
}
Esempio n. 9
0
// Update =================================================================================
CStatus gStretchOp2_Update( CRef& in_ctxt )
{
	OperatorContext ctxt( in_ctxt );

	// User Datas ------------------------------------
	CValue::siPtrType pUserData = ctxt.GetUserData();
	OpUserData* pOpState = (OpUserData*)pUserData;

	if ( pOpState == NULL || pOpState->index >= 4)
	{
		// First time called
		pOpState = new OpUserData();
		ctxt.PutUserData( (CValue::siPtrType)pOpState );

		// Inputs ---------------------------------------
		KinematicState kRoot(ctxt.GetInputValue(0));
		KinematicState kCtrl(ctxt.GetInputValue(1));
		CTransformation tRoot(kRoot.GetTransform());
		CTransformation tCtrl(kCtrl.GetTransform());
		CVector3 vRoot = tRoot.GetTranslation();
		CVector3 vCtrl = tCtrl.GetTranslation();
		CMatrix4 mRoot = tRoot.GetMatrix4();
		CMatrix4 mRootNeg;
		mRootNeg.Invert(mRoot);

		double dRest0      = ctxt.GetParameterValue(L"rest0");
		double dRest1      = ctxt.GetParameterValue(L"rest1");
		double dPrefRot    = ctxt.GetParameterValue(L"prefrot");
		double dScale0     = ctxt.GetParameterValue(L"scale0");
		double dScale1     = ctxt.GetParameterValue(L"scale1");
		double dSoftness   = ctxt.GetParameterValue(L"soft");
		double dMaxStretch = ctxt.GetParameterValue(L"maxstretch");
		double dSlide      = ctxt.GetParameterValue(L"slide");
		double dReverse    = ctxt.GetParameterValue(L"reverse");

		// Distance with MaxStretch ---------------------
		double dRestLength = dRest0 * dScale0 + dRest1 * dScale1;
		CVector3 vDistance;
		vDistance.MulByMatrix4(vCtrl, mRootNeg);
		double dDistance = vDistance.GetLength();
		double dDistance2 = dDistance;
		if (dDistance > (dRestLength * dMaxStretch))
		{
			vDistance.NormalizeInPlace();
			vDistance.ScaleInPlace(dRestLength * dMaxStretch);
			dDistance = dRestLength * dMaxStretch;
		}

		// Adapt Softness value to chain length --------
		dSoftness *= dRestLength*.1;

		// Stretch and softness ------------------------
		/// We use the real distance from root to controler to calculate the softness
		/// This way we have softness working even when there is no stretch
		double dStretch = dDistance/dRestLength;
		if (dStretch < 1)
			dStretch = 1;
		double da = dRestLength - dSoftness;
		if (dSoftness > 0 && dDistance2 > da)
		{
			double newlen = dSoftness*(1.0 - exp(-(dDistance2 -da)/dSoftness)) + da;
			dStretch = dDistance / newlen;
		}

		double dLength0 = dRest0 * dStretch * dScale0;
		double dLength1 = dRest1 * dStretch * dScale1;

		// Reverse -------------------------------------
		double d = dDistance/(dLength0 + dLength1);

		double dScale;
		if (dReverse < 0.5)
			dScale = 1-(dReverse*2 * (1-d));
		else
			dScale = 1-((1-dReverse)*2 * (1-d));

		dLength0 *= dScale;
		dLength1 *= dScale;

		dPrefRot = -(dReverse-0.5) * 2 * dPrefRot;

		// Slide ---------------------------------------
		double dAdd;
		if (dSlide < .5)
			dAdd = (dLength0 * (dSlide*2)) - (dLength0);
		else
			dAdd = (dLength1 * (dSlide*2)) - (dLength1);

		dLength0 += dAdd;
		dLength1 -= dAdd;

		// Effector Position ----------------------------
		CTransformation t;
		vDistance.MulByMatrix4(vDistance, mRoot);
		t.SetTranslation(vDistance);

		pOpState->index = 0;
		pOpState->t = t;
		pOpState->dLength0 = dLength0;
		pOpState->dLength1 = dLength1;
		pOpState->dPrefRot = dPrefRot;
	}

	// Outputs -------------------------------------
	CRef outputPortRef=ctxt.GetOutputPort();
	OutputPort OutPort(outputPortRef);

	// Effector Transform
	if (OutPort.GetIndex() == 2)
	{
		KinematicState kOut = ctxt.GetOutputTarget();
		kOut.PutTransform(pOpState->t);
	}
	// Bone 0 Length
	else if (OutPort.GetIndex() == 3)
	{
		OutPort.PutValue(pOpState->dLength0);
	}
	// Bone 1 Length
	else if (OutPort.GetIndex() == 4)
	{
		OutPort.PutValue(pOpState->dLength1);
	}
	// Bone 1 PrefRot
	else if (OutPort.GetIndex() == 5)
	{
		OutPort.PutValue(pOpState->dPrefRot);
	}

	pOpState->index += 1;

	return CStatus::OK;
}
Esempio n. 10
0
// Pick up items at (pos).
void Pickup::pick_up( const tripoint &p, int min )
{
    int cargo_part = -1;

    const optional_vpart_position vp = g->m.veh_at( p );
    vehicle *const veh = veh_pointer_or_null( vp );
    bool from_vehicle = false;

    if( min != -1 ) {
        veh_interact_results get_items_from = ITEMS_FROM_GROUND;
        if( veh != nullptr ) {
            get_items_from = veh->interact_with( p, vp->part_index() );
        }
        switch( get_items_from ) {
            case DONE:
                return;
            case ITEMS_FROM_CARGO: {
                const cata::optional<vpart_reference> carg = vp.part_with_feature( "CARGO", false );
                cargo_part = carg ? carg->part_index() : -1;
                from_vehicle = cargo_part >= 0;
                break;
            }
            case ITEMS_FROM_GROUND:
                // Nothing to change, default is to pick from ground anyway.
                if( g->m.has_flag( "SEALED", p ) ) {
                    return;
                }
                break;
        }
    }

    if( !from_vehicle ) {
        bool isEmpty = ( g->m.i_at( p ).empty() );

        // Hide the pickup window if this is a toilet and there's nothing here
        // but water.
        if( ( !isEmpty ) && g->m.furn( p ) == f_toilet ) {
            isEmpty = true;
            for( const item &maybe_water : g->m.i_at( p ) ) {
                if( maybe_water.typeId() != "water" ) {
                    isEmpty = false;
                    break;
                }
            }
        }

        if( isEmpty && ( min != -1 || !get_option<bool>( "AUTO_PICKUP_ADJACENT" ) ) ) {
            return;
        }
    }

    // which items are we grabbing?
    std::vector<item> here;
    if( from_vehicle ) {
        auto vehitems = veh->get_items( cargo_part );
        here.resize( vehitems.size() );
        std::copy( vehitems.begin(), vehitems.end(), here.begin() );
    } else {
        auto mapitems = g->m.i_at( p );
        here.resize( mapitems.size() );
        std::copy( mapitems.begin(), mapitems.end(), here.begin() );
    }

    if( min == -1 ) {
        // Recursively pick up adjacent items if that option is on.
        if( get_option<bool>( "AUTO_PICKUP_ADJACENT" ) && g->u.pos() == p ) {
            //Autopickup adjacent
            direction adjacentDir[8] = {NORTH, NORTHEAST, EAST, SOUTHEAST, SOUTH, SOUTHWEST, WEST, NORTHWEST};
            for( auto &elem : adjacentDir ) {

                tripoint apos = tripoint( direction_XY( elem ), 0 );
                apos += p;

                pick_up( apos, min );
            }
        }

        // Bail out if this square cannot be auto-picked-up
        if( g->check_zone( zone_type_id( "NO_AUTO_PICKUP" ), p ) ) {
            return;
        } else if( g->m.has_flag( "SEALED", p ) ) {
            return;
        }
    }

    // Not many items, just grab them
    if( static_cast<int>( here.size() ) <= min && min != -1 ) {
        g->u.assign_activity( activity_id( "ACT_PICKUP" ) );
        g->u.activity.placement = p - g->u.pos();
        g->u.activity.values.push_back( from_vehicle );
        // Only one item means index is 0.
        g->u.activity.values.push_back( 0 );
        // auto-pickup means pick up all.
        g->u.activity.values.push_back( 0 );
        return;
    }

    std::vector<std::list<item_idx>> stacked_here;
    for( size_t i = 0; i < here.size(); i++ ) {
        item &it = here[i];
        bool found_stack = false;
        for( auto &stack : stacked_here ) {
            if( stack.begin()->_item.stacks_with( it ) ) {
                item_idx el = { it, i };
                stack.push_back( el );
                found_stack = true;
                break;
            }
        }
        if( !found_stack ) {
            std::list<item_idx> newstack;
            newstack.push_back( { it, i } );
            stacked_here.push_back( newstack );
        }
    }
    std::reverse( stacked_here.begin(), stacked_here.end() );

    if( min != -1 ) { // don't bother if we're just autopickuping
        g->temp_exit_fullscreen();
    }
    // Otherwise, we have Autopickup, 2 or more items and should list them, etc.
    int maxmaxitems = TERMY;

    int itemsH = std::min( 25, TERMY / 2 );
    int pickupBorderRows = 3;

    // The pickup list may consume the entire terminal, minus space needed for its
    // header/footer and the item info window.
    int minleftover = itemsH + pickupBorderRows;
    if( maxmaxitems > TERMY - minleftover ) {
        maxmaxitems = TERMY - minleftover;
    }

    const int minmaxitems = 9;

    std::vector<pickup_count> getitem( stacked_here.size() );

    int maxitems = stacked_here.size();
    maxitems = ( maxitems < minmaxitems ? minmaxitems : ( maxitems > maxmaxitems ? maxmaxitems :
                 maxitems ) );

    int itemcount = 0;

    if( min == -1 ) { //Auto Pickup, select matching items
        if( !select_autopickup_items( stacked_here, getitem ) ) {
            // If we didn't find anything, bail out now.
            return;
        }
    } else {
        int pickupH = maxitems + pickupBorderRows;
        int pickupW = 44;

        int itemsW = pickupW;

        catacurses::window w_pickup = catacurses::newwin( pickupH, pickupW, 0, 0 );
        catacurses::window w_item_info = catacurses::newwin( TERMY - pickupH,
                                         pickupW,  pickupH,  0 );

        std::string action;
        long raw_input_char = ' ';
        input_context ctxt( "PICKUP" );
        ctxt.register_action( "UP" );
        ctxt.register_action( "DOWN" );
        ctxt.register_action( "RIGHT" );
        ctxt.register_action( "LEFT" );
        ctxt.register_action( "NEXT_TAB", _( "Next page" ) );
        ctxt.register_action( "PREV_TAB", _( "Previous page" ) );
        ctxt.register_action( "SCROLL_UP" );
        ctxt.register_action( "SCROLL_DOWN" );
        ctxt.register_action( "CONFIRM" );
        ctxt.register_action( "SELECT_ALL" );
        ctxt.register_action( "QUIT", _( "Cancel" ) );
        ctxt.register_action( "ANY_INPUT" );
        ctxt.register_action( "HELP_KEYBINDINGS" );
        ctxt.register_action( "FILTER" );
#if defined(__ANDROID__)
        ctxt.allow_text_entry = true; // allow user to specify pickup amount
#endif

        int start = 0;
        int cur_it = 0;
        bool update = true;
        mvwprintw( w_pickup, 0, 0, _( "PICK" ) );
        int selected = 0;
        int iScrollPos = 0;

        std::string filter;
        std::string new_filter;
        std::vector<int> matches;//Indexes of items that match the filter
        bool filter_changed = true;
        if( g->was_fullscreen ) {
            g->draw_ter();
        }
        // Now print the two lists; those on the ground and about to be added to inv
        // Continue until we hit return or space
        do {
            const std::string pickup_chars =
                ctxt.get_available_single_char_hotkeys( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:;" );
            int idx = -1;
            for( int i = 1; i < pickupH; i++ ) {
                mvwprintw( w_pickup, i, 0,
                           "                                                " );
            }
            if( action == "ANY_INPUT" &&
                raw_input_char >= '0' && raw_input_char <= '9' ) {
                int raw_input_char_value = static_cast<char>( raw_input_char ) - '0';
                itemcount *= 10;
                itemcount += raw_input_char_value;
                if( itemcount < 0 ) {
                    itemcount = 0;
                }
            } else if( action == "SCROLL_UP" ) {
                iScrollPos--;
            } else if( action == "SCROLL_DOWN" ) {
                iScrollPos++;
            } else if( action == "PREV_TAB" ) {
                if( start > 0 ) {
                    start -= maxitems;
                } else {
                    start = static_cast<int>( ( matches.size() - 1 ) / maxitems ) * maxitems;
                }
                selected = start;
                mvwprintw( w_pickup, maxitems + 2, 0, "         " );
            } else if( action == "NEXT_TAB" ) {
                if( start + maxitems < static_cast<int>( matches.size() ) ) {
                    start += maxitems;
                } else {
                    start = 0;
                }
                iScrollPos = 0;
                selected = start;
                mvwprintw( w_pickup, maxitems + 2, pickupH, "            " );
            } else if( action == "UP" ) {
                selected--;
                iScrollPos = 0;
                if( selected < 0 ) {
                    selected = matches.size() - 1;
                    start = static_cast<int>( matches.size() / maxitems ) * maxitems;
                    if( start >= static_cast<int>( matches.size() ) ) {
                        start -= maxitems;
                    }
                } else if( selected < start ) {
                    start -= maxitems;
                }
            } else if( action == "DOWN" ) {
                selected++;
                iScrollPos = 0;
                if( selected >= static_cast<int>( matches.size() ) ) {
                    selected = 0;
                    start = 0;
                } else if( selected >= start + maxitems ) {
                    start += maxitems;
                }
            } else if( selected >= 0 && selected < static_cast<int>( matches.size() ) &&
                       ( ( action == "RIGHT" && !getitem[matches[selected]].pick ) ||
                         ( action == "LEFT" && getitem[matches[selected]].pick ) ) ) {
                idx = selected;
            } else if( action == "FILTER" ) {
                new_filter = filter;
                string_input_popup popup;
                popup
                .title( _( "Set filter" ) )
                .width( 30 )
                .edit( new_filter );
                if( !popup.canceled() ) {
                    filter_changed = true;
                } else {
                    wrefresh( g->w_terrain );
                    g->draw_panels();
                }
            } else if( action == "ANY_INPUT" && raw_input_char == '`' ) {
                std::string ext = string_input_popup()
                                  .title( _( "Enter 2 letters (case sensitive):" ) )
                                  .width( 3 )
                                  .max_length( 2 )
                                  .query_string();
                if( ext.size() == 2 ) {
                    int p1 = pickup_chars.find( ext.at( 0 ) );
                    int p2 = pickup_chars.find( ext.at( 1 ) );
                    if( p1 != -1 && p2 != -1 ) {
                        idx = pickup_chars.size() + ( p1 * pickup_chars.size() ) + p2;
                    }
                }
            } else if( action == "ANY_INPUT" ) {
                idx = ( raw_input_char <= 127 ) ? pickup_chars.find( raw_input_char ) : -1;
                iScrollPos = 0;
            }

            if( idx >= 0 && idx < static_cast<int>( matches.size() ) ) {
                size_t true_idx = matches[idx];
                if( itemcount != 0 || getitem[true_idx].count == 0 ) {
                    item &temp = stacked_here[true_idx].begin()->_item;
                    int amount_available = temp.count_by_charges() ? temp.charges : stacked_here[true_idx].size();
                    if( itemcount >= amount_available ) {
                        itemcount = 0;
                    }
                    getitem[true_idx].count = itemcount;
                    itemcount = 0;
                }

                // Note: this might not change the value of getitem[idx] at all!
                getitem[true_idx].pick = ( action == "RIGHT" ? true :
                                           ( action == "LEFT" ? false :
                                             !getitem[true_idx].pick ) );
                if( action != "RIGHT" && action != "LEFT" ) {
                    selected = idx;
                    start = static_cast<int>( idx / maxitems ) * maxitems;
                }

                if( !getitem[true_idx].pick ) {
                    getitem[true_idx].count = 0;
                }
                update = true;
            }
            if( filter_changed ) {
                matches.clear();
                while( matches.empty() ) {
                    auto filter_func = item_filter_from_string( new_filter );
                    for( size_t index = 0; index < stacked_here.size(); index++ ) {
                        if( filter_func( stacked_here[index].begin()->_item ) ) {
                            matches.push_back( index );
                        }
                    }
                    if( matches.empty() ) {
                        popup( _( "Your filter returned no results" ) );
                        wrefresh( g->w_terrain );
                        g->draw_panels();
                        // The filter must have results, or simply be emptied or canceled,
                        // as this screen can't be reached without there being
                        // items available
                        string_input_popup popup;
                        popup
                        .title( _( "Set filter" ) )
                        .width( 30 )
                        .edit( new_filter );
                        if( popup.canceled() ) {
                            new_filter = filter;
                            filter_changed = false;
                        }
                    }
                }
                if( filter_changed ) {
                    filter = new_filter;
                    filter_changed = false;
                    selected = 0;
                    start = 0;
                    iScrollPos = 0;
                }
                wrefresh( g->w_terrain );
                g->draw_panels();
            }
            item &selected_item = stacked_here[matches[selected]].begin()->_item;

            werase( w_item_info );
            if( selected >= 0 && selected <= static_cast<int>( stacked_here.size() ) - 1 ) {
                std::vector<iteminfo> vThisItem;
                std::vector<iteminfo> vDummy;
                selected_item.info( true, vThisItem );

                draw_item_info( w_item_info, "", "", vThisItem, vDummy, iScrollPos, true, true );
            }
            draw_custom_border( w_item_info, 0 );
            mvwprintw( w_item_info, 0, 2, "< " );
            trim_and_print( w_item_info, 0, 4, itemsW - 8, c_white, "%s >",
                            selected_item.display_name() );
            wrefresh( w_item_info );

            if( action == "SELECT_ALL" ) {
                int count = 0;
                for( auto i : matches ) {
                    if( getitem[i].pick ) {
                        count++;
                    }
                    getitem[i].pick = true;
                }
                if( count == static_cast<int>( stacked_here.size() ) ) {
                    for( size_t i = 0; i < stacked_here.size(); i++ ) {
                        getitem[i].pick = false;
                    }
                }
                update = true;
            }
            for( cur_it = start; cur_it < start + maxitems; cur_it++ ) {
                mvwprintw( w_pickup, 1 + ( cur_it % maxitems ), 0,
                           "                                        " );
                if( cur_it < static_cast<int>( matches.size() ) ) {
                    int true_it = matches[cur_it];
                    item &this_item = stacked_here[ true_it ].begin()->_item;
                    nc_color icolor = this_item.color_in_inventory();
                    if( cur_it == selected ) {
                        icolor = hilite( c_white );
                    }

                    if( cur_it < static_cast<int>( pickup_chars.size() ) ) {
                        mvwputch( w_pickup, 1 + ( cur_it % maxitems ), 0, icolor,
                                  static_cast<char>( pickup_chars[cur_it] ) );
                    } else if( cur_it < static_cast<int>( pickup_chars.size() ) + static_cast<int>
                               ( pickup_chars.size() ) *
                               static_cast<int>( pickup_chars.size() ) ) {
                        int p = cur_it - pickup_chars.size();
                        int p1 = p / pickup_chars.size();
                        int p2 = p % pickup_chars.size();
                        mvwprintz( w_pickup, 1 + ( cur_it % maxitems ), 0, icolor, "`%c%c",
                                   static_cast<char>( pickup_chars[p1] ), static_cast<char>( pickup_chars[p2] ) );
                    } else {
                        mvwputch( w_pickup, 1 + ( cur_it % maxitems ), 0, icolor, ' ' );
                    }
                    if( getitem[true_it].pick ) {
                        if( getitem[true_it].count == 0 ) {
                            wprintz( w_pickup, c_light_blue, " + " );
                        } else {
                            wprintz( w_pickup, c_light_blue, " # " );
                        }
                    } else {
                        wprintw( w_pickup, " - " );
                    }
                    std::string item_name;
                    if( stacked_here[true_it].begin()->_item.ammo_type() == "money" ) {
                        //Count charges
                        // TODO: transition to the item_location system used for the inventory
                        unsigned long charges_total = 0;
                        for( const auto &item : stacked_here[true_it] ) {
                            charges_total += item._item.charges;
                        }
                        //Picking up none or all the cards in a stack
                        if( !getitem[true_it].pick || getitem[true_it].count == 0 ) {
                            item_name = stacked_here[true_it].begin()->_item.display_money( stacked_here[true_it].size(),
                                        charges_total );
                        } else {
                            unsigned long charges = 0;
                            int c = getitem[true_it].count;
                            for( auto it = stacked_here[true_it].begin(); it != stacked_here[true_it].end() &&
                                 c > 0; ++it, --c ) {
                                charges += it->_item.charges;
                            }
                            item_name = string_format( _( "%s of %s" ),
                                                       stacked_here[true_it].begin()->_item.display_money( getitem[true_it].count, charges ),
                                                       format_money( charges_total ) );
                        }
                    } else {
                        item_name = this_item.display_name( stacked_here[true_it].size() );
                    }
                    if( stacked_here[true_it].size() > 1 ) {
                        item_name = string_format( "%d %s", stacked_here[true_it].size(), item_name );
                    }
                    if( get_option<bool>( "ITEM_SYMBOLS" ) ) {
                        item_name = string_format( "%s %s", this_item.symbol(), item_name );
                    }
                    trim_and_print( w_pickup, 1 + ( cur_it % maxitems ), 6, pickupW - 4, icolor,
                                    item_name );
                }
            }

            mvwprintw( w_pickup, maxitems + 1, 0, _( "[%s] Unmark" ),
                       ctxt.get_desc( "LEFT", 1 ) );

            center_print( w_pickup, maxitems + 1, c_light_gray, string_format( _( "[%s] Help" ),
                          ctxt.get_desc( "HELP_KEYBINDINGS", 1 ) ) );

            right_print( w_pickup, maxitems + 1, 0, c_light_gray, string_format( _( "[%s] Mark" ),
                         ctxt.get_desc( "RIGHT", 1 ) ) );

            mvwprintw( w_pickup, maxitems + 2, 0, _( "[%s] Prev" ),
                       ctxt.get_desc( "PREV_TAB", 1 ) );

            center_print( w_pickup, maxitems + 2, c_light_gray, string_format( _( "[%s] All" ),
                          ctxt.get_desc( "SELECT_ALL", 1 ) ) );

            right_print( w_pickup, maxitems + 2, 0, c_light_gray, string_format( _( "[%s] Next" ),
                         ctxt.get_desc( "NEXT_TAB", 1 ) ) );

            if( update ) { // Update weight & volume information
                update = false;
                for( int i = 9; i < pickupW; ++i ) {
                    mvwaddch( w_pickup, 0, i, ' ' );
                }
                units::mass weight_picked_up = 0_gram;
                units::volume volume_picked_up = 0_ml;
                for( size_t i = 0; i < getitem.size(); i++ ) {
                    if( getitem[i].pick ) {
                        item temp = stacked_here[i].begin()->_item;
                        if( temp.count_by_charges() && getitem[i].count < temp.charges && getitem[i].count != 0 ) {
                            temp.charges = getitem[i].count;
                        }
                        int num_picked = std::min( stacked_here[i].size(),
                                                   getitem[i].count == 0 ? stacked_here[i].size() : getitem[i].count );
                        weight_picked_up += temp.weight() * num_picked;
                        volume_picked_up += temp.volume() * num_picked;
                    }
                }

                auto weight_predict = g->u.weight_carried() + weight_picked_up;
                auto volume_predict = g->u.volume_carried() + volume_picked_up;

                mvwprintz( w_pickup, 0, 5, weight_predict > g->u.weight_capacity() ? c_red : c_white,
                           _( "Wgt %.1f" ), round_up( convert_weight( weight_predict ), 1 ) );

                wprintz( w_pickup, c_white, "/%.1f", round_up( convert_weight( g->u.weight_capacity() ), 1 ) );

                std::string fmted_volume_predict = format_volume( volume_predict );
                mvwprintz( w_pickup, 0, 18, volume_predict > g->u.volume_capacity() ? c_red : c_white,
                           _( "Vol %s" ), fmted_volume_predict );

                std::string fmted_volume_capacity = format_volume( g->u.volume_capacity() );
                wprintz( w_pickup, c_white, "/%s", fmted_volume_capacity );
            }

            wrefresh( w_pickup );

            action = ctxt.handle_input();
            raw_input_char = ctxt.get_raw_input().get_first_input();

        } while( action != "QUIT" && action != "CONFIRM" );

        bool item_selected = false;
        // Check if we have selected an item.
        for( auto selection : getitem ) {
            if( selection.pick ) {
                item_selected = true;
            }
        }
        if( action != "CONFIRM" || !item_selected ) {
            w_pickup = catacurses::window();
            w_item_info = catacurses::window();
            add_msg( _( "Never mind." ) );
            g->reenter_fullscreen();
            g->refresh_all();
            return;
        }
    }

    // At this point we've selected our items, register an activity to pick them up.
    g->u.assign_activity( activity_id( "ACT_PICKUP" ) );
    g->u.activity.placement = p - g->u.pos();
    g->u.activity.values.push_back( from_vehicle );
    if( min == -1 ) {
        // Auto pickup will need to auto resume since there can be several of them on the stack.
        g->u.activity.auto_resume = true;
    }
    std::vector<std::pair<int, int>> pick_values;
    for( size_t i = 0; i < stacked_here.size(); i++ ) {
        const auto &selection = getitem[i];
        if( !selection.pick ) {
            continue;
        }

        const auto &stack = stacked_here[i];
        // Note: items can be both charged and stacked
        // For robustness, let's assume they can be both in the same stack
        bool pick_all = selection.count == 0;
        size_t count = selection.count;
        for( const item_idx &it : stack ) {
            if( !pick_all && count == 0 ) {
                break;
            }

            if( it._item.count_by_charges() ) {
                size_t num_picked = std::min( static_cast<size_t>( it._item.charges ), count );
                pick_values.push_back( { static_cast<int>( it.idx ), static_cast<int>( num_picked ) } );
                count -= num_picked;
            } else {
                size_t num_picked = 1;
                pick_values.push_back( { static_cast<int>( it.idx ), 0 } );
                count -= num_picked;
            }
        }
    }
    // The pickup activity picks up items last-to-first from its values list, so make sure the
    // higher indices are at the end.
    std::sort( pick_values.begin(), pick_values.end() );
    for( auto &it : pick_values ) {
        g->u.activity.values.push_back( it.first );
        g->u.activity.values.push_back( it.second );
    }

    g->reenter_fullscreen();
}
Esempio n. 11
0
void  TestIt(long p, long r, long c, long _k, long w,
             long L, Vec<long>& mvec, 
             Vec<long>& gens, Vec<long>& ords, long useCache)
{
  if (lsize(mvec)<1) { // use default values
    mvec.SetLength(3); gens.SetLength(3); ords.SetLength(3);
    mvec[0] = 7;    mvec[1] = 3;    mvec[2] = 221;
    gens[0] = 3979; gens[1] = 3095; gens[2] = 3760;
    ords[0] = 6;    ords[1] = 2;    ords[2] = -8;
  }
  if (!noPrint)
    cout << "*** TestIt"
       << (dry? " (dry run):" : ":")
       << " p=" << p
       << ", r=" << r
       << ", c=" << c
       << ", k=" << _k
       << ", w=" << w
       << ", L=" << L
       << ", mvec=" << mvec << ", "
       << ", useCache = " << useCache
       << endl;

  setTimersOn();
  setDryRun(false); // Need to get a "real context" to test ThinEvalMap

  // mvec is supposed to include the prime-power factorization of m
  long nfactors = mvec.length();
  for (long i = 0; i < nfactors; i++)
    for (long j = i+1; j < nfactors; j++)
      assert(GCD(mvec[i], mvec[j]) == 1);

  // multiply all the prime powers to get m itself
  long m = computeProd(mvec);
  assert(GCD(p, m) == 1);

  // build a context with these generators and orders
  vector<long> gens1, ords1;
  convert(gens1, gens);
  convert(ords1, ords);
  FHEcontext context(m, p, r, gens1, ords1);
  buildModChain(context, L, c);

  if (!noPrint) {
    context.zMStar.printout(); // print structure of Zm* /(p) to cout
    cout << endl;
  }
  long d = context.zMStar.getOrdP();
  long phim = context.zMStar.getPhiM();
  long nslots = phim/d;

  setDryRun(dry); // Now we can set the dry-run flag if desired

  FHESecKey secretKey(context);
  const FHEPubKey& publicKey = secretKey;
  secretKey.GenSecKey(w); // A Hamming-weight-w secret key
  addSome1DMatrices(secretKey); // compute key-switching matrices that we need
  addFrbMatrices(secretKey); // compute key-switching matrices that we need

  // GG defines the plaintext space Z_p[X]/GG(X)
  ZZX GG;
  GG = context.alMod.getFactorsOverZZ()[0];
  EncryptedArray ea(context, GG);

  zz_p::init(context.alMod.getPPowR());

  Vec<zz_p> val0(INIT_SIZE, nslots);
  for (auto& x: val0)
    random(x);

  vector<ZZX> val1;
  val1.resize(nslots);
  for (long i = 0; i < nslots; i++) {
    val1[i] = conv<ZZX>(conv<ZZ>(rep(val0[i])));
  }

  Ctxt ctxt(publicKey);
  ea.encrypt(ctxt, publicKey, val1);

  resetAllTimers();
  FHE_NTIMER_START(ALL);

  // Compute homomorphically the transformation that takes the
  // coefficients packed in the slots and produces the polynomial
  // corresponding to cube

  if (!noPrint) CheckCtxt(ctxt, "init");

  if (!noPrint) cout << "build ThinEvalMap\n";
  ThinEvalMap map(ea, /*minimal=*/false, mvec, 
    /*invert=*/false, /*build_cache=*/false); 
  // compute the transformation to apply

  if (!noPrint) cout << "apply ThinEvalMap\n";
  if (useCache) map.upgrade();
  map.apply(ctxt); // apply the transformation to ctxt
  if (!noPrint) CheckCtxt(ctxt, "ThinEvalMap");
  if (!noPrint) cout << "check results\n";

  if (!noPrint) cout << "build ThinEvalMap\n";
  ThinEvalMap imap(ea, /*minimal=*/false, mvec, 
    /*invert=*/true, /*build_cache=*/false); 
  // compute the transformation to apply
  if (!noPrint) cout << "apply ThinEvalMap\n";
  if (useCache) imap.upgrade();
  imap.apply(ctxt); // apply the transformation to ctxt
  if (!noPrint) {
    CheckCtxt(ctxt, "ThinEvalMap");
    cout << "check results\n";
  }

#if 1

  /* create dirty version of ctxt */
  Vec<zz_pX> dirty_val0;
  dirty_val0.SetLength(nslots);
  for (long i = 0; i < nslots; i++) {
    random(dirty_val0[i], d);
    SetCoeff(dirty_val0[i], 0, val0[i]);
  }
  
  vector<ZZX> dirty_val1;
  dirty_val1.resize(nslots);
  for (long i = 0; i < nslots; i++) {
    dirty_val1[i] = conv<ZZX>(dirty_val0[i]);
  }

  Ctxt dirty_ctxt(publicKey);
  ea.encrypt(dirty_ctxt, publicKey, dirty_val1);


  EvalMap dirty_map(ea, /*minimal=*/false, mvec, 
    /*invert=*/false, /*build_cache=*/false); 

  dirty_map.apply(dirty_ctxt);
  imap.apply(dirty_ctxt);
#endif


  vector<ZZX> val2;
  ea.decrypt(ctxt, secretKey, val2);

  if (val1 == val2)
    cout << "ThinEvalMap: GOOD\n";
  else
    cout << "ThinEvalMap: BAD\n";

#if 1
  vector<ZZX> dirty_val2;
  ea.decrypt(dirty_ctxt, secretKey, dirty_val2);

  if (val1 == dirty_val2)
    cout << "ThinEvalMap: GOOD\n";
  else
    cout << "ThinEvalMap: BAD\n";
#endif


  FHE_NTIMER_STOP(ALL);

  if (!noPrint) {
    cout << "\n*********\n";
    printAllTimers();
    cout << endl;
  }
}
Esempio n. 12
0
void Messages::display_messages()
{
    WINDOW_PTR w_ptr {newwin(
        FULL_SCREEN_HEIGHT, FULL_SCREEN_WIDTH,
        (TERMY > FULL_SCREEN_HEIGHT) ? (TERMY - FULL_SCREEN_HEIGHT) / 2 : 0,
        (TERMX > FULL_SCREEN_WIDTH) ? (TERMX - FULL_SCREEN_WIDTH) / 2 : 0)};

    WINDOW *const w = w_ptr.get();

    input_context ctxt("MESSAGE_LOG");
    ctxt.register_action("UP", _("Scroll up"));
    ctxt.register_action("DOWN", _("Scroll down"));
    ctxt.register_action("QUIT");
    ctxt.register_action("HELP_KEYBINDINGS");

    int offset = 0;
    const int maxlength = FULL_SCREEN_WIDTH - 2 - 1;
    const int bottom = FULL_SCREEN_HEIGHT - 2;
    const int msg_count = size();

    for (;;) {
        werase(w);
        draw_border(w);
        mvwprintz(w, bottom + 1, 32, c_red, _("Press %s to return"), ctxt.get_desc("QUIT").c_str());
        draw_scrollbar(w, offset, bottom, msg_count, 1);

        int line = 1;
        int lasttime = -1;
        for( int i = offset; i < msg_count; ++i ) {
            if (line > bottom) {
                break;
            }

            const game_message &m     = player_messages.impl_->history(i);
            const nc_color col        = msgtype_to_color( m.type, false );
            const calendar timepassed = calendar::turn - m.timestamp_in_turns;

            if (timepassed.get_turn() > lasttime) {
                mvwprintz(w, line++, 3, c_ltblue, _("%s ago:"),
                    timepassed.textify_period().c_str());
                lasttime = timepassed.get_turn();
            }

            nc_color col_out = col;
            for( const std::string &folded : foldstring(m.get_with_count(), maxlength) ) {
                if (line > bottom) {
                    break;
                }
                print_colored_text( w, line++, 1, col_out, col, folded );
            }
        }

        if (offset + 1 < msg_count) {
            mvwprintz(w, bottom + 1, 5, c_magenta, "vvv");
        }
        if (offset > 0) {
            mvwprintz(w, bottom + 1, maxlength - 3, c_magenta, "^^^");
        }
        wrefresh(w);

        const std::string &action = ctxt.handle_input();
        if (action == "DOWN" && offset + 1 < msg_count) {
            offset++;
        } else if (action == "UP" && offset > 0) {
            offset--;
        } else if (action == "QUIT") {
            break;
        }
    }

    player_messages.impl_->curmes = calendar::turn.get_turn();
}
Esempio n. 13
0
// TODO: Shunt redundant drawing code elsewhere
std::vector<point> game::target(int &x, int &y, int lowx, int lowy, int hix,
                                int hiy, std::vector <monster> t, int &target,
                                item *relevent)
{
 std::vector<point> ret;
 int tarx, tary, junk, tart;
 int range=(hix-u.posx);
// First, decide on a target among the monsters, if there are any in range
 if (!t.empty()) {
// Check for previous target
  if (target == -1) {
// If no previous target, target the closest there is
   double closest = -1;
   double dist;
   for (int i = 0; i < t.size(); i++) {
    dist = rl_dist(t[i].posx(), t[i].posy(), u.posx, u.posy);
    if (closest < 0 || dist < closest) {
     closest = dist;
     target = i;
    }
   }
  }
  x = t[target].posx();
  y = t[target].posy();
 } else
  target = -1; // No monsters in range, don't use target, reset to -1

 bool sideStyle = use_narrow_sidebar();
 int height = 13;
 int width  = getmaxx(w_messages);
 int top    = sideStyle ? getbegy(w_messages) : (getbegy(w_minimap) + getmaxy(w_minimap));
 int left   = getbegx(w_messages);
 WINDOW* w_target = newwin(height, width, top, left);
 draw_border(w_target);
 mvwprintz(w_target, 0, 2, c_white, "< ");
 if (!relevent) { // currently targetting vehicle to refill with fuel
   wprintz(w_target, c_red, _("Select a vehicle"));
 } else {
   if (relevent == &u.weapon && relevent->is_gun()) {
     wprintz(w_target, c_red, _("Firing %s (%d)"), // - %s (%d)",
            u.weapon.tname().c_str(),// u.weapon.curammo->name.c_str(),
            u.weapon.charges);
   } else {
     wprintz(w_target, c_red, _("Throwing %s"), relevent->tname().c_str());
   }
 }
 wprintz(w_target, c_white, " >");
/* Annoying clutter @ 2 3 4. */
 int text_y = getmaxy(w_target) - 4;
 if (is_mouse_enabled()) {
     --text_y;
 }
 mvwprintz(w_target, text_y++, 1, c_white,
           _("Move cursor to target with directional keys"));
 if (relevent) {
  mvwprintz(w_target, text_y++, 1, c_white,
            _("'<' '>' Cycle targets; 'f' or '.' to fire"));
  mvwprintz(w_target, text_y++, 1, c_white,
            _("'0' target self; '*' toggle snap-to-target"));
 }

 if (is_mouse_enabled()) {
     mvwprintz(w_target, text_y++, 1, c_white,
         _("Mouse: LMB: Target, Wheel: Cycle, RMB: Fire"));
 }

 wrefresh(w_target);
 bool snap_to_target = OPTIONS["SNAP_TO_TARGET"];
 do {
  if (m.sees(u.posx, u.posy, x, y, -1, tart))
    ret = line_to(u.posx, u.posy, x, y, tart);
  else
    ret = line_to(u.posx, u.posy, x, y, 0);

  if(trigdist && trig_dist(u.posx,u.posy, x,y) > range) {
    bool cont=true;
    int cx=x;
    int cy=y;
    for (int i = 0; i < ret.size() && cont; i++) {
      if(trig_dist(u.posx,u.posy, ret[i].x, ret[i].y) > range) {
        ret.resize(i);
        cont=false;
      } else {
        cx=0+ret[i].x; cy=0+ret[i].y;
      }
    }
    x=cx;y=cy;
  }
  point center;
  if (snap_to_target)
   center = point(x, y);
  else
   center = point(u.posx + u.view_offset_x, u.posy + u.view_offset_y);
  // Clear the target window.
  for (int i = 1; i < getmaxy(w_target) - 5; i++) {
   for (int j = 1; j < getmaxx(w_target) - 2; j++)
    mvwputch(w_target, i, j, c_white, ' ');
  }
  /* Start drawing w_terrain things -- possibly move out to centralized draw_terrain_window function as they all should be roughly similar*/
  m.build_map_cache(); // part of the SDLTILES drawing code
  m.draw(w_terrain, center); // embedded in SDL drawing code
  // Draw the Monsters
  for (int i = 0; i < num_zombies(); i++) {
   if (u_see(&(zombie(i)))) {
    zombie(i).draw(w_terrain, center.x, center.y, false);
   }
  }
  // Draw the NPCs
  for (int i = 0; i < active_npc.size(); i++) {
   if (u_see(active_npc[i]->posx, active_npc[i]->posy))
    active_npc[i]->draw(w_terrain, center.x, center.y, false);
  }
  if (x != u.posx || y != u.posy) {

   // Draw the player
   int atx = POSX + u.posx - center.x, aty = POSY + u.posy - center.y;
   if (atx >= 0 && atx < TERRAIN_WINDOW_WIDTH && aty >= 0 && aty < TERRAIN_WINDOW_HEIGHT)
    mvwputch(w_terrain, aty, atx, u.color(), '@');

   // Only draw a highlighted trajectory if we can see the endpoint.
   // Provides feedback to the player, and avoids leaking information about tiles they can't see.
   draw_line(x, y, center, ret);
/*
   if (u_see( x, y)) {
    for (int i = 0; i < ret.size(); i++) {
      int mondex = mon_at(ret[i].x, ret[i].y),
          npcdex = npc_at(ret[i].x, ret[i].y);
      // NPCs and monsters get drawn with inverted colors
      if (mondex != -1 && u_see(&(zombie(mondex))))
       zombie(mondex).draw(w_terrain, center.x, center.y, true);
      else if (npcdex != -1)
       active_npc[npcdex]->draw(w_terrain, center.x, center.y, true);
      else
       m.drawsq(w_terrain, u, ret[i].x, ret[i].y, true,true,center.x, center.y);
    }
   }
//*/
            // Print to target window
            if (!relevent) {
                // currently targetting vehicle to refill with fuel
                vehicle *veh = m.veh_at(x, y);
                if (veh) {
                    mvwprintw(w_target, 1, 1, _("There is a %s"),
                              veh->name.c_str());
                }
            } else if (relevent == &u.weapon && relevent->is_gun()) {
                // firing a gun
                mvwprintw(w_target, 1, 1, _("Range: %d"),
                          rl_dist(u.posx, u.posy, x, y));
                // get the current weapon mode or mods
                std::string mode = "";
                if (u.weapon.mode == "MODE_BURST") {
                    mode = _("Burst");
                } else {
                    item* gunmod = u.weapon.active_gunmod();
                    if (gunmod != NULL) {
                        mode = gunmod->type->name;
                    }
                }
                if (mode != "") {
                    mvwprintw(w_target, 1, 14, _("Firing mode: %s"),
                              mode.c_str());
                }
            } else {
                // throwing something
                mvwprintw(w_target, 1, 1, _("Range: %d"),
                          rl_dist(u.posx, u.posy, x, y));
            }

   const int zid = mon_at(x, y);
   if (zid == -1) {
    if (snap_to_target)
     mvwputch(w_terrain, POSY, POSX, c_red, '*');
    else
     mvwputch(w_terrain, POSY + y - center.y, POSX + x - center.x, c_red, '*');
   } else {
    if (u_see(&(zombie(zid)))) {
     zombie(zid).print_info(w_target,2);
    }
   }
  }
  wrefresh(w_target);
  wrefresh(w_terrain);
  wrefresh(w_status);
  refresh();

  input_context ctxt("TARGET");
  // "ANY_INPUT" should be added before any real help strings
  // Or strings will be writen on window border.
  ctxt.register_action("ANY_INPUT");
  ctxt.register_directions();
  ctxt.register_action("COORDINATE");
  ctxt.register_action("SELECT");
  ctxt.register_action("FIRE");
  ctxt.register_action("NEXT_TARGET");
  ctxt.register_action("PREV_TARGET");
  ctxt.register_action("WAIT");
  ctxt.register_action("CENTER");
  ctxt.register_action("TOGGLE_SNAP_TO_TARGET");
  ctxt.register_action("HELP_KEYBINDINGS");
  ctxt.register_action("QUIT");

  const std::string& action = ctxt.handle_input();


  tarx = 0; tary = 0;
  // Our coordinates will either be determined by coordinate input(mouse),
  // by a direction key, or by the previous value.
  if (action == "SELECT" && ctxt.get_coordinates(g->w_terrain, tarx, tary)) {
      if (!OPTIONS["USE_TILES"] && snap_to_target) {
          // Snap to target doesn't currently work with tiles.
          tarx += x - u.posx;
          tary += y - u.posy;
      }
      tarx -= x;
      tary -= y;


  } else {
    ctxt.get_direction(tarx, tary, action);
    if(tarx == -2) {
        tarx = 0;
        tary = 0;
    }
  }

  /* More drawing to terrain */
  if (tarx != 0 || tary != 0) {
   int mondex = mon_at(x, y), npcdex = npc_at(x, y);
   if (mondex != -1 && u_see(&(zombie(mondex))))
    zombie(mondex).draw(w_terrain, center.x, center.y, false);
   else if (npcdex != -1)
    active_npc[npcdex]->draw(w_terrain, center.x, center.y, false);
   else if (m.sees(u.posx, u.posy, x, y, -1, junk))
    m.drawsq(w_terrain, u, x, y, false, true, center.x, center.y);
   else
    mvwputch(w_terrain, POSY, POSX, c_black, 'X');
   x += tarx;
   y += tary;
   if (x < lowx)
    x = lowx;
   else if (x > hix)
    x = hix;
   if (y < lowy)
    y = lowy;
   else if (y > hiy)
    y = hiy;
  } else if ((action == "PREV_TARGET") && (target != -1)) {
   target--;
   if (target == -1) target = t.size() - 1;
   x = t[target].posx();
   y = t[target].posy();
  } else if ((action == "NEXT_TARGET") && (target != -1)) {
   target++;
   if (target == t.size()) target = 0;
   x = t[target].posx();
   y = t[target].posy();
  } else if (action == "WAIT" || action == "FIRE") {
   for (int i = 0; i < t.size(); i++) {
    if (t[i].posx() == x && t[i].posy() == y)
     target = i;
   }
   if (u.posx == x && u.posy == y)
       ret.clear();
   break;
  } else if (action == "CENTER") {
   x = u.posx;
   y = u.posy;
   ret.clear();
  } else if (action == "TOGGLE_SNAP_TO_TARGET")
   snap_to_target = !snap_to_target;
  else if (action == "QUIT") { // return empty vector (cancel)
   ret.clear();
   break;
  }
 } while (true);

 return ret;
}
Esempio n. 14
0
void Messages::display_messages()
{
    catacurses::window w = catacurses::newwin(
                               FULL_SCREEN_HEIGHT, FULL_SCREEN_WIDTH,
                               ( TERMY > FULL_SCREEN_HEIGHT ) ? ( TERMY - FULL_SCREEN_HEIGHT ) / 2 : 0,
                               ( TERMX > FULL_SCREEN_WIDTH ) ? ( TERMX - FULL_SCREEN_WIDTH ) / 2 : 0 );

    input_context ctxt( "MESSAGE_LOG" );
    ctxt.register_action( "UP", _( "Scroll up" ) );
    ctxt.register_action( "DOWN", _( "Scroll down" ) );
    ctxt.register_action( "QUIT" );
    ctxt.register_action( "HELP_KEYBINDINGS" );

    /* Right-Aligning Time Epochs For Readability
     * ==========================================
     * Given display_messages(); right-aligns epochs, we must declare one quick variable first:
     * max_padlength refers to the length of the LONGEST possible unit of time returned by to_string_clipped() any language has to offer.
     * This variable is, for now, set to '10', which seems most reasonable.
     *
     * The reason right-aligned epochs don't use a "shortened version" (e.g. only showing the first letter) boils down to:
     * 1. The first letter of every time unit being unique is a property that might not carry across to other languages.
     * 2. Languages where displayed characters change depending on the characters preceding/following it will become unclear.
     * 3. Some polymorphic languages might not be able to appropriately convey meaning with one character (FRS is not a linguist- correct her on this if needed.)
     *
     * This right padlength is then incorporated into a so-called 'epoch_format' which, in turn, will be used to format the correct epoch.
     * If an external language introduces time units longer than 10 characters in size, consider altering these variables.
     * The game (likely) shan't segfault, though the text may appear a bit messed up if these variables aren't set properly.
     */
    const int max_padlength = 10;

    /* Dealing With Screen Extremities
     * ===============================
     * 'maxlength' corresponds to the most extreme length a log message may be before foldstring() wraps it around to two or more lines.
     * The numbers subtracted from FULL_SCREEN_WIDTH are - in order:
     * '-2' the characters reserved for the borders of the box, both on the left and right side.
     * '-1' the leftmost guide character that's drawn on screen.
     * '-4' the padded three-digit number each epoch starts with.
     * '-max_padlength' the characters of space that are allocated to time units (e.g. "years", "minutes", etc.)
     *
     * 'bottom' works much like 'maxlength', but instead it refers to the amount of lines that the message box may hold.
     */
    const int maxlength = FULL_SCREEN_WIDTH - 2 - 1 - 4 - max_padlength;
    const int bottom = FULL_SCREEN_HEIGHT - 2;
    const int msg_count = size();

    /* Dealing With Scroll Direction
     * =============================
     * Much like how the sidebar can have variable scroll direction, so will the message box.
     * To properly differentiate the two methods of displaying text, we will label them NEWEST-TOP, and OLDEST-TOP. This labeling should be self explanatory.
     *
     * Note that 'offset' tracks only our current position in the list; it shan't at all affect the manner in which the messages are drawn.
     * Messages are always drawn top-to-bottom. If NEWEST-TOP is used, then the top line (line=1) corresponds to the newest message. The one further down the second-newest, etc.
     * If the OLDEST-TOP method is used, then the top line (line=1) corresponds to the oldest message, and the bottom one to the newest.
     * The 'for (;;)' block below is nearly completely method-agnostic, save for the `player_messages.impl_->history(i)` call.
     *
     * In case of NEWEST-TOP, the 'i' variable easily enough corresponds to the newest message.
     * In case of OLDEST-TOP, the 'i' variable must be flipped- meaning the highest value of 'i' returns the result for the lowest value of 'i', etc.
     * To achieve this, the 'flip_message' variable is set to either the value of 'msg_count', or '0'. This variable is then subtracted from 'i' in each call to player_messages.impl_->history();
     *
     * 'offset' refers to the corresponding message that will be displayed at the very TOP of the message box window.
     *  NEWEST-TOP: 'offset' starts simply at '0' - the very top of the window.
     *  OLDEST-TOP: 'offset' is set to the maximum value it could possibly be. That is- 'msg_count-bottom'. This way, the screen starts with the scrollbar all the way down.
     * 'retrieve_history' refers to the line that should be displayed- this is either 'i' if it's NEWEST-TOP, or a flipped version of 'i' if it's OLDEST-TOP.
     */
    int offset = log_from_top ? 0 : ( msg_count - bottom );
    const int flip = log_from_top ? 0 : msg_count - 1;

    for( ;; ) {
        werase( w );
        draw_border( w );
        mvwprintz( w, bottom + 1, 32, c_red, _( "Press %s to return" ), ctxt.get_desc( "QUIT" ).c_str() );
        draw_scrollbar( w, offset, bottom, msg_count, 1, 0, c_white, true );

        int line = 1;
        int lasttime = -1;
        for( int i = offset; i < msg_count; ++i ) {
            const int retrieve_history = abs( i - flip );
            if( line > bottom ) {
                break;
                // This statement makes it so that no non-existent messages are printed (which usually results in a segfault)
            } else if( retrieve_history >= msg_count ) {
                continue;
            }

            const game_message &m     = player_messages.impl_->history( retrieve_history );
            const calendar timepassed = calendar::turn - m.timestamp_in_turns;
            std::string long_ago      = to_string_clipped( time_duration::from_turns( timepassed ) );
            nc_color col              = msgtype_to_color( m.type, false );

            // Here we separate the unit and amount from one another so that they can be properly padded when they're drawn on the screen.
            // Note that the very first character of 'unit' is often a space (except for languages where the time unit directly follows the number.)
            const auto amount_len = long_ago.find_first_not_of( "0123456789" );
            std::string amount = long_ago.substr( 0, amount_len );
            std::string unit = long_ago.substr( amount_len );
            if( timepassed.get_turn() != lasttime ) {
                right_print( w, line, 2, c_light_blue, string_format( _( "%-3s%-10s" ), amount.c_str(),
                             unit.c_str() ) );
                lasttime = timepassed.get_turn();
            }

            nc_color col_out = col;
            for( const std::string &folded : foldstring( m.get_with_count(), maxlength ) ) {
                if( line > bottom ) {
                    break;
                }
                print_colored_text( w, line, 2, col_out, col, folded );


                // So-called special "markers"- alternating '=' and '-'s at the edges of te message window so players can properly make sense of which message belongs to which time interval.
                // The '+offset%4' in the calculation makes it so that the markings scroll along with the messages.
                // On lines divisible by 4, draw a dark gray '-' at both horizontal extremes of the window.
                if( ( line + offset % 4 ) % 4 == 0 ) {
                    mvwprintz( w, line, 1, c_dark_gray, "-" );
                    mvwprintz( w, line, FULL_SCREEN_WIDTH - 2, c_dark_gray, "-" );
                    // On lines divisible by 2 (but not 4), draw a light gray '=' at the horizontal extremes of the window.
                } else if( ( line + offset % 4 ) % 2 == 0 ) {
                    mvwprintz( w, line, 1, c_light_gray, "=" );
                    mvwprintz( w, line, FULL_SCREEN_WIDTH - 2, c_light_gray, "=" );
                }

                // Only now are we done with this line:
                line++;
            }
        }

        if( offset < msg_count - bottom ) {
            mvwprintz( w, bottom + 1, 5, c_magenta, "vvv" );
        }
        if( offset > 0 ) {
            mvwprintz( w, bottom + 1, FULL_SCREEN_WIDTH - 8, c_magenta, "^^^" );
        }
        wrefresh( w );

        const std::string &action = ctxt.handle_input();
        if( action == "DOWN" && offset < msg_count - bottom ) {
            offset++;
        } else if( action == "UP" && offset > 0 ) {
            offset--;
        } else if( action == "QUIT" ) {
            break;
        }
    }

    player_messages.impl_->curmes = calendar::turn.get_turn();
}
Esempio n. 15
0
WORLDPTR worldfactory::pick_world( bool show_prompt )
{
    std::map<std::string, WORLDPTR> worlds = get_all_worlds();
    std::vector<std::string> world_names = all_worldnames;

    // Filter out special worlds (TUTORIAL | DEFENSE) from world_names.
    for (std::vector<std::string>::iterator it = world_names.begin(); it != world_names.end();) {
        if (*it == "TUTORIAL" || *it == "DEFENSE") {
            it = world_names.erase(it);
        } else {
            ++it;
        }
    }
    // If there is only one world to pick from, autoreturn it.
    if (world_names.size() == 1) {
        return worlds[world_names[0]];
    }
    // If there are no worlds to pick from, immediately try to make one.
    else if (world_names.empty()) {
        return make_new_world( show_prompt );
    }
    // If we're skipping prompts, just return the first one.
    else if( !show_prompt ) {
        return worlds[world_names[0]];
    }

    const int iTooltipHeight = 3;
    const int iContentHeight = FULL_SCREEN_HEIGHT - 3 - iTooltipHeight;
    const unsigned int num_pages = world_names.size() / iContentHeight + 1; // at least 1 page
    const int iOffsetX = (TERMX > FULL_SCREEN_WIDTH) ? (TERMX - FULL_SCREEN_WIDTH) / 2 : 0;
    const int iOffsetY = (TERMY > FULL_SCREEN_HEIGHT) ? (TERMY - FULL_SCREEN_HEIGHT) / 2 : 0;

    std::map<int, bool> mapLines;
    mapLines[3] = true;

    std::map<int, std::vector<std::string> > world_pages;
    unsigned int worldnum = 0;
    for (size_t i = 0; i < num_pages; ++i) {
        for (int j = 0; j < iContentHeight && worldnum < world_names.size(); ++j) {
            world_pages[i].push_back(world_names[worldnum++]);
        }
    }
    unsigned int sel = 0, selpage = 0;

    WINDOW *w_worlds_border = newwin(FULL_SCREEN_HEIGHT, FULL_SCREEN_WIDTH, iOffsetY, iOffsetX);
    WINDOW *w_worlds_tooltip = newwin(iTooltipHeight, FULL_SCREEN_WIDTH - 2, 1 + iOffsetY,
                                      1 + iOffsetX);
    WINDOW *w_worlds_header = newwin(1, FULL_SCREEN_WIDTH - 2, 1 + iTooltipHeight + iOffsetY,
                                     1 + iOffsetX);
    WINDOW *w_worlds        = newwin(iContentHeight, FULL_SCREEN_WIDTH - 2,
                                     iTooltipHeight + 2 + iOffsetY, 1 + iOffsetX);

    draw_border(w_worlds_border);
    mvwputch(w_worlds_border, 4, 0, BORDER_COLOR, LINE_XXXO); // |-
    mvwputch(w_worlds_border, 4, FULL_SCREEN_WIDTH - 1, BORDER_COLOR, LINE_XOXX); // -|

    for (std::map<int, bool>::iterator iter = mapLines.begin(); iter != mapLines.end(); ++iter) {
        mvwputch(w_worlds_border, FULL_SCREEN_HEIGHT - 1, iter->first + 1, BORDER_COLOR, LINE_XXOX); // _|_
    }

    center_print(w_worlds_border, 0, c_ltred, _(" WORLD SELECTION "));
    wrefresh(w_worlds_border);

    for (int i = 0; i < 78; i++) {
        if (mapLines[i]) {
            mvwputch(w_worlds_header, 0, i, BORDER_COLOR, LINE_OXXX);
        } else {
            mvwputch(w_worlds_header, 0, i, BORDER_COLOR, LINE_OXOX); // Draw header line
        }
    }

    wrefresh(w_worlds_header);

    input_context ctxt("PICK_WORLD_DIALOG");
    ctxt.register_updown();
    ctxt.register_action("HELP_KEYBINDINGS");
    ctxt.register_action("QUIT");
    ctxt.register_action("NEXT_TAB");
    ctxt.register_action("PREV_TAB");
    ctxt.register_action("CONFIRM");

    std::stringstream sTemp;

    while(true) {
        //Clear the lines
        for (int i = 0; i < iContentHeight; i++) {
            for (int j = 0; j < 79; j++) {
                if (mapLines[j]) {
                    mvwputch(w_worlds, i, j, BORDER_COLOR, LINE_XOXO);
                } else {
                    mvwputch(w_worlds, i, j, c_black, ' ');
                }

                if (i < iTooltipHeight) {
                    mvwputch(w_worlds_tooltip, i, j, c_black, ' ');
                }
            }
        }

        //Draw World Names
        for (size_t i = 0; i < world_pages[selpage].size(); ++i) {
            sTemp.str("");
            sTemp << i + 1;
            mvwprintz(w_worlds, i, 0, c_white, "%s", sTemp.str().c_str());
            mvwprintz(w_worlds, i, 4, c_white, "");


            if (i == sel) {
                wprintz(w_worlds, c_yellow, ">> ");
            } else {
                wprintz(w_worlds, c_yellow, " ");
            }

            wprintz(w_worlds, c_white, "%s (%i)", (world_pages[selpage])[i].c_str(),
                    world_generator->all_worlds[((world_pages[selpage])[i])]->world_saves.size());
        }

        //Draw Tabs
        mvwprintz(w_worlds_header, 0, 7, c_white, "");

        for (size_t i = 0; i < num_pages; ++i) {
            nc_color tabcolor = (selpage == i) ? hilite(c_white) : c_white;
            if (!world_pages[i].empty()) { //skip empty pages
                wprintz(w_worlds_header, c_white, "[");
                wprintz(w_worlds_header, tabcolor, _("Page %d"), i + 1);
                wprintz(w_worlds_header, c_white, "]");
                wputch(w_worlds_header, BORDER_COLOR, LINE_OXOX);
            }
        }

        wrefresh(w_worlds_header);

        fold_and_print(w_worlds_tooltip, 0, 0, 78, c_white, _("Pick a world to enter game"));
        wrefresh(w_worlds_tooltip);

        wrefresh(w_worlds);

        const std::string action = ctxt.handle_input();

        if (action == "QUIT") {
            break;
        } else if (!world_pages[selpage].empty() && action == "DOWN") {
                    sel++;
                    if (sel >= world_pages[selpage].size()) {
                        sel = 0;
                    }
        } else if (!world_pages[selpage].empty() && action == "UP") {
                    if (sel == 0) {
                        sel = world_pages[selpage].size() - 1;
                    } else {
                        sel--;
                    }
        } else if (action == "NEXT_TAB") {
                    sel = 0;
                    do { //skip empty pages
                        selpage++;
                        if (selpage >= world_pages.size()) {
                            selpage = 0;
                        }
                    } while(world_pages[selpage].empty());
        } else if (action == "PREV_TAB") {
                    sel = 0;
                    do { //skip empty pages
                        if (selpage != 0) {
                            selpage--;
                        } else {
                            selpage = world_pages.size() - 1;
                        }
                    } while(world_pages[selpage].empty());
        } else if (action == "CONFIRM") {
                    // we are wanting to get out of this by confirmation, so ask if we want to load the level [y/n prompt] and if yes exit
                    if (query_yn(_("Do you want to start the game in world [%s]?"),
                                    world_pages[selpage][sel].c_str())) {
                        werase(w_worlds);
                        werase(w_worlds_border);
                        werase(w_worlds_header);
                        werase(w_worlds_tooltip);
                        return all_worlds[world_pages[selpage][sel]];//sel + selpage * iContentHeight;
                    }
        }
    }

    werase(w_worlds);
    werase(w_worlds_border);
    werase(w_worlds_header);
    werase(w_worlds_tooltip);

    return NULL;
}
Esempio n. 16
0
// Testing the I/O of the important classes of the library
// (context, keys, ciphertexts).
int main(int argc, char *argv[])
{
  ArgMapping amap;

  long r=1;
  long p=2;
  long c = 2;
  long w = 64;
  long L = 5;
  amap.arg("p", p, "plaintext base");
  amap.arg("r", r,  "lifting");
  amap.arg("c", c, "number of columns in the key-switching matrices");
  amap.parse(argc, argv);

  long ptxtSpace = power_long(p,r);

  FHEcontext* contexts[N_TESTS];
  FHESecKey*  sKeys[N_TESTS];
  Ctxt*       ctxts[N_TESTS];
  EncryptedArray* eas[N_TESTS];
  vector<ZZX> ptxts[N_TESTS];

  // first loop: generate stuff and write it to cout

  // open file for writing
  {fstream keyFile("iotest.txt", fstream::out|fstream::trunc);
   assert(keyFile.is_open());
  for (long i=0; i<N_TESTS; i++) {
    long m = ms[i][1];

    cout << "Testing IO: m="<<m<<", p^r="<<p<<"^"<<r<<endl;

    if (i==N_TESTS-1) { // test bootstrapping data I/O
      Vec<long> mvec(INIT_SIZE,2);
      mvec[0] = ms[i][4];  mvec[1] = ms[i][5];
      vector<long> gens(2);
      gens[0] = ms[i][6];  gens[1] = ms[i][7];
      vector<long> ords(2);
      ords[0] = ms[i][8];  ords[1] = ms[i][9];

      contexts[i] = new FHEcontext(m, p, r, gens, ords);
      buildModChain(*contexts[i], L, c);  // Set the modulus chain
      contexts[i]->makeBootstrappable(mvec);
    }
    else {
      contexts[i] = new FHEcontext(m, p, r);
      buildModChain(*contexts[i], L, c);  // Set the modulus chain
    }

    // Output the FHEcontext to file
    writeContextBase(keyFile, *contexts[i]);
    keyFile << *contexts[i] << endl;

    sKeys[i] = new FHESecKey(*contexts[i]);
    const FHEPubKey& publicKey = *sKeys[i];
    sKeys[i]->GenSecKey(w,ptxtSpace); // A Hamming-weight-w secret key
    addSome1DMatrices(*sKeys[i]);// compute key-switching matrices that we need
    eas[i] = new EncryptedArray(*contexts[i]);

    long nslots = eas[i]->size();

    // Output the secret key to file, twice. Below we will have two copies
    // of most things.
    keyFile << *sKeys[i] << endl;;
    keyFile << *sKeys[i] << endl;;

    vector<ZZX> b;
    long p2r = eas[i]->getContext().alMod.getPPowR();
    ZZX poly = RandPoly(0,to_ZZ(p2r)); // choose a random constant polynomial
    eas[i]->decode(ptxts[i], poly);

    ctxts[i] = new Ctxt(publicKey);
    eas[i]->encrypt(*ctxts[i], publicKey, ptxts[i]);
    eas[i]->decrypt(*ctxts[i], *sKeys[i], b);
    assert(ptxts[i].size() == b.size());
    for (long j = 0; j < nslots; j++) assert (ptxts[i][j] == b[j]);

    // output the plaintext
    keyFile << "[ ";
    for (long j = 0; j < nslots; j++) keyFile << ptxts[i][j] << " ";
    keyFile << "]\n";

    eas[i]->encode(poly,ptxts[i]);
    keyFile << poly << endl;

    // Output the ciphertext to file
    keyFile << *ctxts[i] << endl;
    keyFile << *ctxts[i] << endl;
    cerr << "okay " << i << endl;
  }
  keyFile.close();}
  cerr << "so far, so good\n";

  // second loop: read from input and repeat the computation

  // open file for read
  {fstream keyFile("iotest.txt", fstream::in);
  for (long i=0; i<N_TESTS; i++) {

    // Read context from file
    unsigned long m1, p1, r1;
    vector<long> gens, ords;
    readContextBase(keyFile, m1, p1, r1, gens, ords);
    FHEcontext tmpContext(m1, p1, r1, gens, ords);
    keyFile >> tmpContext;
    assert (*contexts[i] == tmpContext);
    cerr << i << ": context matches input\n";

    // We define some things below wrt *contexts[i], not tmpContext.
    // This is because the various operator== methods check equality of
    // references, not equality of the referenced FHEcontext objects.
    FHEcontext& context = *contexts[i];
    FHESecKey secretKey(context);
    FHESecKey secretKey2(tmpContext);
    const FHEPubKey& publicKey = secretKey;
    const FHEPubKey& publicKey2 = secretKey2;

    keyFile >> secretKey;
    keyFile >> secretKey2;
    assert(secretKey == *sKeys[i]);
    cerr << "   secret key matches input\n";

    EncryptedArray ea(context);
    EncryptedArray ea2(tmpContext);

    long nslots = ea.size();

    // Read the plaintext from file
    vector<ZZX> a;
    a.resize(nslots);
    assert(nslots == (long)ptxts[i].size());
    seekPastChar(keyFile, '['); // defined in NumbTh.cpp
    for (long j = 0; j < nslots; j++) {
      keyFile >> a[j];
      assert(a[j] == ptxts[i][j]);
    }
    seekPastChar(keyFile, ']');
    cerr << "   ptxt matches input\n";

    // Read the encoded plaintext from file
    ZZX poly1, poly2;
    keyFile >> poly1;
    eas[i]->encode(poly2,a);
    assert(poly1 == poly2);
    cerr << "   eas[i].encode(a)==poly1 okay\n";

    ea.encode(poly2,a);
    assert(poly1 == poly2);
    cerr << "   ea.encode(a)==poly1 okay\n";

    ea2.encode(poly2,a);
    assert(poly1 == poly2);
    cerr << "   ea2.encode(a)==poly1 okay\n";

    eas[i]->decode(a,poly1);
    assert(nslots == (long)a.size());
    for (long j = 0; j < nslots; j++) assert(a[j] == ptxts[i][j]);
    cerr << "   eas[i].decode(poly1)==ptxts[i] okay\n";

    ea.decode(a,poly1);
    assert(nslots == (long)a.size());
    for (long j = 0; j < nslots; j++) assert(a[j] == ptxts[i][j]);
    cerr << "   ea.decode(poly1)==ptxts[i] okay\n";

    ea2.decode(a,poly1);
    assert(nslots == (long)a.size());
    for (long j = 0; j < nslots; j++) assert(a[j] == ptxts[i][j]);
    cerr << "   ea2.decode(poly1)==ptxts[i] okay\n";

    // Read ciperhtext from file
    Ctxt ctxt(publicKey);
    Ctxt ctxt2(publicKey2);
    keyFile >> ctxt;
    keyFile >> ctxt2;
    assert(ctxts[i]->equalsTo(ctxt,/*comparePkeys=*/false));
    cerr << "   ctxt matches input\n";

    sKeys[i]->Decrypt(poly2,*ctxts[i]);
    assert(poly1 == poly2);
    cerr << "   sKeys[i]->decrypt(*ctxts[i]) == poly1 okay\n";

    secretKey.Decrypt(poly2,*ctxts[i]);
    assert(poly1 == poly2);
    cerr << "   secretKey.decrypt(*ctxts[i]) == poly1 okay\n";

    secretKey.Decrypt(poly2,ctxt);
    assert(poly1 == poly2);
    cerr << "   secretKey.decrypt(ctxt) == poly1 okay\n";

    secretKey2.Decrypt(poly2,ctxt2);
    assert(poly1 == poly2);
    cerr << "   secretKey2.decrypt(ctxt2) == poly1 okay\n";

    eas[i]->decrypt(ctxt, *sKeys[i], a);
    assert(nslots == (long)a.size());
    for (long j = 0; j < nslots; j++) assert(a[j] == ptxts[i][j]);
    cerr << "   eas[i].decrypt(ctxt, *sKeys[i])==ptxts[i] okay\n";

    ea.decrypt(ctxt, secretKey, a);
    assert(nslots == (long)a.size());
    for (long j = 0; j < nslots; j++) assert(a[j] == ptxts[i][j]);
    cerr << "   ea.decrypt(ctxt, secretKey)==ptxts[i] okay\n";

    ea2.decrypt(ctxt2, secretKey2, a);
    assert(nslots == (long)a.size());
    for (long j = 0; j < nslots; j++) assert(a[j] == ptxts[i][j]);
    cerr << "   ea2.decrypt(ctxt2, secretKey2)==ptxts[i] okay\n";

    cerr << "test "<<i<<" okay\n\n";
  }}
  unlink("iotest.txt"); // clean up before exiting
}
Esempio n. 17
0
int worldfactory::show_worldgen_tab_options(WINDOW *win, WORLDPTR world)
{
    const int iTooltipHeight = 1;
    const int iContentHeight = FULL_SCREEN_HEIGHT - 3 - iTooltipHeight;

    const int iOffsetX = (TERMX > FULL_SCREEN_WIDTH) ? (TERMX - FULL_SCREEN_WIDTH) / 2 : 0;
    const int iOffsetY = (TERMY > FULL_SCREEN_HEIGHT) ? (TERMY - FULL_SCREEN_HEIGHT) / 2 : 0;

    WINDOW *w_options = newwin(iContentHeight, FULL_SCREEN_WIDTH - 2, iTooltipHeight + 2 + iOffsetY,
                               1 + iOffsetX);
    std::stringstream sTemp;

    std::map<int, bool> mapLines;
    mapLines[3] = true;
    mapLines[60] = true;
    // only populate once
    if (world->world_options.empty()) {
        for (std::map<std::string, cOpt>::iterator it = OPTIONS.begin(); it != OPTIONS.end(); ++it) {
            if (it->second.getPage() == "world_default") {
                world->world_options[it->first] = it->second;
            }
        }
    }

    std::vector<std::string> keys;
    for (std::map<std::string, cOpt>::iterator it = world->world_options.begin();
         it != world->world_options.end(); ++it) {
        keys.push_back(it->first);
    }

    for (std::map<int, bool>::iterator mLine = mapLines.begin(); mLine != mapLines.end(); ++mLine) {
        if (mLine->second) {
            mvwputch(win, 2, mLine->first + 1, BORDER_COLOR, LINE_OXXX); // -.-
            mvwputch(win, FULL_SCREEN_HEIGHT - 1, mLine->first + 1, BORDER_COLOR, LINE_XXOX); // _|_
        }
    }
    wrefresh(win);
    refresh();

    input_context ctxt("WORLDGEN_OPTION_DIALOG");
    ctxt.register_cardinal();
    ctxt.register_action("HELP_KEYBINDINGS");
    ctxt.register_action("QUIT");
    ctxt.register_action("NEXT_TAB");
    ctxt.register_action("PREV_TAB");
    unsigned int sel = 0;
    unsigned int curoption = 0;
    do {
        for (int i = 0; i < iContentHeight; i++) {
            for (int j = 0; j < 79; j++) {
                if (mapLines[j]) {
                    mvwputch(w_options, i, j, BORDER_COLOR, LINE_XOXO);
                } else {
                    mvwputch(w_options, i, j, c_black, ' ');
                }
            }
        }
        curoption = 0;
        for (std::map<std::string, cOpt>::iterator it = world->world_options.begin();
             it != world->world_options.end(); ++it) {
            nc_color cLineColor = c_ltgreen;

            sTemp.str("");
            sTemp << curoption + 1;
            mvwprintz(w_options, curoption , 0, c_white, "%s", sTemp.str().c_str());
            mvwprintz(w_options, curoption , 4, c_white, "");

            if (sel == curoption) {
                wprintz(w_options, c_yellow, ">> ");
            } else {
                wprintz(w_options, c_yellow, " ");
            }

            wprintz(w_options, c_white, "%s", (it->second.getMenuText()).c_str());

            if (it->second.getValue() == "False") {
                cLineColor = c_ltred;
            }

            mvwprintz(w_options, curoption, 62, (sel == curoption) ? hilite(cLineColor) : cLineColor, "%s",
                      (it->second.getValueName()).c_str());
            ++curoption;
        }

        wrefresh(w_options);
        refresh();

        const std::string action = ctxt.handle_input();
        if (action == "DOWN") {
                    sel++;
                    if (sel >= world->world_options.size()) {
                        sel = 0;
                    }
        } else if (action == "UP") {
                    if (sel == 0) {
                        sel = world->world_options.size() - 1;
                    } else {
                        sel--;
                    }
        } else if (!world->world_options.empty() && action == "LEFT") {
                    world->world_options[keys[sel]].setPrev();
        } else if (!world->world_options.empty() && action == "RIGHT") {
                    world->world_options[keys[sel]].setNext();
        } else if (action == "PREV_TAB") {
                    werase(w_options);
                    delwin(w_options);
                    return -1;
        } else if (action == "NEXT_TAB") {
                    werase(w_options);
                    delwin(w_options);
                    return 1;
        } else if (action == "QUIT") {
                    return -999;
        }
    } while (true);

    return 0;
}
Esempio n. 18
0
void player::power_bionics()
{
    std::vector <bionic *> passive;
    std::vector <bionic *> active;
    for (std::vector<bionic>::iterator it = my_bionics.begin();
         it != my_bionics.end(); ++it) {
        if (!bionics[it->id]->activated) {
            passive.push_back(&*it);
        } else {
            active.push_back(&*it);
        }
    }

    // maximal number of rows in both columns
    const int bionic_count = std::max(passive.size(), active.size());

    int TITLE_HEIGHT = 2;
    int DESCRIPTION_HEIGHT = 5;

    // Main window
    /** Total required height is:
    * top frame line:                                         + 1
    * height of title window:                                 + TITLE_HEIGHT
    * line after the title:                                   + 1
    * line with active/passive bionic captions:               + 1
    * height of the biggest list of active/passive bionics:   + bionic_count
    * line before bionic description:                         + 1
    * height of description window:                           + DESCRIPTION_HEIGHT
    * bottom frame line:                                      + 1
    * TOTAL: TITLE_HEIGHT + bionic_count + DESCRIPTION_HEIGHT + 5
    */
    int HEIGHT = std::min(TERMY, std::max(FULL_SCREEN_HEIGHT,
                                          TITLE_HEIGHT + bionic_count + DESCRIPTION_HEIGHT + 5));
    int WIDTH = FULL_SCREEN_WIDTH + (TERMX - FULL_SCREEN_WIDTH) / 2;
    int START_X = (TERMX - WIDTH) / 2;
    int START_Y = (TERMY - HEIGHT) / 2;
    WINDOW *wBio = newwin(HEIGHT, WIDTH, START_Y, START_X);

    // Description window @ the bottom of the bio window
    int DESCRIPTION_START_Y = START_Y + HEIGHT - DESCRIPTION_HEIGHT - 1;
    int DESCRIPTION_LINE_Y = DESCRIPTION_START_Y - START_Y - 1;
    WINDOW *w_description = newwin(DESCRIPTION_HEIGHT, WIDTH - 2,
                                   DESCRIPTION_START_Y, START_X + 1);

    // Title window
    int TITLE_START_Y = START_Y + 1;
    int HEADER_LINE_Y = TITLE_HEIGHT + 1; // + lines with text in titlebar, local
    WINDOW *w_title = newwin(TITLE_HEIGHT, WIDTH - 2, TITLE_START_Y, START_X + 1);

    int scroll_position = 0;
    int second_column = 32 + (TERMX - FULL_SCREEN_WIDTH) /
                        4; // X-coordinate of the list of active bionics

    input_context ctxt("BIONICS");
    ctxt.register_updown();
    ctxt.register_action("ANY_INPUT");
    ctxt.register_action("TOOGLE_EXAMINE");
    ctxt.register_action("REASSIGN");
    ctxt.register_action("REMOVE");
    ctxt.register_action("HELP_KEYBINDINGS");

    bool redraw = true;
    std::string menu_mode = "activating";

    while(true) {
        // offset for display: bionic with index i is drawn at y=list_start_y+i
        // drawing the bionics starts with bionic[scroll_position]
        const int list_start_y = HEADER_LINE_Y + 2 - scroll_position;
        int max_scroll_position = HEADER_LINE_Y + 2 + bionic_count -
                                  ((menu_mode == "examining") ? DESCRIPTION_LINE_Y : (HEIGHT - 1));
        if(redraw) {
            redraw = false;

            werase(wBio);
            draw_border(wBio);
            // Draw line under title
            mvwhline(wBio, HEADER_LINE_Y, 1, LINE_OXOX, WIDTH - 2);
            // Draw symbols to connect additional lines to border
            mvwputch(wBio, HEADER_LINE_Y, 0, BORDER_COLOR, LINE_XXXO); // |-
            mvwputch(wBio, HEADER_LINE_Y, WIDTH - 1, BORDER_COLOR, LINE_XOXX); // -|

            // Captions
            mvwprintz(wBio, HEADER_LINE_Y + 1, 2, c_ltblue, _("Passive:"));
            mvwprintz(wBio, HEADER_LINE_Y + 1, second_column, c_ltblue, _("Active:"));

            draw_exam_window(wBio, DESCRIPTION_LINE_Y, menu_mode == "examining");
            nc_color type;
            if (passive.empty()) {
                mvwprintz(wBio, list_start_y, 2, c_ltgray, _("None"));
            } else {
                for (size_t i = scroll_position; i < passive.size(); i++) {
                    if (list_start_y + static_cast<int>(i) ==
                        (menu_mode == "examining" ? DESCRIPTION_LINE_Y : HEIGHT - 1)) {
                        break;
                    }
                    if (bionics[passive[i]->id]->power_source) {
                        type = c_ltcyan;
                    } else {
                        type = c_cyan;
                    }
                    mvwprintz(wBio, list_start_y + i, 2, type, "%c %s", passive[i]->invlet,
                              bionics[passive[i]->id]->name.c_str());
                }
            }

            if (active.empty()) {
                mvwprintz(wBio, list_start_y, second_column, c_ltgray, _("None"));
            } else {
                for (size_t i = scroll_position; i < active.size(); i++) {
                    if (list_start_y + static_cast<int>(i) ==
                        (menu_mode == "examining" ? DESCRIPTION_LINE_Y : HEIGHT - 1)) {
                        break;
                    }
                    if (active[i]->powered && !bionics[active[i]->id]->power_source) {
                        type = c_red;
                    } else if (bionics[active[i]->id]->power_source && !active[i]->powered) {
                        type = c_ltcyan;
                    } else if (bionics[active[i]->id]->power_source && active[i]->powered) {
                        type = c_ltgreen;
                    } else {
                        type = c_ltred;
                    }
                    mvwputch(wBio, list_start_y + i, second_column, type, active[i]->invlet);
                    mvwprintz(wBio, list_start_y + i, second_column + 2, type,
                              (active[i]->powered ? _("%s - ON") : _("%s - %d PU / %d turns")),
                              bionics[active[i]->id]->name.c_str(),
                              bionics[active[i]->id]->power_cost,
                              bionics[active[i]->id]->charge_time);
                }
            }

            // Scrollbar
            if(scroll_position > 0) {
                mvwputch(wBio, HEADER_LINE_Y + 2, 0, c_ltgreen, '^');
            }
            if(scroll_position < max_scroll_position && max_scroll_position > 0) {
                mvwputch(wBio, (menu_mode == "examining" ? DESCRIPTION_LINE_Y : HEIGHT - 1) - 1,
                         0, c_ltgreen, 'v');
            }
        }
        wrefresh(wBio);
        show_bionics_titlebar(w_title, this, menu_mode);
        const std::string action = ctxt.handle_input();
        const long ch = ctxt.get_raw_input().get_first_input();
        bionic *tmp = NULL;
        if (menu_mode == "reassigning") {
            menu_mode = "activating";
            tmp = bionic_by_invlet(ch);
            if(tmp == 0) {
                // Selected an non-existing bionic (or escape, or ...)
                continue;
            }
            redraw = true;
            const char newch = popup_getkey(_("%s; enter new letter."),
                                            bionics[tmp->id]->name.c_str());
            wrefresh(wBio);
            if(newch == ch || newch == ' ' || newch == KEY_ESCAPE) {
                continue;
            }
            bionic *otmp = bionic_by_invlet(newch);
            // if there is already a bionic with the new invlet, the invlet
            // is considered valid.
            if(otmp == 0 && inv_chars.find(newch) == std::string::npos) {
                // TODO separate list of letters for bionics
                popup(_("%c is not a valid inventory letter."), newch);
                continue;
            }
            if(otmp != 0) {
                std::swap(tmp->invlet, otmp->invlet);
            } else {
                tmp->invlet = newch;
            }
            // TODO: show a message like when reassigning a key to an item?
        } else if (action == "DOWN") {
            if(scroll_position < max_scroll_position) {
                scroll_position++;
                redraw = true;
            }
        } else if (action == "UP") {
            if(scroll_position > 0) {
                scroll_position--;
                redraw = true;
            }
        } else if (action == "REASSIGN") {
            menu_mode = "reassigning";
        } else if (action == "TOOGLE_EXAMINE") { // switches between activation and examination
            menu_mode = menu_mode == "activating" ? "examining" : "activating";
            werase(w_description);
            draw_exam_window(wBio, DESCRIPTION_LINE_Y, false);
            redraw = true;
        } else if (action == "REMOVE") {
            menu_mode = "removing";
            redraw = true;
        } else if (action == "HELP_KEYBINDINGS") {
            redraw = true;
        } else {
            tmp = bionic_by_invlet(ch);
            if(tmp == 0) {
                // entered a key that is not mapped to any bionic,
                // -> leave screen
                break;
            }
            const std::string &bio_id = tmp->id;
            const bionic_data &bio_data = *bionics[bio_id];
            if (menu_mode == "removing") {
                uninstall_bionic(bio_id);
                break;
            }
            if (menu_mode == "activating") {
                if (bio_data.activated) {
                    itype_id weapon_id = weapon.type->id;
                    int b = tmp - &my_bionics[0];
                    if (tmp->powered) {
                        tmp->powered = false;
                        add_msg(m_neutral, _("%s powered off."), bio_data.name.c_str());

                        deactivate_bionic(b);
                    } else if (power_level >= bio_data.power_cost ||
                               (weapon_id == "bio_claws_weapon" && bio_id == "bio_claws_weapon") ||
                               (weapon_id == "bio_blade_weapon" && bio_id == "bio_blade_weapon")) {

                        // this will clear the bionics menu for targeting purposes
                        werase(wBio);
                        wrefresh(wBio);
                        delwin(w_title);
                        delwin(w_description);
                        delwin(wBio);
                        g->draw();
                        activate_bionic(b);

                        if (bio_id == "bio_cqb") {
                            pick_style();
                        }
                    } else {
                        popup( _( "You don't have enough power to activate the %s." ), bio_data.name.c_str() );
                        redraw = true;
                        continue;
                    }
                    // Action done, leave screen
                    break;
                } else {
                    popup(_("\
You can not activate %s!  To read a description of \
%s, press '!', then '%c'."), bio_data.name.c_str(), bio_data.name.c_str(), tmp->invlet);
                    redraw = true;
                }
            }
            if (menu_mode == "examining") { // Describing bionics, not activating them!
                draw_exam_window(wBio, DESCRIPTION_LINE_Y, true);
                // Clear the lines first
                werase(w_description);
                fold_and_print(w_description, 0, 0, WIDTH - 2, c_ltblue, bio_data.description);
                wrefresh(w_description);
            }
        }
    }
    //if we activated a bionic, already killed the windows
    if(!(menu_mode == "activating")) {
        werase(wBio);
        wrefresh(wBio);
        delwin(w_title);
        delwin(w_description);
        delwin(wBio);
    }
}
Esempio n. 19
0
void safemode::test_pattern( const int tab_in, const int row_in )
{
    std::vector<std::string> creature_list;

    auto &temp_rules = ( tab_in == GLOBAL_TAB ) ? global_rules : character_rules;

    if( temp_rules[row_in].rule.empty() ) {
        return;
    }

    if( g->u.name.empty() ) {
        popup( _( "No monsters loaded. Please start a game first." ) );
        return;
    }

    //Loop through all monster mtypes
    for( const auto &mtype : MonsterGenerator::generator().get_all_mtypes() ) {
        std::string creature_name = mtype.nname();
        if( wildcard_match( creature_name, temp_rules[row_in].rule ) ) {
            creature_list.push_back( creature_name );
        }
    }

    const int offset_x = 15 + ( ( TERMX > FULL_SCREEN_WIDTH ) ? ( TERMX - FULL_SCREEN_WIDTH ) / 2 : 0 );
    const int offset_y = 5 + ( ( TERMY > FULL_SCREEN_HEIGHT ) ? ( TERMY - FULL_SCREEN_HEIGHT ) / 2 :
                               0 );

    int start_pos = 0;
    const int content_height = FULL_SCREEN_HEIGHT - 8;
    const int content_width = FULL_SCREEN_WIDTH - 30;

    const catacurses::window w_test_rule_border = catacurses::newwin( content_height + 2, content_width,
            offset_y, offset_x );
    const catacurses::window w_test_rule_content = catacurses::newwin( content_height,
            content_width - 2,
            1 + offset_y, 1 + offset_x );

    int nmatch = creature_list.size();
    const std::string buf = string_format( ngettext( "%1$d monster matches: %2$s",
                                           "%1$d monsters match: %2$s",
                                           nmatch ), nmatch, temp_rules[row_in].rule.c_str() );
    draw_border( w_test_rule_border, BORDER_COLOR, buf, hilite( c_white ) );
    center_print( w_test_rule_border, content_height + 1, red_background( c_white ),
                  _( "Lists monsters regardless of their attitude." ) );

    wrefresh( w_test_rule_border );

    int line = 0;

    input_context ctxt( "SAFEMODE_TEST" );
    ctxt.register_updown();
    ctxt.register_action( "QUIT" );

    while( true ) {
        // Clear the lines
        for( int i = 0; i < content_height; i++ ) {
            for( int j = 0; j < 79; j++ ) {
                mvwputch( w_test_rule_content, i, j, c_black, ' ' );
            }
        }

        calcStartPos( start_pos, line, content_height, creature_list.size() );

        // display safe mode
        for( int i = start_pos; i < static_cast<int>( creature_list.size() ); i++ ) {
            if( i >= start_pos &&
                i < start_pos + std::min( content_height, static_cast<int>( creature_list.size() ) ) ) {
                nc_color line_color = c_white;

                mvwprintz( w_test_rule_content, i - start_pos, 0, line_color, "%d", i + 1 );
                mvwprintz( w_test_rule_content, i - start_pos, 4, line_color, "" );

                wprintz( w_test_rule_content, c_yellow, ( line == i ) ? ">> " : "   " );

                wprintz( w_test_rule_content, ( line == i ) ? hilite( line_color ) : line_color,
                         creature_list[i] );
            }
        }

        wrefresh( w_test_rule_content );

        const std::string action = ctxt.handle_input();
        if( action == "DOWN" ) {
            line++;
            if( line >= static_cast<int>( creature_list.size() ) ) {
                line = 0;
            }
        } else if( action == "UP" ) {
            line--;
            if( line < 0 ) {
                line = creature_list.size() - 1;
            }
        } else {
            break;
        }
    }
}
Esempio n. 20
0
void testCtxt(long m, long p, long widthBound, long L, long r)
{
  if (!noPrint)
    cout << "@testCtxt(m="<<m<<",p="<<p<<",depth="<<widthBound<< ",r="<<r<<")";

  FHEcontext context(m,p,r);
  EncryptedArray ea(context); // Use G(X)=X for this ea object

  // Some arbitrary initial plaintext array
  vector<long> in(ea.size());
  for (long i=0; i<ea.size(); i++) in[i] = i % p;

  // Setup generator-descriptors for the PAlgebra generators
  Vec<GenDescriptor> vec(INIT_SIZE, ea.dimension());
  for (long i=0; i<ea.dimension(); i++)
    vec[i] = GenDescriptor(/*order=*/ea.sizeOfDimension(i),
			   /*good=*/ ea.nativeDimension(i), /*genIdx=*/i);

  // Some default for the width-bound, if not provided
  if (widthBound<=0) widthBound = 1+log2((double)ea.size());

  // Get the generator-tree structures and the corresponding hypercube
  GeneratorTrees trees;
  long cost = trees.buildOptimalTrees(vec, widthBound);
  if (!noPrint) {
    context.zMStar.printout();
    cout << ": trees=" << trees << endl;
    cout << " cost =" << cost << endl;
  }
  //  Vec<long> dims;
  //  trees.getCubeDims(dims);
  //  CubeSignature sig(dims);

  // 1/2 prime per level should be more or less enough, here we use 1 per layer
  if (L<=0) L = (1+trees.numLayers())*context.BPL();
  buildModChain(context, /*nLevels=*/L, /*nDigits=*/3);
  if (!noPrint) cout << "**Using "<<L<<" and "
		     << context.ctxtPrimes.card() << " Ctxt-primes\n";

  // Generate a sk/pk pair
  FHESecKey secretKey(context);
  const FHEPubKey& publicKey = secretKey;
  secretKey.GenSecKey(); // A +-1/0 secret key
  Ctxt ctxt(publicKey);

  for (long cnt=0; cnt<3; cnt++) {
    resetAllTimers();
    // Choose a random permutation
    Permut pi;
    randomPerm(pi, trees.getSize());

    // Build a permutation network for pi
    PermNetwork net;
    net.buildNetwork(pi, trees);

    // make sure we have the key-switching matrices needed for this network
    addMatrices4Network(secretKey, net);

    // Apply the permutation pi to the plaintext
    vector<long> out1(ea.size());
    vector<long> out2(ea.size());
    applyPermToVec(out1, in, pi); // direct application

    // Encrypt plaintext array, then apply permutation network to ciphertext
    ea.encrypt(ctxt, publicKey, in);
    if (!noPrint)
      cout << "  ** applying permutation network to ciphertext... " << flush;
    double t = GetTime();
    net.applyToCtxt(ctxt, ea); // applying permutation netwrok
    t = GetTime() -t;
    if (!noPrint)
      cout << "done in " << t << " seconds" << endl;
    ea.decrypt(ctxt, secretKey, out2);

    if (out1==out2) cout << "GOOD\n";
    else {
      cout << "************ BAD\n";
    }
    // printAllTimers();
  }
}
Esempio n. 21
0
void test_pattern(int iCurrentPage, int iCurrentLine)
{
    std::vector<std::string> vMatchingItems;
    std::string sItemName = "";

    if (vAutoPickupRules[iCurrentPage][iCurrentLine].sRule == "") {
        return;
    }

    //Loop through all itemfactory items
    //TODO: somehow generate damaged, fitting or container items
    for (std::vector<std::string>::iterator it = standard_itype_ids.begin();
         it != standard_itype_ids.end(); ++it) {
        sItemName = item_controller->find_template(*it)->nname(1);
        if (vAutoPickupRules[iCurrentPage][iCurrentLine].bActive &&
            auto_pickup_match(sItemName, vAutoPickupRules[iCurrentPage][iCurrentLine].sRule)) {
            vMatchingItems.push_back(sItemName);
        }
    }

    const int iOffsetX = 15 + ((TERMX > FULL_SCREEN_WIDTH) ? (TERMX - FULL_SCREEN_WIDTH) / 2 : 0);
    const int iOffsetY = 5 + ((TERMY > FULL_SCREEN_HEIGHT) ? (TERMY - FULL_SCREEN_HEIGHT) / 2 : 0);

    int iStartPos = 0;
    const int iContentHeight = FULL_SCREEN_HEIGHT - 8;
    const int iContentWidth = FULL_SCREEN_WIDTH - 30;
    std::stringstream sTemp;

    WINDOW *w_test_rule_border = newwin(iContentHeight + 2, iContentWidth, iOffsetY, iOffsetX);
    WINDOW *w_test_rule_content = newwin(iContentHeight, iContentWidth - 2, 1 + iOffsetY, 1 + iOffsetX);

    draw_border(w_test_rule_border);

    int nmatch = vMatchingItems.size();
    std::string buf = string_format(ngettext("%1$d item matches: %2$s", "%1$d items match: %2$s",
                                    nmatch), nmatch, vAutoPickupRules[iCurrentPage][iCurrentLine].sRule.c_str());
    mvwprintz(w_test_rule_border, 0, iContentWidth / 2 - utf8_width(buf.c_str()) / 2, hilite(c_white),
              "%s", buf.c_str());

    mvwprintz(w_test_rule_border, iContentHeight + 1, 1, red_background(c_white),
              _("Won't display damaged, fits and can/bottle items"));

    wrefresh(w_test_rule_border);

    iCurrentLine = 0;

    input_context ctxt("AUTO_PICKUP_TEST");
    ctxt.register_updown();
    ctxt.register_action("QUIT");

    while(true) {
        // Clear the lines
        for (int i = 0; i < iContentHeight; i++) {
            for (int j = 0; j < 79; j++) {
                mvwputch(w_test_rule_content, i, j, c_black, ' ');
            }
        }

        calcStartPos(iStartPos, iCurrentLine, iContentHeight, vMatchingItems.size());

        // display auto pickup
        for (int i = iStartPos; i < vMatchingItems.size(); i++) {
            if (i >= iStartPos &&
                i < iStartPos + ((iContentHeight > vMatchingItems.size()) ? vMatchingItems.size() :
                                 iContentHeight)) {
                nc_color cLineColor = c_white;

                sTemp.str("");
                sTemp << i + 1;
                mvwprintz(w_test_rule_content, i - iStartPos, 0, cLineColor, "%s", sTemp.str().c_str());
                mvwprintz(w_test_rule_content, i - iStartPos, 4, cLineColor, "");

                if (iCurrentLine == i) {
                    wprintz(w_test_rule_content, c_yellow, ">> ");
                } else {
                    wprintz(w_test_rule_content, c_yellow, "   ");
                }

                wprintz(w_test_rule_content, (iCurrentLine == i) ? hilite(cLineColor) : cLineColor,
                        vMatchingItems[i].c_str());
            }
        }

        wrefresh(w_test_rule_content);

        const std::string action = ctxt.handle_input();
        if (action == "DOWN") {
            iCurrentLine++;
            if (iCurrentLine >= vMatchingItems.size()) {
                iCurrentLine = 0;
            }
        } else if (action == "UP") {
            iCurrentLine--;
            if (iCurrentLine < 0) {
                iCurrentLine = vMatchingItems.size() - 1;
            }
        } else {
            break;
        }
    }

    werase(w_test_rule_border);
    werase(w_test_rule_content);
}
Esempio n. 22
0
void color_manager::show_gui()
{
    const int iHeaderHeight = 4;
    const int iContentHeight = FULL_SCREEN_HEIGHT - 2 - iHeaderHeight;

    const int iOffsetX = (TERMX > FULL_SCREEN_WIDTH) ? (TERMX - FULL_SCREEN_WIDTH) / 2 : 0;
    const int iOffsetY = (TERMY > FULL_SCREEN_HEIGHT) ? (TERMY - FULL_SCREEN_HEIGHT) / 2 : 0;

    std::vector<int> vLines;
    vLines.push_back(-1);
    vLines.push_back(48);

    const int iTotalCols = vLines.size();

    WINDOW *w_colors_help = newwin((FULL_SCREEN_HEIGHT / 2) - 2, FULL_SCREEN_WIDTH * 3 / 4,
                                        7 + iOffsetY + (FULL_SCREEN_HEIGHT / 2) / 2, iOffsetX + 19 / 2);
    WINDOW_PTR w_colors_helpptr( w_colors_help );

    WINDOW *w_colors_border = newwin(FULL_SCREEN_HEIGHT, FULL_SCREEN_WIDTH, iOffsetY, iOffsetX);
    WINDOW_PTR w_colors_borderptr( w_colors_border );
    WINDOW *w_colors_header = newwin(iHeaderHeight, FULL_SCREEN_WIDTH - 2, 1 + iOffsetY,
                                          1 + iOffsetX);
    WINDOW_PTR w_colors_headerptr( w_colors_header );
    WINDOW *w_colors = newwin(iContentHeight, FULL_SCREEN_WIDTH - 2, iHeaderHeight + 1 + iOffsetY,
                                   1 + iOffsetX);
    WINDOW_PTR w_colorsptr( w_colors );

    draw_border(w_colors_border);
    mvwputch(w_colors_border, 3,  0, c_ltgray, LINE_XXXO); // |-
    mvwputch(w_colors_border, 3, 79, c_ltgray, LINE_XOXX); // -|

    for (int i = 0; i < 78; i++) {
        mvwputch(w_colors_header, 2, i, c_ltgray, LINE_OXOX); // Draw line under header
    }

    for( auto &iCol : vLines ) {
        if ( iCol > -1 ) {
            mvwputch(w_colors_border, FULL_SCREEN_HEIGHT - 1, iCol + 1, c_ltgray, LINE_XXOX); // _|_
            mvwputch(w_colors_header, 2, iCol, c_ltgray, LINE_OXXX);
            mvwputch(w_colors_header, 3, iCol, c_ltgray, LINE_XOXO);
        }
    }

    mvwprintz(w_colors_border, 0, 32, c_ltred, _(" COLOR MANAGER "));
    wrefresh(w_colors_border);

    int tmpx = 0;
    tmpx += shortcut_print(w_colors_header, 0, tmpx, c_white, c_ltgreen, _("<R>emove custom color")) + 2;
    tmpx += shortcut_print(w_colors_header, 0, tmpx, c_white, c_ltgreen, _("<Arrow Keys> To navigate")) + 2;
    tmpx += shortcut_print(w_colors_header, 0, tmpx, c_white, c_ltgreen, _("<Enter>-Edit")) + 2;
    shortcut_print(w_colors_header, 0, tmpx, c_white, c_ltgreen, _("Load <T>emplate"));

    mvwprintz(w_colors_header, 1, 0, c_white, _("Some color changes may require a restart."));

    mvwprintz(w_colors_header, 3, 3, c_white, _("Colorname"));
    mvwprintz(w_colors_header, 3, 21, c_white, _("Normal"));
    mvwprintz(w_colors_header, 3, 52, c_white, _("Invert"));

    wrefresh(w_colors_header);

    int iCurrentLine = 0;
    int iCurrentCol = 1;
    int iStartPos = 0;
    const int iMaxColors = color_array.size();
    bool bStuffChanged = false;
    input_context ctxt("COLORS");
    ctxt.register_cardinal();
    ctxt.register_action("CONFIRM");
    ctxt.register_action("QUIT");
    ctxt.register_action("REMOVE_CUSTOM");
    ctxt.register_action("LOAD_TEMPLATE");
    ctxt.register_action("HELP_KEYBINDINGS");

    std::map<std::string, color_struct> name_color_map;

    for( const auto &pr : name_map ) {
        name_color_map[pr.first] = color_array[pr.second];
    }

    while(true) {
        // Clear all lines
        for (int i = 0; i < iContentHeight; i++) {
            for (int j = 0; j < 79; j++) {
                mvwputch(w_colors, i, j, c_black, ' ');

                for( auto &iCol : vLines ) {
                    if ( iCol == j ) {
                        mvwputch(w_colors, i, j, c_ltgray, LINE_XOXO);
                    }
                }
            }
        }

        calcStartPos(iStartPos, iCurrentLine, iContentHeight, iMaxColors);

        //Draw Scrollbar
        draw_scrollbar(w_colors_border, iCurrentLine, iContentHeight, iMaxColors, 5);

        auto iter = name_color_map.begin();
        std::advance( iter, iStartPos );

        std::string sActive = "";

        // display colormanager
        for (int i=iStartPos; iter != name_color_map.end(); ++iter, ++i) {
            if (i >= iStartPos && i < iStartPos + ((iContentHeight > iMaxColors) ? iMaxColors : iContentHeight)) {
                auto &entry = iter->second;

                if (iCurrentLine == i) {
                    sActive = iter->first;
                    mvwprintz(w_colors, i - iStartPos, vLines[iCurrentCol-1] + 2, c_yellow, ">");
                }

                mvwprintz(w_colors, i - iStartPos, 3, c_white, iter->first.c_str()); //colorname
                mvwprintz(w_colors, i - iStartPos, 21, entry.color, _("default")); //default color

                if ( !entry.name_custom.empty() ) {
                    mvwprintz(w_colors, i - iStartPos, 30, name_color_map[entry.name_custom].color, entry.name_custom.c_str()); //custom color
                }

                mvwprintz(w_colors, i - iStartPos, 52, entry.invert, _("default")); //invert default color

                if ( !entry.name_invert_custom.empty() ) {
                    mvwprintz(w_colors, i - iStartPos, 61, name_color_map[entry.name_invert_custom].color, entry.name_invert_custom.c_str()); //invert custom color
                }
            }
        }

        wrefresh(w_colors);

        const std::string action = ctxt.handle_input();

        if (action == "QUIT") {
            break;
        } else if (action == "UP") {
            iCurrentLine--;
            if (iCurrentLine < 0) {
                iCurrentLine = iMaxColors - 1;
            }
        } else if (action == "DOWN") {
            iCurrentLine++;
            if (iCurrentLine >= (int)iMaxColors) {
                iCurrentLine = 0;
            }
        } else if (action == "LEFT") {
            iCurrentCol--;
            if (iCurrentCol < 1) {
                iCurrentCol = iTotalCols;
            }
        } else if (action == "RIGHT") {
            iCurrentCol++;
            if (iCurrentCol > iTotalCols) {
                iCurrentCol = 1;
            }
        } else if (action == "REMOVE_CUSTOM") {
            auto &entry = name_color_map[sActive];

            if ( iCurrentCol == 1 && !entry.name_custom.empty() ) {
                bStuffChanged = true;
                entry.name_custom = "";

            } else if ( iCurrentCol == 2 && !entry.name_invert_custom.empty() ) {
                bStuffChanged = true;
                entry.name_invert_custom = "";

            }

            finalize(); // Need to recalculate caches

        } else if (action == "LOAD_TEMPLATE") {
            auto vFiles = get_files_from_path(".json", FILENAMES["color_templates"], false, true);

            if ( vFiles.size() > 0 ) {
                uimenu ui_templates;
                ui_templates.w_y = iHeaderHeight + 1 + iOffsetY;
                ui_templates.w_height = 18;
                ui_templates.return_invalid = true;

                ui_templates.text = _("Color templates:");

                for ( const auto& filename : vFiles ) {
                    ui_templates.addentry( filename.substr(filename.find_last_of("/") + 1) );
                }

                ui_templates.addentry(std::string(_("Cancel")));
                ui_templates.query();

                if ( (size_t)ui_templates.ret < vFiles.size() ) {
                    bStuffChanged = true;

                    clear();

                    load_default();
                    load_custom(vFiles[ui_templates.ret]);

                    name_color_map.clear();
                    for( const auto &pr : name_map ) {
                        name_color_map[pr.first] = color_array[pr.second];
                    }
                }
            }

            finalize(); // Need to recalculate caches

        } else if (action == "CONFIRM") {
            uimenu ui_colors;
            ui_colors.w_y = iHeaderHeight + 1 + iOffsetY;
            ui_colors.w_height = 18;
            ui_colors.return_invalid = true;

            std::string sColorType = _("Normal");
            std::string sSelected = name_color_map[sActive].name_custom;

            if ( iCurrentCol == 2 ) {
                sColorType = _("Invert");
                sSelected = name_color_map[sActive].name_invert_custom;

            }

            ui_colors.text = string_format( _("Custom %s color:"), sColorType.c_str() );

            int i = 0;
            for ( auto &iter : name_color_map ) {
                std::string sColor = iter.first;
                std::string sType = _("default");

                std::string name_custom = "";

                if ( sSelected == sColor ) {
                    ui_colors.selected = i;
                }

                if ( !iter.second.name_custom.empty() ) {
                    name_custom = " <color_" + iter.second.name_custom + ">" + iter.second.name_custom + "</color>";
                }

                ui_colors.addentry(string_format( "%-17s <color_%s>%s</color>%s", iter.first.c_str(), sColor.c_str(), sType.c_str(), name_custom.c_str() ) );

                i++;
            }

            ui_colors.addentry(std::string(_("Cancel")));
            ui_colors.query();

            if ( (size_t)ui_colors.ret < name_color_map.size() ) {
                bStuffChanged = true;

                iter = name_color_map.begin();
                std::advance( iter, ui_colors.ret );

                auto &entry = name_color_map[sActive];

                if ( iCurrentCol == 1 ) {
                    entry.name_custom = iter->first;

                } else if ( iCurrentCol == 2 ) {
                    entry.name_invert_custom = iter->first;

                }
            }

            finalize(); // Need to recalculate caches
        }
    }

    if( bStuffChanged && query_yn(_("Save changes?") ) ) {
        for( const auto &pr : name_color_map ) {
            color_id id = name_to_id( pr.first );
            color_array[id].name_custom = pr.second.name_custom;
            color_array[id].name_invert_custom = pr.second.name_invert_custom;
        }

        finalize();
        save_custom();

        clear();
        load_default();
        load_custom();
    }
}
Esempio n. 23
0
void player::power_mutations()
{
    if( !is_player() ) {
        // TODO: Implement NPCs activating muts
        return;
    }

    std::vector <std::string> passive;
    std::vector <std::string> active;
    for( auto &mut : my_mutations ) {
        if (!mutation_branch::get( mut.first ).activated) {
            passive.push_back(mut.first);
        } else {
            active.push_back(mut.first);
        }
        // New mutations are initialized with no key at all, so we have to do this here.
        if( mut.second.key == ' ' ) {
            for( const auto &letter : mutation_chars ) {
                if( trait_by_invlet( letter ).empty() ) {
                    mut.second.key = letter;
                    break;
                }
            }
        }
    }

    // maximal number of rows in both columns
    const int mutations_count = std::max(passive.size(), active.size());

    int TITLE_HEIGHT = 2;
    int DESCRIPTION_HEIGHT = 5;

    // Main window
    /** Total required height is:
    * top frame line:                                         + 1
    * height of title window:                                 + TITLE_HEIGHT
    * line after the title:                                   + 1
    * line with active/passive mutation captions:               + 1
    * height of the biggest list of active/passive mutations:   + mutations_count
    * line before mutation description:                         + 1
    * height of description window:                           + DESCRIPTION_HEIGHT
    * bottom frame line:                                      + 1
    * TOTAL: TITLE_HEIGHT + mutations_count + DESCRIPTION_HEIGHT + 5
    */
    int HEIGHT = std::min(TERMY, std::max(FULL_SCREEN_HEIGHT,
                                          TITLE_HEIGHT + mutations_count + DESCRIPTION_HEIGHT + 5));
    int WIDTH = FULL_SCREEN_WIDTH + (TERMX - FULL_SCREEN_WIDTH) / 2;
    int START_X = (TERMX - WIDTH) / 2;
    int START_Y = (TERMY - HEIGHT) / 2;
    WINDOW *wBio = newwin(HEIGHT, WIDTH, START_Y, START_X);

    // Description window @ the bottom of the bio window
    int DESCRIPTION_START_Y = START_Y + HEIGHT - DESCRIPTION_HEIGHT - 1;
    int DESCRIPTION_LINE_Y = DESCRIPTION_START_Y - START_Y - 1;
    WINDOW *w_description = newwin(DESCRIPTION_HEIGHT, WIDTH - 2,
                                   DESCRIPTION_START_Y, START_X + 1);

    // Title window
    int TITLE_START_Y = START_Y + 1;
    int HEADER_LINE_Y = TITLE_HEIGHT + 1; // + lines with text in titlebar, local
    WINDOW *w_title = newwin(TITLE_HEIGHT, WIDTH - 2, TITLE_START_Y, START_X + 1);

    int scroll_position = 0;
    int second_column = 32 + (TERMX - FULL_SCREEN_WIDTH) /
                        4; // X-coordinate of the list of active mutations

    input_context ctxt("MUTATIONS");
    ctxt.register_updown();
    ctxt.register_action("ANY_INPUT");
    ctxt.register_action("TOGGLE_EXAMINE");
    ctxt.register_action("REASSIGN");
    ctxt.register_action("HELP_KEYBINDINGS");

    bool redraw = true;
    std::string menu_mode = "activating";

    while(true) {
        // offset for display: mutation with index i is drawn at y=list_start_y+i
        // drawing the mutation starts with mutation[scroll_position]
        const int list_start_y = HEADER_LINE_Y + 2 - scroll_position;
        int max_scroll_position = HEADER_LINE_Y + 2 + mutations_count -
                                  ((menu_mode == "examining") ? DESCRIPTION_LINE_Y : (HEIGHT - 1));
        if(redraw) {
            redraw = false;

            werase(wBio);
            draw_border(wBio);
            // Draw line under title
            mvwhline(wBio, HEADER_LINE_Y, 1, LINE_OXOX, WIDTH - 2);
            // Draw symbols to connect additional lines to border
            mvwputch(wBio, HEADER_LINE_Y, 0, BORDER_COLOR, LINE_XXXO); // |-
            mvwputch(wBio, HEADER_LINE_Y, WIDTH - 1, BORDER_COLOR, LINE_XOXX); // -|

            // Captions
            mvwprintz(wBio, HEADER_LINE_Y + 1, 2, c_ltblue, _("Passive:"));
            mvwprintz(wBio, HEADER_LINE_Y + 1, second_column, c_ltblue, _("Active:"));

            draw_exam_window(wBio, DESCRIPTION_LINE_Y, menu_mode == "examining");
            nc_color type;
            if (passive.empty()) {
                mvwprintz(wBio, list_start_y, 2, c_ltgray, _("None"));
            } else {
                for (size_t i = scroll_position; i < passive.size(); i++) {
                    const auto &md = mutation_branch::get( passive[i] );
                    const auto &td = my_mutations[passive[i]];
                    if (list_start_y + static_cast<int>(i) ==
                        (menu_mode == "examining" ? DESCRIPTION_LINE_Y : HEIGHT - 1)) {
                        break;
                    }
                    type = c_cyan;
                    mvwprintz(wBio, list_start_y + i, 2, type, "%c %s", td.key, md.name.c_str());
                }
            }

            if (active.empty()) {
                mvwprintz(wBio, list_start_y, second_column, c_ltgray, _("None"));
            } else {
                for (size_t i = scroll_position; i < active.size(); i++) {
                    const auto &md = mutation_branch::get( active[i] );
                    const auto &td = my_mutations[active[i]];
                    if (list_start_y + static_cast<int>(i) ==
                        (menu_mode == "examining" ? DESCRIPTION_LINE_Y : HEIGHT - 1)) {
                        break;
                    }
                    if (!td.powered) {
                        type = c_red;
                    }else if (td.powered) {
                        type = c_ltgreen;
                    } else {
                        type = c_ltred;
                    }
                    // TODO: track resource(s) used and specify
                    mvwputch( wBio, list_start_y + i, second_column, type, td.key );
                    std::stringstream mut_desc;
                    mut_desc << md.name;
                    if ( md.cost > 0 && md.cooldown > 0 ) {
                        mut_desc << string_format( _(" - %d RU / %d turns"),
                                      md.cost, md.cooldown );
                    } else if ( md.cost > 0 ) {
                        mut_desc << string_format( _(" - %d RU"), md.cost );
                    } else if ( md.cooldown > 0 ) {
                        mut_desc << string_format( _(" - %d turns"), md.cooldown );
                    }
                    if ( td.powered ) {
                        mut_desc << _(" - Active");
                    }
                    mvwprintz( wBio, list_start_y + i, second_column + 2, type,
                               mut_desc.str().c_str() );
                }
            }

            // Scrollbar
            if(scroll_position > 0) {
                mvwputch(wBio, HEADER_LINE_Y + 2, 0, c_ltgreen, '^');
            }
            if(scroll_position < max_scroll_position && max_scroll_position > 0) {
                mvwputch(wBio, (menu_mode == "examining" ? DESCRIPTION_LINE_Y : HEIGHT - 1) - 1,
                         0, c_ltgreen, 'v');
            }
        }
        wrefresh(wBio);
        show_mutations_titlebar(w_title, this, menu_mode);
        const std::string action = ctxt.handle_input();
        const long ch = ctxt.get_raw_input().get_first_input();
        if (menu_mode == "reassigning") {
            menu_mode = "activating";
            const auto mut_id = trait_by_invlet( ch );
            if( mut_id.empty() ) {
                // Selected an non-existing mutation (or escape, or ...)
                continue;
            }
            redraw = true;
            const long newch = popup_getkey(_("%s; enter new letter."),
                                            mutation_branch::get_name( mut_id ).c_str());
            wrefresh(wBio);
            if(newch == ch || newch == ' ' || newch == KEY_ESCAPE) {
                continue;
            }
            if( !mutation_chars.valid( newch ) ) {
                popup( _("Invalid mutation letter. Only those characters are valid:\n\n%s"),
                       mutation_chars.get_allowed_chars().c_str() );
                continue;
            }
            const auto other_mut_id = trait_by_invlet( newch );
            if( !other_mut_id.empty() ) {
                std::swap(my_mutations[mut_id].key, my_mutations[other_mut_id].key);
            } else {
                my_mutations[mut_id].key = newch;
            }
            // TODO: show a message like when reassigning a key to an item?
        } else if (action == "DOWN") {
            if(scroll_position < max_scroll_position) {
                scroll_position++;
                redraw = true;
            }
        } else if (action == "UP") {
            if(scroll_position > 0) {
                scroll_position--;
                redraw = true;
            }
        } else if (action == "REASSIGN") {
            menu_mode = "reassigning";
        } else if (action == "TOGGLE_EXAMINE") { // switches between activation and examination
            menu_mode = menu_mode == "activating" ? "examining" : "activating";
            werase(w_description);
            draw_exam_window(wBio, DESCRIPTION_LINE_Y, false);
            redraw = true;
        }else if (action == "HELP_KEYBINDINGS") {
            redraw = true;
        } else {
            const auto mut_id = trait_by_invlet( ch );
            if( mut_id.empty() ) {
                // entered a key that is not mapped to any mutation,
                // -> leave screen
                break;
            }
            const auto &mut_data = mutation_branch::get( mut_id );
            if (menu_mode == "activating") {
                if (mut_data.activated) {
                    if (my_mutations[mut_id].powered) {
                        add_msg_if_player(m_neutral, _("You stop using your %s."), mut_data.name.c_str());

                        deactivate_mutation( mut_id );
                        delwin(w_title);
                        delwin(w_description);
                        delwin(wBio);
                        // Action done, leave screen
                        break;
                    } else if( (!mut_data.hunger || get_hunger() <= 400) &&
                               (!mut_data.thirst || get_thirst() <= 400) &&
                               (!mut_data.fatigue || get_fatigue() <= 400) ) {

                        // this will clear the mutations menu for targeting purposes
                        werase(wBio);
                        wrefresh(wBio);
                        delwin(w_title);
                        delwin(w_description);
                        delwin(wBio);
                        g->draw();
                        add_msg_if_player( m_neutral, _("You activate your %s."), mut_data.name.c_str() );
                        activate_mutation( mut_id );
                        // Action done, leave screen
                        break;
                    } else {
                        popup( _( "You don't have enough in you to activate your %s!" ), mut_data.name.c_str() );
                        redraw = true;
                        continue;
                    }
                } else {
                    popup(_("\
You cannot activate %s!  To read a description of \
%s, press '!', then '%c'."), mut_data.name.c_str(), mut_data.name.c_str(),
                          my_mutations[mut_id].key );
                    redraw = true;
                }
            }
            if (menu_mode == "examining") { // Describing mutations, not activating them!
                draw_exam_window(wBio, DESCRIPTION_LINE_Y, true);
                // Clear the lines first
                werase(w_description);
                fold_and_print(w_description, 0, 0, WIDTH - 2, c_ltblue, mut_data.description);
                wrefresh(w_description);
            }
        }
    }
    //if we activated a mutation, already killed the windows
    if(!(menu_mode == "activating")) {
        werase(wBio);
        wrefresh(wBio);
        delwin(w_title);
        delwin(w_description);
        delwin(wBio);
    }
}
Esempio n. 24
0
const recipe *select_crafting_recipe( int &batch_size )
{
    if( normalized_names.empty() ) {
        translate_all();
    }

    const int headHeight = 3;
    const int subHeadHeight = 2;
    const int freeWidth = TERMX - FULL_SCREEN_WIDTH;
    bool isWide = ( TERMX > FULL_SCREEN_WIDTH && freeWidth > 15 );

    const int width = isWide ? ( freeWidth > FULL_SCREEN_WIDTH ? FULL_SCREEN_WIDTH * 2 : TERMX ) :
                      FULL_SCREEN_WIDTH;
    const int wStart = ( TERMX - width ) / 2;
    const int tailHeight = isWide ? 3 : 4;
    const int dataLines = TERMY - ( headHeight + subHeadHeight ) - tailHeight;
    const int dataHalfLines = dataLines / 2;
    const int dataHeight = TERMY - ( headHeight + subHeadHeight );
    const int infoWidth = width - FULL_SCREEN_WIDTH - 1;

    const recipe *last_recipe = nullptr;

    WINDOW *w_head = newwin( headHeight, width, 0, wStart );
    WINDOW_PTR w_head_ptr( w_head );
    WINDOW *w_subhead = newwin( subHeadHeight, width, 3, wStart );
    WINDOW_PTR w_subhead_ptr( w_subhead );
    WINDOW *w_data = newwin( dataHeight, width, headHeight + subHeadHeight, wStart );
    WINDOW_PTR w_data_ptr( w_data );

    int item_info_x = infoWidth;
    int item_info_y = dataHeight - 3;
    int item_info_width = wStart + width - infoWidth;
    int item_info_height = headHeight + subHeadHeight;

    if( !isWide ) {
        item_info_x = 1;
        item_info_y = 1;
        item_info_width = 1;
        item_info_height = 1;
    }

    WINDOW *w_iteminfo = newwin( item_info_y, item_info_x, item_info_height, item_info_width );
    WINDOW_PTR w_iteminfo_ptr( w_iteminfo );

    list_circularizer<std::string> tab( craft_cat_list );
    list_circularizer<std::string> subtab( craft_subcat_list[tab.cur()] );
    std::vector<const recipe *> current;
    std::vector<bool> available;
    const int componentPrintHeight = dataHeight - tailHeight - 1;
    //preserves component color printout between mode rotations
    nc_color rotated_color = c_white;
    int previous_item_line = -1;
    std::string previous_tab = "";
    std::string previous_subtab = "";
    item tmp;
    int line = 0, ypos, scroll_pos = 0;
    bool redraw = true;
    bool keepline = false;
    bool done = false;
    bool batch = false;
    int batch_line = 0;
    int display_mode = 0;
    const recipe *chosen = NULL;
    std::vector<iteminfo> thisItem, dummy;

    input_context ctxt( "CRAFTING" );
    ctxt.register_cardinal();
    ctxt.register_action( "QUIT" );
    ctxt.register_action( "CONFIRM" );
    ctxt.register_action( "CYCLE_MODE" );
    ctxt.register_action( "SCROLL_UP" );
    ctxt.register_action( "SCROLL_DOWN" );
    ctxt.register_action( "PREV_TAB" );
    ctxt.register_action( "NEXT_TAB" );
    ctxt.register_action( "FILTER" );
    ctxt.register_action( "RESET_FILTER" );
    ctxt.register_action( "HELP_RECIPE" );
    ctxt.register_action( "HELP_KEYBINDINGS" );
    ctxt.register_action( "CYCLE_BATCH" );

    const inventory &crafting_inv = g->u.crafting_inventory();
    const std::vector<npc *> helpers = g->u.get_crafting_helpers();
    std::string filterstring = "";

    const auto &available_recipes = g->u.get_available_recipes( crafting_inv, &helpers );
    std::map<const recipe *, bool> availability_cache;

    do {
        if( redraw ) {
            // When we switch tabs, redraw the header
            redraw = false;
            if( ! keepline ) {
                line = 0;
            } else {
                keepline = false;
            }

            if( display_mode > 2 ) {
                display_mode = 2;
            }

            TAB_MODE m = ( batch ) ? BATCH : ( filterstring == "" ) ? NORMAL : FILTERED;
            draw_recipe_tabs( w_head, tab.cur(), m );
            draw_recipe_subtabs( w_subhead, tab.cur(), subtab.cur(), m );

            available.clear();

            if( batch ) {
                current.clear();
                for( int i = 1; i <= 20; i++ ) {
                    current.push_back( chosen );
                    available.push_back( chosen->requirements().can_make_with_inventory( crafting_inv, i ) );
                }
            } else {
                if( filterstring.empty() ) {
                    current = available_recipes.in_category( tab.cur(), subtab.cur() != "CSC_ALL" ? subtab.cur() : "" );
                } else {
                    auto qry = trim( filterstring );
                    if( qry.size() > 2 && qry[1] == ':' ) {
                        switch( qry[0] ) {
                            case 't':
                                current = available_recipes.search( qry.substr( 2 ), recipe_subset::search_type::tool );
                                break;

                            case 'c':
                                current = available_recipes.search( qry.substr( 2 ), recipe_subset::search_type::component );
                                break;

                            case 's':
                                current = available_recipes.search( qry.substr( 2 ), recipe_subset::search_type::skill );
                                break;

                            case 'q':
                                current = available_recipes.search( qry.substr( 2 ), recipe_subset::search_type::quality );
                                break;

                            case 'Q':
                                current = available_recipes.search( qry.substr( 2 ), recipe_subset::search_type::quality_result );
                                break;

                            default:
                                current.clear();
                        }
                    } else {
                        current = available_recipes.search( qry );
                    }
                }
                available.reserve( current.size() );
                // cache recipe availability on first display
                for( const auto e : current ) {
                    if( !availability_cache.count( e ) ) {
                        availability_cache.emplace( e, e->requirements().can_make_with_inventory( crafting_inv ) );
                    }
                }

                std::stable_sort( current.begin(), current.end(), []( const recipe * a, const recipe * b ) {
                    return b->difficulty < a->difficulty;
                } );

                std::stable_sort( current.begin(), current.end(), [&]( const recipe * a, const recipe * b ) {
                    return availability_cache[a] && !availability_cache[b];
                } );

                std::transform( current.begin(), current.end(),
                std::back_inserter( available ), [&]( const recipe * e ) {
                    return availability_cache[e];
                } );
            }

            // current/available have been rebuilt, make sure our cursor is still in range
            if( current.empty() ) {
                line = 0;
            } else {
                line = std::min( line, ( int )current.size() - 1 );
            }
        }

        // Clear the screen of recipe data, and draw it anew
        werase( w_data );

        if( isWide ) {
            werase( w_iteminfo );
        }

        if( isWide ) {
            mvwprintz( w_data, dataLines + 1, 5, c_white,
                       _( "Press <ENTER> to attempt to craft object." ) );
            wprintz( w_data, c_white, "  " );
            if( filterstring != "" ) {
                wprintz( w_data, c_white, _( "[E]: Describe, [F]ind, [R]eset, [m]ode, %s [?] keybindings" ),
                         ( batch ) ? _( "cancel [b]atch" ) : _( "[b]atch" ) );
            } else {
                wprintz( w_data, c_white, _( "[E]: Describe, [F]ind, [m]ode, %s [?] keybindings" ),
                         ( batch ) ? _( "cancel [b]atch" ) : _( "[b]atch" ) );
            }
        } else {
            if( filterstring != "" ) {
                mvwprintz( w_data, dataLines + 1, 5, c_white,
                           _( "[E]: Describe, [F]ind, [R]eset, [m]ode, [b]atch [?] keybindings" ) );
            } else {
                mvwprintz( w_data, dataLines + 1, 5, c_white,
                           _( "[E]: Describe, [F]ind, [m]ode, [b]atch [?] keybindings" ) );
            }
            mvwprintz( w_data, dataLines + 2, 5, c_white,
                       _( "Press <ENTER> to attempt to craft object." ) );
        }
        // Draw borders
        for( int i = 1; i < width - 1; ++i ) { // _
            mvwputch( w_data, dataHeight - 1, i, BORDER_COLOR, LINE_OXOX );
        }
        for( int i = 0; i < dataHeight - 1; ++i ) { // |
            mvwputch( w_data, i, 0, BORDER_COLOR, LINE_XOXO );
            mvwputch( w_data, i, width - 1, BORDER_COLOR, LINE_XOXO );
        }
        mvwputch( w_data, dataHeight - 1,  0, BORDER_COLOR, LINE_XXOO ); // _|
        mvwputch( w_data, dataHeight - 1, width - 1, BORDER_COLOR, LINE_XOOX ); // |_

        int recmin = 0, recmax = current.size();
        if( recmax > dataLines ) {
            if( line <= recmin + dataHalfLines ) {
                for( int i = recmin; i < recmin + dataLines; ++i ) {
                    std::string tmp_name = item::nname( current[i]->result );
                    if( batch ) {
                        tmp_name = string_format( _( "%2dx %s" ), i + 1, tmp_name.c_str() );
                    }
                    mvwprintz( w_data, i - recmin, 2, c_dkgray, "" ); // Clear the line
                    if( i == line ) {
                        mvwprintz( w_data, i - recmin, 2, ( available[i] ? h_white : h_dkgray ),
                                   utf8_truncate( tmp_name, 28 ).c_str() );
                    } else {
                        mvwprintz( w_data, i - recmin, 2, ( available[i] ? c_white : c_dkgray ),
                                   utf8_truncate( tmp_name, 28 ).c_str() );
                    }
                }
            } else if( line >= recmax - dataHalfLines ) {
                for( int i = recmax - dataLines; i < recmax; ++i ) {
                    std::string tmp_name = item::nname( current[i]->result );
                    if( batch ) {
                        tmp_name = string_format( _( "%2dx %s" ), i + 1, tmp_name.c_str() );
                    }
                    mvwprintz( w_data, dataLines + i - recmax, 2, c_ltgray, "" ); // Clear the line
                    if( i == line ) {
                        mvwprintz( w_data, dataLines + i - recmax, 2,
                                   ( available[i] ? h_white : h_dkgray ),
                                   utf8_truncate( tmp_name, 28 ).c_str() );
                    } else {
                        mvwprintz( w_data, dataLines + i - recmax, 2,
                                   ( available[i] ? c_white : c_dkgray ),
                                   utf8_truncate( tmp_name, 28 ).c_str() );
                    }
                }
            } else {
                for( int i = line - dataHalfLines; i < line - dataHalfLines + dataLines; ++i ) {
                    std::string tmp_name = item::nname( current[i]->result );
                    if( batch ) {
                        tmp_name = string_format( _( "%2dx %s" ), i + 1, tmp_name.c_str() );
                    }
                    mvwprintz( w_data, dataHalfLines + i - line, 2, c_ltgray, "" ); // Clear the line
                    if( i == line ) {
                        mvwprintz( w_data, dataHalfLines + i - line, 2,
                                   ( available[i] ? h_white : h_dkgray ),
                                   utf8_truncate( tmp_name, 28 ).c_str() );
                    } else {
                        mvwprintz( w_data, dataHalfLines + i - line, 2,
                                   ( available[i] ? c_white : c_dkgray ),
                                   utf8_truncate( tmp_name, 28 ).c_str() );
                    }
                }
            }
        } else {
            for( size_t i = 0; i < current.size() && i < ( size_t )dataHeight + 1; ++i ) {
                std::string tmp_name = item::nname( current[i]->result );
                if( batch ) {
                    tmp_name = string_format( _( "%2dx %s" ), ( int )i + 1, tmp_name.c_str() );
                }
                if( ( int )i == line ) {
                    mvwprintz( w_data, i, 2, ( available[i] ? h_white : h_dkgray ),
                               utf8_truncate( tmp_name, 28 ).c_str() );
                } else {
                    mvwprintz( w_data, i, 2, ( available[i] ? c_white : c_dkgray ),
                               utf8_truncate( tmp_name, 28 ).c_str() );
                }
            }
        }

        if( !current.empty() ) {
            int pane = FULL_SCREEN_WIDTH - 30 - 1;
            int count = batch ? line + 1 : 1; // batch size
            nc_color col = available[ line ] ? c_white : c_ltgray;

            const auto &req = current[ line ]->requirements();

            draw_can_craft_indicator( w_head, 0, *current[line] );
            wrefresh( w_head );

            ypos = 0;

            std::vector<std::string> component_print_buffer;
            auto tools = req.get_folded_tools_list( pane, col, crafting_inv, count );
            auto comps = req.get_folded_components_list( pane, col, crafting_inv, count );
            component_print_buffer.insert( component_print_buffer.end(), tools.begin(), tools.end() );
            component_print_buffer.insert( component_print_buffer.end(), comps.begin(), comps.end() );

            if( !g->u.knows_recipe( current[line] ) ) {
                component_print_buffer.push_back( _( "Recipe not memorized yet" ) );
            }

            //handle positioning of component list if it needed to be scrolled
            int componentPrintOffset = 0;
            if( display_mode > 2 ) {
                componentPrintOffset = ( display_mode - 2 ) * componentPrintHeight;
            }
            if( component_print_buffer.size() < static_cast<size_t>( componentPrintOffset ) ) {
                componentPrintOffset = 0;
                if( previous_tab != tab.cur() || previous_subtab != subtab.cur() || previous_item_line != line ) {
                    display_mode = 2;
                } else {
                    display_mode = 0;
                }
            }

            //only used to preserve mode position on components when
            //moving to another item and the view is already scrolled
            previous_tab = tab.cur();
            previous_subtab = subtab.cur();
            previous_item_line = line;

            if( display_mode == 0 ) {
                mvwprintz( w_data, ypos++, 30, col, _( "Skills used: %s" ),
                           ( !current[line]->skill_used ? _( "N/A" ) :
                             current[line]->skill_used.obj().name().c_str() ) );

                mvwprintz( w_data, ypos++, 30, col, _( "Required skills: %s" ),
                           ( current[line]->required_skills_string().c_str() ) );
                mvwprintz( w_data, ypos++, 30, col, _( "Difficulty: %d" ),
                           current[ line ]->difficulty );
                if( !current[line]->skill_used ) {
                    mvwprintz( w_data, ypos++, 30, col, _( "Your skill level: N/A" ) );
                } else {
                    mvwprintz( w_data, ypos++, 30, col, _( "Your skill level: %d" ),
                               // Macs don't seem to like passing this as a class, so force it to int
                               ( int )g->u.get_skill_level( current[line]->skill_used ) );
                }
                ypos += current[line]->print_time( w_data, ypos, 30, pane, col, count );
                mvwprintz( w_data, ypos++, 30, col, _( "Dark craftable? %s" ),
                           current[line]->has_flag( "BLIND_EASY" ) ? _( "Easy" ) :
                           current[line]->has_flag( "BLIND_HARD" ) ? _( "Hard" ) :
                           _( "Impossible" ) );
                ypos += current[line]->print_items( w_data, ypos, 30, col, ( batch ) ? line + 1 : 1 );
            }

            //color needs to be preserved in case part of the previous page was cut off
            nc_color stored_color = col;
            if( display_mode > 2 ) {
                stored_color = rotated_color;
            } else {
                rotated_color = col;
            }
            int components_printed = 0;
            for( size_t i = static_cast<size_t>( componentPrintOffset );
                 i < component_print_buffer.size(); i++ ) {
                if( ypos >= componentPrintHeight ) {
                    break;
                }

                components_printed++;
                print_colored_text( w_data, ypos++, 30, stored_color, col, component_print_buffer[i] );
            }

            if( ypos >= componentPrintHeight &&
                component_print_buffer.size() > static_cast<size_t>( components_printed ) ) {
                mvwprintz( w_data, ypos++, 30, col, _( "v (more)" ) );
                rotated_color = stored_color;
            }

            if( isWide ) {
                if( last_recipe != current[line] ) {
                    last_recipe = current[line];
                    tmp = current[line]->create_result();
                    tmp.info( true, thisItem );
                }
                draw_item_info( w_iteminfo, tmp.tname(), tmp.type_name(), thisItem, dummy,
                                scroll_pos, true, true, true, false, true );
            }
        }

        draw_scrollbar( w_data, line, dataLines, recmax, 0 );
        wrefresh( w_data );

        if( isWide ) {
            wrefresh( w_iteminfo );
        }

        const std::string action = ctxt.handle_input();
        if( action == "CYCLE_MODE" ) {
            display_mode = display_mode + 1;
            if( display_mode <= 0 ) {
                display_mode = 0;
            }
        } else if( action == "LEFT" ) {
            subtab.prev();
            redraw = true;
        } else if( action == "SCROLL_UP" ) {
            scroll_pos--;
        } else if( action == "SCROLL_DOWN" ) {
            scroll_pos++;
        } else if( action == "PREV_TAB" ) {
            tab.prev();
            subtab = list_circularizer<std::string>( craft_subcat_list[tab.cur()] );//default ALL
            redraw = true;
        } else if( action == "RIGHT" ) {
            subtab.next();
            redraw = true;
        } else if( action == "NEXT_TAB" ) {
            tab.next();
            subtab = list_circularizer<std::string>( craft_subcat_list[tab.cur()] );//default ALL
            redraw = true;
        } else if( action == "DOWN" ) {
            line++;
        } else if( action == "UP" ) {
            line--;
        } else if( action == "CONFIRM" ) {
            if( available.empty() || !available[line] ) {
                popup( _( "You can't do that!" ) );
            } else if( !current[line]->check_eligible_containers_for_crafting( ( batch ) ? line + 1 : 1 ) ) {
                ; // popup is already inside check
            } else {
                chosen = current[line];
                batch_size = ( batch ) ? line + 1 : 1;
                done = true;
            }
        } else if( action == "HELP_RECIPE" ) {
            if( current.empty() ) {
                popup( _( "Nothing selected!" ) );
                redraw = true;
                continue;
            }
            tmp = current[line]->create_result();

            full_screen_popup( "%s\n%s", tmp.type_name( 1 ).c_str(),  tmp.info( true ).c_str() );
            redraw = true;
            keepline = true;
        } else if( action == "FILTER" ) {
            filterstring = string_input_popup( _( "Search:" ), 85, filterstring,
                                               _( "Special prefixes for requirements:\n"
                                                  "  [t] search tools\n"
                                                  "  [c] search components\n"
                                                  "  [q] search qualities\n"
                                                  "  [s] search skills\n"
                                                  "Special prefixes for results:\n"
                                                  "  [Q] search qualities\n"
                                                  "Examples:\n"
                                                  "  t:soldering iron\n"
                                                  "  c:two by four\n"
                                                  "  q:metal sawing\n"
                                                  "  s:cooking\n"
                                                  "  Q:fine bolt turning"
                                                ) );
            redraw = true;
        } else if( action == "QUIT" ) {
            chosen = nullptr;
            done = true;
        } else if( action == "RESET_FILTER" ) {
            filterstring = "";
            redraw = true;
        } else if( action == "CYCLE_BATCH" ) {
            if( current.empty() ) {
                popup( _( "Nothing selected!" ) );
                redraw = true;
                continue;
            }
            batch = !batch;
            if( batch ) {
                batch_line = line;
                chosen = current[batch_line];
            } else {
                line = batch_line;
                keepline = true;
            }
            redraw = true;
        }
        if( line < 0 ) {
            line = current.size() - 1;
        } else if( line >= ( int )current.size() ) {
            line = 0;
        }
    } while( !done );

    return chosen;
}
robot_finds_kitten::robot_finds_kitten( const catacurses::window &w )
{
#ifdef __ANDROID__
    input_context ctxt( "IUSE_SOFTWARE_KITTEN" );
#endif

    ret = false;
    char ktile[83] =
        "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#&()*+./:;=?![]{|}y";
    int used_messages[MAXMESSAGES];

    rfkLINES = 20;
    rfkCOLS = 60;

    const int numbogus = 20;
    nummessages = 201;
    empty.x = -1;
    empty.y = -1;
    empty.color = nc_color();
    empty.character = ' ';
    for( int c = 0; c < rfkCOLS; c++ ) {
        for( int c2 = 0; c2 < rfkLINES; c2++ ) {
            rfkscreen[c][c2] = EMPTY;
        }
    }
    /* Create an array to ensure we don't get duplicate messages. */
    for( int c = 0; c < nummessages; c++ ) {
        used_messages[c] = 0;
        bogus_messages[c] = 0;
        bogus[c] = empty;
    }
    /* Now we initialize the various game OBJECTs.
       * Assign a position to the player. */
    robot.x = rand() % rfkCOLS;
    robot.y = rand() % ( rfkLINES - 3 ) + 3;
    robot.character = '#';
    robot.color = c_white;
    rfkscreen[robot.x][robot.y] = ROBOT;

    /* Assign the kitten a unique position. */
    do {
        kitten.x = rand() % rfkCOLS;
        kitten.y = rand() % ( rfkLINES - 3 ) + 3;
    } while( rfkscreen[kitten.x][kitten.y] != EMPTY );

    /* Assign the kitten a character and a color. */
    do {
        kitten.character = ktile[rand() % 82];
    } while( kitten.character == '#' || kitten.character == ' ' );

    do {
        kitten.color = all_colors.get_random();
    } while( kitten.color == c_black );

    rfkscreen[kitten.x][kitten.y] = KITTEN;

    /* Now, initialize non-kitten OBJECTs. */
    for( int c = 0; c < numbogus; c++ ) {
        /* Assign a unique position. */
        do {
            bogus[c].x = rand() % rfkCOLS;
            bogus[c].y = ( rand() % ( rfkLINES - 3 ) ) + 3;
        } while( rfkscreen[bogus[c].x][bogus[c].y] != EMPTY );
        rfkscreen[bogus[c].x][bogus[c].y] = c + 2;

        /* Assign a character. */
        do {
            bogus[c].character = ktile[rand() % 82];
        } while( bogus[c].character == '#' || bogus[c].character == ' ' );

        do {
            bogus[c].color = all_colors.get_random();
        } while( bogus[c].color == c_black );

        /* Assign a unique message. */
        int index = 0;
        do {
            index = rand() % nummessages;
        } while( used_messages[index] != 0 );
        bogus_messages[c] = index;
        used_messages[index] = 1;
    }

    instructions( w );

    werase( w );
    mvwprintz( w, 0, 0, c_white, _( "robotfindskitten v22July2008 - press q to quit." ) );
    for( int c = 0; c < rfkCOLS; c++ ) {
        mvwputch( w, 2, c, BORDER_COLOR, '_' );
    }
    wmove( w, kitten.y, kitten.x );
    draw_kitten( w );

    for( int c = 0; c < numbogus; c++ ) {
        mvwputch( w, bogus[c].y, bogus[c].x, bogus[c].color, bogus[c].character );
    }

    wmove( w, robot.y, robot.x );
    draw_robot( w );
    int old_x = robot.x;
    int old_y = robot.y;

    wrefresh( w );
    /* Now the fun begins. */
    int input = inp_mngr.get_input_event().get_first_input(); // @todo: use input context

    while( input != 'q' && input != 'Q' && input != KEY_ESCAPE ) {
        process_input( input, w );
        if( ret ) {
            break;
        }
        /* Redraw robot, where available */
        if( !( old_x == robot.x && old_y == robot.y ) ) {
            wmove( w, old_y, old_x );
            wputch( w, c_white, ' ' );
            wmove( w, robot.y, robot.x );
            draw_robot( w );
            rfkscreen[old_x][old_y] = EMPTY;
            rfkscreen[robot.x][robot.y] = ROBOT;
            old_x = robot.x;
            old_y = robot.y;
        }
        wrefresh( w );
        // TODO: use input context / rewrite loop so this is only called at one place
        input = inp_mngr.get_input_event().get_first_input();
    }
}
Esempio n. 26
0
//--------------------------------------------------------------------------------------------
bool tile_dictionary_load_vfs( const char * filename, tile_dictionary_t * pdict, int max_dict_size )
{
    /// @author ZZ
    /// @details This function loads fan types for the terrain

    Uint32 cnt, entry, vertices, commandsize;
    int fantype_count, fantype_offset, fantype;
    int command_count, command;
    int definition_count;
    int itmp;
    float ftmp;

    if ( NULL == pdict ) return false;

    // "delete" the old list
    *pdict = tile_dictionary_t();

    if ( !VALID_CSTR( filename ) ) return false;

    // handle default parameters
    if ( max_dict_size < 0 )
    {
        max_dict_size = MAP_FAN_TYPE_MAX;
    }

    // Try to open a context.
    ReadContext ctxt(filename);
    if (!ctxt.ensureOpen()) {
		Log::get().error("unable to load tile definitions file `%s`\n", filename);
        return false;
    }

    fantype_count    = vfs_get_next_int(ctxt);
    fantype_offset   = 2 * std::pow( 2.0f, std::floor( std::log( fantype_count ) / std::log( 2.0f ) ) );
    definition_count = 2 * fantype_offset;

    if ( definition_count > MAP_FAN_TYPE_MAX )
    {
		Log::get().error( "%s - tile dictionary has too many tile definitions (%d/%d).\n", __FUNCTION__, definition_count, MAP_FAN_TYPE_MAX );
        return false;
    }
    else if ( definition_count > max_dict_size )
    {
		Log::get().error( "%s - the number of tile difinitions has exceeded the requested number (%d/%d).\n", __FUNCTION__, definition_count, max_dict_size );
        return false;
    }

    pdict->offset    = fantype_offset;
    pdict->def_count = definition_count;

    for ( fantype = 0; fantype < fantype_count; fantype++ )
    {
        tile_definition_t& pdef_sml = pdict->def_lst[fantype];
        tile_definition_t& pdef_big = pdict->def_lst[fantype + fantype_offset];

        vertices = vfs_get_next_int(ctxt);

        pdef_sml.numvertices = vertices;
        pdef_big.numvertices = vertices;  // Dupe

        for ( cnt = 0; cnt < vertices; cnt++ )
        {
            itmp = vfs_get_next_int(ctxt);
            pdef_sml.ref[cnt]    = itmp;
            pdef_sml.grid_ix[cnt] = itmp & 3;
            pdef_sml.grid_iy[cnt] = ( itmp >> 2 ) & 3;

            ftmp = vfs_get_next_float(ctxt);
            pdef_sml.u[cnt] = ftmp;

            ftmp = vfs_get_next_float(ctxt);
            pdef_sml.v[cnt] = ftmp;

            // Dupe
            pdef_big.ref[cnt]    = pdef_sml.ref[cnt];
            pdef_big.grid_ix[cnt] = pdef_sml.grid_ix[cnt];
            pdef_big.grid_iy[cnt] = pdef_sml.grid_iy[cnt];
            pdef_big.u[cnt]      = pdef_sml.u[cnt];
            pdef_big.v[cnt]      = pdef_sml.v[cnt];
        }

        command_count = vfs_get_next_int(ctxt);
        pdef_sml.command_count = command_count;
        pdef_big.command_count = command_count;  // Dupe

        for ( entry = 0, command = 0; command < command_count; command++ )
        {
            commandsize = vfs_get_next_int(ctxt);
            pdef_sml.command_entries[command] = commandsize;
            pdef_big.command_entries[command] = commandsize;  // Dupe

            for ( cnt = 0; cnt < commandsize; cnt++ )
            {
                itmp = vfs_get_next_int(ctxt);
                pdef_sml.command_verts[entry] = itmp;
                pdef_big.command_verts[entry] = itmp;  // Dupe

                entry++;
            }
        }
    }

    pdict->loaded = true;

    tile_dictionary_finalize( pdict );

    return true;
}
Esempio n. 27
0
void faction_manager::display() const
{
    std::vector<const faction *> valfac; // Factions that we know of.
    for( const faction &elem : factions ) {
        if( elem.known_by_u ) {
            valfac.push_back( &elem );
        }
    }
    if( valfac.empty() ) { // We don't know of any factions!
        popup( _( "You don't know of any factions.  Press Spacebar..." ) );
        return;
    }

    catacurses::window w_list = catacurses::newwin( FULL_SCREEN_HEIGHT, FULL_SCREEN_WIDTH,
                                ( ( TERMY > FULL_SCREEN_HEIGHT ) ? ( TERMY - FULL_SCREEN_HEIGHT ) / 2 : 0 ),
                                ( TERMX > FULL_SCREEN_WIDTH ) ? ( TERMX - FULL_SCREEN_WIDTH ) / 2 : 0 );
    catacurses::window w_info = catacurses::newwin( FULL_SCREEN_HEIGHT - 2,
                                FULL_SCREEN_WIDTH - 1 - MAX_FAC_NAME_SIZE,
                                1 + ( ( TERMY > FULL_SCREEN_HEIGHT ) ? ( TERMY - FULL_SCREEN_HEIGHT ) / 2 : 0 ),
                                MAX_FAC_NAME_SIZE + ( ( TERMX > FULL_SCREEN_WIDTH ) ? ( TERMX - FULL_SCREEN_WIDTH ) / 2 : 0 ) );

    const int maxlength = FULL_SCREEN_WIDTH - 1 - MAX_FAC_NAME_SIZE;
    size_t sel = 0;
    bool redraw = true;

    input_context ctxt( "FACTIONS" );
    ctxt.register_action( "UP", _( "Move cursor up" ) );
    ctxt.register_action( "DOWN", _( "Move cursor down" ) );
    ctxt.register_action( "QUIT" );
    ctxt.register_action( "HELP_KEYBINDINGS" );
    while( true ) {
        const faction &cur_frac = *valfac[sel];
        if( redraw ) {
            werase( w_list );
            draw_border( w_list );
            mvwprintz( w_list, 1, 1, c_white, _( "FACTIONS:" ) );
            for( size_t i = 0; i < valfac.size(); i++ ) {
                nc_color col = ( i == sel ? h_white : c_white );
                mvwprintz( w_list, i + 2, 1, col, _( valfac[i]->name.c_str() ) );
            }
            wrefresh( w_list );
            werase( w_info );
            mvwprintz( w_info, 0, 0, c_white, _( "Ranking:           %s" ),
                       fac_ranking_text( cur_frac.likes_u ) );
            mvwprintz( w_info, 1, 0, c_white, _( "Respect:           %s" ),
                       fac_respect_text( cur_frac.respects_u ) );
            mvwprintz( w_info, 2, 0, c_white, _( "Wealth:            %s" ), fac_wealth_text( cur_frac.wealth,
                       cur_frac.size ) );
            mvwprintz( w_info, 3, 0, c_white, _( "Food Supply:       %s" ),
                       fac_food_supply_text( cur_frac.food_supply, cur_frac.size ) );
            mvwprintz( w_info, 4, 0, c_white, _( "Combat Ability:    %s" ),
                       fac_combat_ability_text( cur_frac.combat_ability ) );
            fold_and_print( w_info, 6, 0, maxlength, c_white, cur_frac.describe() );
            wrefresh( w_info );
            redraw = false;
        }
        const std::string action = ctxt.handle_input();
        if( action == "DOWN" ) {
            mvwprintz( w_list, sel + 2, 1, c_white, cur_frac.name );
            sel = ( sel + 1 ) % valfac.size();
            redraw = true;
        } else if( action == "UP" ) {
            mvwprintz( w_list, sel + 2, 1, c_white, cur_frac.name );
            sel = ( sel + valfac.size() - 1 ) % valfac.size();
            redraw = true;
        } else if( action == "HELP_KEYBINDINGS" ) {
            redraw = true;
        } else if( action == "QUIT" ) {
            break;
        } else if( action == "CONFIRM" ) {
            break;
        }
    }
}
Esempio n. 28
0
int worldfactory::show_worldgen_tab_confirm(WINDOW *win, WORLDPTR world)
{
    const int iTooltipHeight = 1;
    const int iContentHeight = FULL_SCREEN_HEIGHT - 3 - iTooltipHeight;

    const int iOffsetX = (TERMX > FULL_SCREEN_WIDTH) ? (TERMX - FULL_SCREEN_WIDTH) / 2 : 0;
    const int iOffsetY = (TERMY > FULL_SCREEN_HEIGHT) ? (TERMY - FULL_SCREEN_HEIGHT) / 2 : 0;

    WINDOW *w_confirmation = newwin(iContentHeight, FULL_SCREEN_WIDTH - 2,
                                    iTooltipHeight + 2 + iOffsetY, 1 + iOffsetX);

    unsigned namebar_y = 1;
    unsigned namebar_x = 3 + utf8_width(_("World Name:"));

    int line = 1;
    bool noname = false;
    input_context ctxt("WORLDGEN_CONFIRM_DIALOG");
    // Disabled because it conflicts with the "pick random world name" option,
    // feel free to enable it and change its keybinding in keybindings.json
    // ctxt.register_action("HELP_KEYBINDINGS");
    ctxt.register_action("QUIT");
    ctxt.register_action("ANY_INPUT");
    ctxt.register_action("NEXT_TAB");
    ctxt.register_action("PREV_TAB");
    ctxt.register_action("PICK_RANDOM_WORLDNAME");

    std::string worldname = world->world_name;
    do {
        mvwprintz(w_confirmation, namebar_y, 2, c_white, _("World Name:"));
        mvwprintz(w_confirmation, namebar_y, namebar_x, c_ltgray, "______________________________");
        fold_and_print(w_confirmation, 3, 2, 76, c_ltgray,
                       _("Press <color_yellow>?</color> to pick a random name for your world."));
        fold_and_print(w_confirmation, FULL_SCREEN_HEIGHT / 2 - 2, 2, 76, c_ltgray, _("\
Press <color_yellow>></color> when you are satisfied with the world as it is and are ready \
to continue, or <color_yellow><</color> to go back and review your world."));
        if (!noname) {
            mvwprintz(w_confirmation, namebar_y, namebar_x, c_ltgray, "%s", worldname.c_str());
            if (line == 1) {
                wprintz(w_confirmation, h_ltgray, "_");
            }
        }
        if (noname) {
            mvwprintz(w_confirmation, namebar_y, namebar_x, c_ltgray, "______________________________");
            noname = false;
        }

        wrefresh(win);
        wrefresh(w_confirmation);
        refresh();

        const std::string action = ctxt.handle_input();
        if (action == "NEXT_TAB") {
            if (worldname.empty()) {
                mvwprintz(w_confirmation, namebar_y, namebar_x, h_ltgray, _("______NO NAME ENTERED!!!!_____"));
                noname = true;
                wrefresh(w_confirmation);
                if (!query_yn(_("Are you SURE you're finished? World name will be randomly generated."))) {
                    continue;
                } else {
                    world->world_name = pick_random_name();
                    if (!valid_worldname(world->world_name)) {
                        continue;
                    }
                    return 1;
                }
            } else if (query_yn(_("Are you SURE you're finished?")) && valid_worldname(worldname)) {
                world->world_name = worldname;
                werase(w_confirmation);
                delwin(w_confirmation);

                return 1;
            } else {
                continue;
            }
        } else if (action == "PREV_TAB") {
            world->world_name = worldname;
            werase(w_confirmation);
            delwin(w_confirmation);
            return -1;
        } else if (action == "PICK_RANDOM_WORLDNAME") {
            mvwprintz(w_confirmation, namebar_y, namebar_x, c_ltgray, "______________________________");
            world->world_name = worldname = pick_random_name();
        } else if (action == "QUIT") {
            world->world_name =
                worldname; // cache the current worldname just in case they say No to the exit query
            return -999;
        } else if (action == "ANY_INPUT") {
            const long ch = ctxt.get_raw_input().get_first_input();
            switch (line) {
                case 1:
                    if (ch == KEY_BACKSPACE || ch == 127) {
                        if (!worldname.empty()) {
                            //erase utf8 character TODO: make a function
                            while(!worldname.empty() &&
                                  ((unsigned char)worldname[worldname.size() - 1]) >= 128 &&
                                  ((unsigned char)worldname[(int)worldname.size() - 1]) <= 191) {
                                worldname.erase(worldname.size() - 1);
                            }
                            worldname.erase(worldname.size() - 1);
                            mvwprintz(w_confirmation, namebar_y, namebar_x, c_ltgray,
                                      "______________________________ ");
                            mvwprintz(w_confirmation, namebar_y, namebar_x, c_ltgray,
                                      "%s", worldname.c_str());
                            wprintz(w_confirmation, h_ltgray, "_");
                        }
                    } else if (is_char_allowed(ch) && utf8_width(worldname.c_str()) < 30) {
                        worldname.push_back(ch);
                    } else if(ch == KEY_F(2)) {
                        std::string tmp = get_input_string_from_file();
                        int tmplen = utf8_width(tmp.c_str());
                        if(tmplen > 0 && tmplen + utf8_width(worldname.c_str()) < 30) {
                            worldname.append(tmp);
                        }
                    }
                    //experimental unicode input
                    else if(ch > 127) {
                        std::string tmp = utf32_to_utf8(ch);
                        int tmplen = utf8_width(tmp.c_str());
                        if(tmplen > 0 && tmplen + utf8_width(worldname.c_str()) < 30) {
                            worldname.append(tmp);
                        }
                    }
                    break;
            }
        }
    } while (true);

    return 0;
}
Esempio n. 29
0
void auto_pickup::show( const std::string &custom_name, bool is_autopickup )
{
    save_reset_changes(false);

    const int iHeaderHeight = 4;
    const int iContentHeight = FULL_SCREEN_HEIGHT - 2 - iHeaderHeight;

    const int iOffsetX = (TERMX > FULL_SCREEN_WIDTH) ? (TERMX - FULL_SCREEN_WIDTH) / 2 : 0;
    const int iOffsetY = (TERMY > FULL_SCREEN_HEIGHT) ? (TERMY - FULL_SCREEN_HEIGHT) / 2 : 0;

    std::map<int, bool> mapLines;
    mapLines[4] = true;
    mapLines[50] = true;
    mapLines[54] = true;

    const int iTotalCols = mapLines.size() - 1;

    WINDOW *w_help = newwin((FULL_SCREEN_HEIGHT / 2) - 2, FULL_SCREEN_WIDTH * 3 / 4,
                                        7 + iOffsetY + (FULL_SCREEN_HEIGHT / 2) / 2, iOffsetX + 19 / 2);
    WINDOW_PTR w_helpptr( w_help );

    WINDOW *w_border = newwin(FULL_SCREEN_HEIGHT, FULL_SCREEN_WIDTH, iOffsetY, iOffsetX);
    WINDOW_PTR w_borderptr( w_border );
    WINDOW *w_header = newwin(iHeaderHeight, FULL_SCREEN_WIDTH - 2, 1 + iOffsetY,
                                          1 + iOffsetX);
    WINDOW_PTR w_headerptr( w_header );
    WINDOW *w = newwin(iContentHeight, FULL_SCREEN_WIDTH - 2, iHeaderHeight + 1 + iOffsetY,
                                   1 + iOffsetX);
    WINDOW_PTR wptr( w );

    draw_border(w_border);
    mvwputch(w_border, 3,  0, c_ltgray, LINE_XXXO); // |-
    mvwputch(w_border, 3, 79, c_ltgray, LINE_XOXX); // -|

    for( auto &mapLine : mapLines ) {
        mvwputch( w_border, FULL_SCREEN_HEIGHT - 1, mapLine.first + 1, c_ltgray,
                  LINE_XXOX ); // _|_
    }

    mvwprintz(w_border, 0, 29, c_ltred, custom_name.c_str() );
    wrefresh(w_border);

    int tmpx = 0;
    tmpx += shortcut_print(w_header, 0, tmpx, c_white, c_ltgreen, _("<A>dd")) + 2;
    tmpx += shortcut_print(w_header, 0, tmpx, c_white, c_ltgreen, _("<R>emove")) + 2;
    tmpx += shortcut_print(w_header, 0, tmpx, c_white, c_ltgreen, _("<C>opy")) + 2;
    tmpx += shortcut_print(w_header, 0, tmpx, c_white, c_ltgreen, _("<M>ove")) + 2;
    tmpx += shortcut_print(w_header, 0, tmpx, c_white, c_ltgreen, _("<E>nable")) + 2;
    tmpx += shortcut_print(w_header, 0, tmpx, c_white, c_ltgreen, _("<D>isable")) + 2;
    shortcut_print(w_header, 0, tmpx, c_white, c_ltgreen, _("<T>est"));
    tmpx = 0;
    tmpx += shortcut_print(w_header, 1, tmpx, c_white, c_ltgreen,
                           _("<+-> Move up/down")) + 2;
    tmpx += shortcut_print(w_header, 1, tmpx, c_white, c_ltgreen, _("<Enter>-Edit")) + 2;
    shortcut_print(w_header, 1, tmpx, c_white, c_ltgreen, _("<Tab>-Switch Page"));

    for (int i = 0; i < 78; i++) {
        if (mapLines[i]) {
            mvwputch(w_header, 2, i, c_ltgray, LINE_OXXX);
            mvwputch(w_header, 3, i, c_ltgray, LINE_XOXO);
        } else {
            mvwputch(w_header, 2, i, c_ltgray, LINE_OXOX); // Draw line under header
        }
    }

    mvwprintz(w_header, 3, 1, c_white, "#");
    mvwprintz(w_header, 3, 8, c_white, _("Rules"));
    mvwprintz(w_header, 3, 51, c_white, _("I/E"));

    wrefresh(w_header);

    int iCurrentPage = 1;
    int iCurrentLine = 0;
    int iCurrentCol = 1;
    int iStartPos = 0;
    bool bStuffChanged = false;
    input_context ctxt("AUTO_PICKUP");
    ctxt.register_cardinal();
    ctxt.register_action("CONFIRM");
    ctxt.register_action("QUIT");
    ctxt.register_action("NEXT_TAB");
    ctxt.register_action("PREV_TAB");
    ctxt.register_action("ADD_RULE");
    ctxt.register_action("REMOVE_RULE");
    ctxt.register_action("COPY_RULE");
    ctxt.register_action("ENABLE_RULE");
    ctxt.register_action("DISABLE_RULE");
    ctxt.register_action("MOVE_RULE_UP");
    ctxt.register_action("MOVE_RULE_DOWN");
    ctxt.register_action("TEST_RULE");
    ctxt.register_action("HELP_KEYBINDINGS");

    if( is_autopickup ) {
        ctxt.register_action("SWITCH_AUTO_PICKUP_OPTION");
        ctxt.register_action("SWAP_RULE_GLOBAL_CHAR");
    }

    std::ostringstream sTemp;

    while(true) {
        int locx = 17;
        locx += shortcut_print(w_header, 2, locx, c_white,
                               (iCurrentPage == 1) ? hilite(c_white) : c_white, _("[<Global>]")) + 1;
        shortcut_print(w_header, 2, locx, c_white,
                       (iCurrentPage == 2) ? hilite(c_white) : c_white, _("[<Character>]"));

        locx = 55;
        mvwprintz(w_header, 0, locx, c_white, _("Auto pickup enabled:"));
        locx += shortcut_print(w_header, 1, locx,
                               ((OPTIONS["AUTO_PICKUP"]) ? c_ltgreen : c_ltred), c_white,
                               ((OPTIONS["AUTO_PICKUP"]) ? _("True") : _("False")));
        locx += shortcut_print(w_header, 1, locx, c_white, c_ltgreen, "  ");
        locx += shortcut_print(w_header, 1, locx, c_white, c_ltgreen, _("<S>witch"));
        shortcut_print(w_header, 1, locx, c_white, c_ltgreen, "  ");

        wrefresh(w_header);

        // Clear the lines
        for (int i = 0; i < iContentHeight; i++) {
            for (int j = 0; j < 79; j++) {
                if (mapLines[j]) {
                    mvwputch(w, i, j, c_ltgray, LINE_XOXO);
                } else {
                    mvwputch(w, i, j, c_black, ' ');
                }
            }
        }

        const bool currentPageNonEmpty = !vRules[iCurrentPage].empty();

        if (iCurrentPage == 2 && g->u.name == "") {
            vRules[2].clear();
            mvwprintz(w, 8, 15, c_white,
                      _("Please load a character first to use this page!"));
        }

        draw_scrollbar(w_border, iCurrentLine, iContentHeight,
                       vRules[iCurrentPage].size(), 5);
        wrefresh(w_border);

        calcStartPos(iStartPos, iCurrentLine, iContentHeight,
                     vRules[iCurrentPage].size());

        // display auto pickup
        for (int i = iStartPos; i < (int)vRules[iCurrentPage].size(); i++) {
            if (i >= iStartPos &&
                i < iStartPos + ((iContentHeight > (int)vRules[iCurrentPage].size()) ?
                                 (int)vRules[iCurrentPage].size() : iContentHeight)) {
                nc_color cLineColor = (vRules[iCurrentPage][i].bActive) ?
                                      c_white : c_ltgray;

                sTemp.str("");
                sTemp << i + 1;
                mvwprintz(w, i - iStartPos, 1, cLineColor, "%s", sTemp.str().c_str());
                mvwprintz(w, i - iStartPos, 5, cLineColor, "");

                if (iCurrentLine == i) {
                    wprintz(w, c_yellow, ">> ");
                } else {
                    wprintz(w, c_yellow, "   ");
                }

                wprintz(w, (iCurrentLine == i &&
                                        iCurrentCol == 1) ? hilite(cLineColor) : cLineColor, "%s",
                        ((vRules[iCurrentPage][i].sRule == "") ? _("<empty rule>") :
                         vRules[iCurrentPage][i].sRule).c_str());

                mvwprintz(w, i - iStartPos, 52, (iCurrentLine == i &&
                          iCurrentCol == 2) ? hilite(cLineColor) : cLineColor, "%s",
                          ((vRules[iCurrentPage][i].bExclude) ? rm_prefix(_("<Exclude>E")).c_str() : rm_prefix(
                               _("<Include>I")).c_str()));
            }
        }

        wrefresh(w);

        const std::string action = ctxt.handle_input();

        if (action == "NEXT_TAB") {
            iCurrentPage++;
            if (iCurrentPage > 2) {
                iCurrentPage = 1;
                iCurrentLine = 0;
            }
        } else if (action == "PREV_TAB") {
            iCurrentPage--;
            if (iCurrentPage < 1) {
                iCurrentPage = 2;
                iCurrentLine = 0;
            }
        } else if (action == "QUIT") {
            break;
        } else if (iCurrentPage == 2 && g->u.name.empty()) {
            //Only allow loaded games to use the char sheet
        } else if (action == "DOWN") {
            iCurrentLine++;
            iCurrentCol = 1;
            if (iCurrentLine >= (int)vRules[iCurrentPage].size()) {
                iCurrentLine = 0;
            }
        } else if (action == "UP") {
            iCurrentLine--;
            iCurrentCol = 1;
            if (iCurrentLine < 0) {
                iCurrentLine = vRules[iCurrentPage].size() - 1;
            }
        } else if (action == "ADD_RULE") {
            bStuffChanged = true;
            vRules[iCurrentPage].push_back(cRules("", true, false));
            iCurrentLine = vRules[iCurrentPage].size() - 1;
        } else if (action == "REMOVE_RULE" && currentPageNonEmpty) {
            bStuffChanged = true;
            vRules[iCurrentPage].erase(vRules[iCurrentPage].begin() + iCurrentLine);
            if (iCurrentLine > (int)vRules[iCurrentPage].size() - 1) {
                iCurrentLine--;
            }
            if(iCurrentLine < 0){
                iCurrentLine = 0;
            }
        } else if (action == "COPY_RULE" && currentPageNonEmpty) {
            bStuffChanged = true;
            vRules[iCurrentPage].push_back(cRules(
                        vRules[iCurrentPage][iCurrentLine].sRule,
                        vRules[iCurrentPage][iCurrentLine].bActive,
                        vRules[iCurrentPage][iCurrentLine].bExclude));
            iCurrentLine = vRules[iCurrentPage].size() - 1;
        } else if (action == "SWAP_RULE_GLOBAL_CHAR" && currentPageNonEmpty) {
            if ((iCurrentPage == 1 && g->u.name != "") || iCurrentPage == 2) {
                bStuffChanged = true;
                //copy over
                vRules[(iCurrentPage == 1) ? 2 : 1].push_back(cRules(
                            vRules[iCurrentPage][iCurrentLine].sRule,
                            vRules[iCurrentPage][iCurrentLine].bActive,
                            vRules[iCurrentPage][iCurrentLine].bExclude));

                //remove old
                vRules[iCurrentPage].erase(vRules[iCurrentPage].begin() + iCurrentLine);
                iCurrentLine = vRules[(iCurrentPage == 1) ? 2 : 1].size() - 1;
                iCurrentPage = (iCurrentPage == 1) ? 2 : 1;
            }
        } else if (action == "CONFIRM" && currentPageNonEmpty) {
            bStuffChanged = true;
            if (iCurrentCol == 1) {
                fold_and_print(w_help, 1, 1, 999, c_white,
                               _(
                                   "* is used as a Wildcard. A few Examples:\n"
                                   "\n"
                                   "wooden arrow    matches the itemname exactly\n"
                                   "wooden ar*      matches items beginning with wood ar\n"
                                   "*rrow           matches items ending with rrow\n"
                                   "*avy fle*fi*arrow     multiple * are allowed\n"
                                   "heAVY*woOD*arrOW      case insensitive search\n"
                                   "")
                              );

                draw_border(w_help);
                wrefresh(w_help);
                vRules[iCurrentPage][iCurrentLine].sRule = trim_rule(string_input_popup(_("Pickup Rule:"),
                        30, vRules[iCurrentPage][iCurrentLine].sRule));
            } else if (iCurrentCol == 2) {
                vRules[iCurrentPage][iCurrentLine].bExclude =
                    !vRules[iCurrentPage][iCurrentLine].bExclude;
            }
        } else if (action == "ENABLE_RULE" && currentPageNonEmpty) {
            bStuffChanged = true;
            vRules[iCurrentPage][iCurrentLine].bActive = true;
        } else if (action == "DISABLE_RULE" && currentPageNonEmpty) {
            bStuffChanged = true;
            vRules[iCurrentPage][iCurrentLine].bActive = false;
        } else if (action == "LEFT") {
            iCurrentCol--;
            if (iCurrentCol < 1) {
                iCurrentCol = iTotalCols;
            }
        } else if (action == "RIGHT") {
            iCurrentCol++;
            if (iCurrentCol > iTotalCols) {
                iCurrentCol = 1;
            }
        } else if (action == "MOVE_RULE_UP" && currentPageNonEmpty) {
            bStuffChanged = true;
            if (iCurrentLine < (int)vRules[iCurrentPage].size() - 1) {
                std::swap(vRules[iCurrentPage][iCurrentLine],
                          vRules[iCurrentPage][iCurrentLine + 1]);
                iCurrentLine++;
                iCurrentCol = 1;
            }
        } else if (action == "MOVE_RULE_DOWN" && currentPageNonEmpty) {
            bStuffChanged = true;
            if (iCurrentLine > 0) {
                std::swap(vRules[iCurrentPage][iCurrentLine],
                          vRules[iCurrentPage][iCurrentLine - 1]);
                iCurrentLine--;
                iCurrentCol = 1;
            }
        } else if (action == "TEST_RULE" && currentPageNonEmpty) {
            test_pattern(iCurrentPage, iCurrentLine);
        } else if (action == "SWITCH_OPTION") {
            // @todo Now that NPCs use this function, it could be used for them too
            OPTIONS["AUTO_PICKUP"].setNext();
            get_options().save();
        }
    }

    if( !bStuffChanged ) {
        return;
    }

    if( query_yn( _("Save changes?") ) ) {
        // NPC pickup rules don't need to be saved explicitly
        if( is_autopickup ) {
            save( false );
            if( g->u.name != "" ) {
                save(true);
            }
        } else {
            merge_vector();
            create_rules();
        }
    } else {
        save_reset_changes( true );
    }
}
Esempio n. 30
0
void Messages::display_messages()
{
    WINDOW *w = newwin(FULL_SCREEN_HEIGHT, FULL_SCREEN_WIDTH,
                       (TERMY > FULL_SCREEN_HEIGHT) ? (TERMY - FULL_SCREEN_HEIGHT) / 2 : 0,
                       (TERMX > FULL_SCREEN_WIDTH) ? (TERMX - FULL_SCREEN_WIDTH) / 2 : 0);

    size_t offset = 0;
    const int maxlength = FULL_SCREEN_WIDTH - 2 - 1;
    const int bottom = FULL_SCREEN_HEIGHT - 2;
    input_context ctxt("MESSAGE_LOG");
    ctxt.register_action("UP", _("Scroll up"));
    ctxt.register_action("DOWN", _("Scroll down"));
    ctxt.register_action("QUIT");
    ctxt.register_action("HELP_KEYBINDINGS");
    while(true) {
        werase(w);
        draw_border(w);
        mvwprintz(w, FULL_SCREEN_HEIGHT - 1, 32, c_red, _("Press %s to return"),
                  ctxt.get_desc("QUIT").c_str());

        draw_scrollbar(w, offset, FULL_SCREEN_HEIGHT - 2, size(), 1);

        int line = 1;
        int lasttime = -1;
        for (size_t i = offset; i < size() && line <= bottom; i++) {
            const game_message &m = player_messages.messages[size() - i - 1];
            const std::string mstr = m.get_with_count();
            const nc_color col = m.get_color();
            calendar timepassed = calendar::turn - m.turn;
            if (int(timepassed) > lasttime) {
                mvwprintz(w, line, 3, c_ltblue, _("%s ago:"),
                        timepassed.textify_period().c_str());
                line++;
                lasttime = int(timepassed);
            }
            std::vector<std::string> folded = foldstring(mstr, maxlength);
            for (size_t j = 0; j < folded.size() && line <= bottom; j++, line++) {
                mvwprintz(w, line, 1, col, "%s", folded[j].c_str());
            }
        }

        if (offset + 1 < size()) {
            mvwprintz(w, FULL_SCREEN_HEIGHT - 1, 5, c_magenta, "vvv");
        }
        if (offset > 0) {
            mvwprintz(w, FULL_SCREEN_HEIGHT - 1, FULL_SCREEN_WIDTH - 6, c_magenta, "^^^");
        }
        wrefresh(w);

        const std::string action = ctxt.handle_input();
        if (action == "DOWN" && offset + 1 < size()) {
            offset++;
        } else if (action == "UP" && offset > 0) {
            offset--;
        } else if (action == "QUIT") {
            break;
        }
    }
    player_messages.curmes = int(calendar::turn);
    werase(w);
    delwin(w);
}