Ejemplo n.º 1
0
void game::construction_menu()
{
 WINDOW *w_con = newwin(25, 80, 0, 0);
 wborder(w_con, LINE_XOXO, LINE_XOXO, LINE_OXOX, LINE_OXOX,
                LINE_OXXO, LINE_OOXX, LINE_XXOO, LINE_XOOX );
 mvwprintz(w_con, 0, 1, c_red, "Construction");
 mvwputch(w_con,  0, 30, c_white, LINE_OXXX);
 mvwputch(w_con, 24, 30, c_white, LINE_XXOX);
 for (int i = 1; i < 24; i++)
  mvwputch(w_con, i, 30, c_white, LINE_XOXO);

 mvwprintz(w_con,  1, 31, c_white, "Difficulty:");

 wrefresh(w_con);

 bool update_info = true;
 int select = 0;
 char ch;

 inventory total_inv;
 total_inv.form_from_map(this, point(u.posx, u.posy), PICKUP_RANGE);
 total_inv.add_stack(u.inv_dump());
 if (u.has_bionic(bio_tools)) {
  item tools(itypes[itm_toolset], turn);
  tools.charges = u.power_level;
  total_inv += tools;
 }

 do {
// Erase existing list of constructions
  for (int i = 1; i < 24; i++) {
   for (int j = 1; j < 29; j++)
    mvwputch(w_con, i, j, c_black, 'x');
  }
// Determine where in the master list to start printing
  int offset = select - 11;
  if (offset > constructions.size() - 22)
   offset = constructions.size() - 22;
  if (offset < 0)
   offset = 0;
// Print the constructions between offset and max (or how many will fit)
  for (int i = 0; i < 22 && i + offset < constructions.size(); i++) {
   int current = i + offset;
   nc_color col = (player_can_build(u, total_inv, constructions[current], 0) ?
                   c_white : c_dkgray);
   if (current == select)
    col = hilite(col);
   mvwprintz(w_con, 1 + i, 1, col, constructions[current]->name.c_str());
  }

  if (update_info) {
   update_info = false;
   constructable* current_con = constructions[select];
// Print difficulty
   int pskill = u.sklevel[sk_carpentry], diff = current_con->difficulty;
   mvwprintz(w_con, 1, 43, (pskill >= diff ? c_white : c_red),
             "%d   ", diff);
// Clear out lines for tools & materials
   for (int i = 2; i < 24; i++) {
    for (int j = 31; j < 79; j++)
     mvwputch(w_con, i, j, c_black, 'x');
   }

// Print stages and their requirements
   int posx = 33, posy = 2;
   for (int n = 0; n < current_con->stages.size(); n++) {
    nc_color color_stage = (player_can_build(u, total_inv, current_con, n) ?
                            c_white : c_dkgray);
    mvwprintz(w_con, posy, 31, color_stage, "Stage %d: %s", n + 1,
              current_con->stages[n].terrain == t_null? "" : terlist[current_con->stages[n].terrain].name.c_str());
    posy++;
// Print tools
    construction_stage stage = current_con->stages[n];
    bool has_tool[3] = {stage.tools[0].empty(),
                        stage.tools[1].empty(),
                        stage.tools[2].empty()};
    for (int i = 0; i < 3 && !has_tool[i]; i++) {
     posy++;
     posx = 33;
     for (int j = 0; j < stage.tools[i].size(); j++) {
      itype_id tool = stage.tools[i][j];
      nc_color col = c_red;
      if (total_inv.has_amount(tool, 1)) {
       has_tool[i] = true;
       col = c_green;
      }
      int length = itypes[tool]->name.length();
      if (posx + length > 79) {
       posy++;
       posx = 33;
      }
      mvwprintz(w_con, posy, posx, col, itypes[tool]->name.c_str());
      posx += length + 1; // + 1 for an empty space
      if (j < stage.tools[i].size() - 1) { // "OR" if there's more
       if (posx > 77) {
        posy++;
        posx = 33;
       }
       mvwprintz(w_con, posy, posx, c_white, "OR");
       posx += 3;
      }
     }
    }
// Print components
    posy++;
    posx = 33;
    bool has_component[3] = {stage.components[0].empty(),
                             stage.components[1].empty(),
                             stage.components[2].empty()};
    for (int i = 0; i < 3; i++) {
     posx = 33;
     while (has_component[i])
      i++;
     for (int j = 0; j < stage.components[i].size() && i < 3; j++) {
      nc_color col = c_red;
      component comp = stage.components[i][j];
      if (( itypes[comp.type]->is_ammo() &&
           total_inv.has_charges(comp.type, comp.count)) ||
          (!itypes[comp.type]->is_ammo() &&
           total_inv.has_amount(comp.type, comp.count))) {
       has_component[i] = true;
       col = c_green;
      }
      int length = itypes[comp.type]->name.length();
      if (posx + length > 79) {
       posy++;
       posx = 33;
      }
      mvwprintz(w_con, posy, posx, col, "%s x%d",
                itypes[comp.type]->name.c_str(), comp.count);
      posx += length + 3; // + 2 for " x", + 1 for an empty space
// Add more space for the length of the count
      if (comp.count < 10)
       posx++;
      else if (comp.count < 100)
       posx += 2;
      else
       posx += 3;

      if (j < stage.components[i].size() - 1) { // "OR" if there's more
       if (posx > 77) {
        posy++;
        posx = 33;
       }
       mvwprintz(w_con, posy, posx, c_white, "OR");
       posx += 3;
      }
     }
     posy++;
    }
   }
   wrefresh(w_con);
  } // Finished updating
 
  ch = input();
  switch (ch) {
   case 'j':
    update_info = true;
    if (select < constructions.size() - 1)
     select++;
    else
     select = 0;
    break;
   case 'k':
    update_info = true;
    if (select > 0)
     select--;
    else
     select = constructions.size() - 1;
    break;
   case '\n':
   case 'l':
    if (player_can_build(u, total_inv, constructions[select], 0)) {
     place_construction(constructions[select]);
     ch = 'q';
    } else {
     popup("You can't build that!");
     for (int i = 1; i < 24; i++)
      mvwputch(w_con, i, 30, c_white, LINE_XOXO);
     update_info = true;
    }
    break;
  }
 } while (ch != 'q' && ch != 'Q' && ch != KEY_ESCAPE);
 refresh_all();
}
Ejemplo n.º 2
0
void safemode::test_pattern( const int tab_in, const int row_in )
{
    std::vector<std::string> creature_list;
    std::string creature_name;

    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() ) {
        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;

    WINDOW *w_test_rule_border = newwin( content_height + 2, content_width, offset_y, offset_x );
    WINDOW_PTR w_test_rule_borderptr( w_test_rule_border );
    WINDOW *w_test_rule_content = newwin( content_height, content_width - 2, 1 + offset_y,
                                          1 + offset_x );
    WINDOW_PTR w_test_rule_contentptr( w_test_rule_content );

    draw_border( w_test_rule_border );

    int nmatch = creature_list.size();
    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() );
    mvwprintz( w_test_rule_border, 0, content_width / 2 - utf8_width( buf ) / 2, hilite( c_white ),
               "%s", buf.c_str() );

    mvwprintz( w_test_rule_border, content_height + 1, 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 < ( 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, "%s",
                         creature_list[i].c_str() );
            }
        }

        wrefresh( w_test_rule_content );

        const std::string action = ctxt.handle_input();
        if( action == "DOWN" ) {
            line++;
            if( line >= ( int )creature_list.size() ) {
                line = 0;
            }
        } else if( action == "UP" ) {
            line--;
            if( line < 0 ) {
                line = creature_list.size() - 1;
            }
        } else {
            break;
        }
    }
}
Ejemplo n.º 3
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();

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

    WINDOW *w_border = newwin( FULL_SCREEN_HEIGHT, FULL_SCREEN_WIDTH, offset_y, offset_x );
    WINDOW_PTR w_borderptr( w_border );
    WINDOW *w_header = newwin( header_height, FULL_SCREEN_WIDTH - 2, 1 + offset_y,
                               1 + offset_x );
    WINDOW_PTR w_headerptr( w_header );
    WINDOW *w = newwin( content_height, FULL_SCREEN_WIDTH - 2, header_height + 1 + offset_y,
                        1 + offset_x );
    WINDOW_PTR wptr( w );

    draw_border( w_border, BORDER_COLOR, custom_name_in );

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

    for( auto &column : column_pos ) {
        mvwputch( w_border, FULL_SCREEN_HEIGHT - 1, column.second + 1, c_ltgray,
                  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_ltgreen, hotkey ) + 2;
    }

    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++ ) {
        mvwputch( w_header, 2, i, c_ltgray, LINE_OXOX ); // Draw line under header
    }

    for( auto &pos : column_pos ) {
        mvwputch( w_header, 2, pos.second, c_ltgray, LINE_OXXX );
        mvwputch( w_header, 3, pos.second, c_ltgray, 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_ltgreen : c_ltred ), c_white,
                                ( ( get_option<bool>( "SAFEMODE" ) ) ? _( "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 < 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_ltgray, 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 < ( 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_ltgray;

                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, std::string text_in ) {
                    mvwprintz( w, i - start_pos, column_pos[column_in] + 2,
                               ( line == i && column == column_in ) ? hilite( line_color ) : line_color,
                               "%s", text_in.c_str()
                             );
                };

                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 ).c_str() : "---" );
                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 >= ( 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 > ( 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 viewdistance)" ) )
                                  .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 < ( 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;
    }
}
Ejemplo n.º 4
0
void veh_interact::move_cursor (int dx, int dy)
{
    mvwputch (w_disp, cy + 6, cx + 6, cpart >= 0 ? veh->part_color (cpart) : c_black,
              special_symbol(cpart >= 0 ? veh->part_sym (cpart) : ' '));
    cx += dx;
    cy += dy;
    cpart = part_at (cx, cy);
    int vdx = -ddx - cy;
    int vdy = cx - ddy;
    int vx, vy;
    veh->coord_translate (vdx, vdy, vx, vy);
    int vehx = veh->global_x() + vx;
    int vehy = veh->global_y() + vy;
    bool obstruct = g->m.move_cost_ter_furn (vehx, vehy) == 0;
    vehicle *oveh = g->m.veh_at (vehx, vehy);
    if (oveh && oveh != veh)
    {
        obstruct = true;
    }
    nc_color col = cpart >= 0 ? veh->part_color (cpart) : c_black;
    mvwputch (w_disp, cy + 6, cx + 6, obstruct ? red_background(col) : hilite(col),
              special_symbol(cpart >= 0 ? veh->part_sym (cpart) : ' '));
    wrefresh (w_disp);
    werase (w_parts);
    veh->print_part_desc (w_parts, 0, winw2, cpart, -1);
    wrefresh (w_parts);

    can_mount.clear();
    has_mats.clear();
    if (!obstruct)
        for (int i = 1; i < num_vparts; i++)
        {
            if (veh->can_mount (vdx, vdy, (vpart_id) i))
                can_mount.push_back (i);
        }
    need_repair.clear();
    parts_here.clear();
    ptank = -1;
    wheel = -1;
    if (cpart >= 0)
    {
        parts_here = veh->internal_parts(cpart);
        parts_here.insert (parts_here.begin(), cpart);
        for (int i = 0; i < parts_here.size(); i++)
        {
            int p = parts_here[i];
            if (veh->parts[p].hp < veh->part_info(p).durability)
            {
                need_repair.push_back (i);
            }
            if (veh->part_flag(p, vpf_fuel_tank) && veh->parts[p].amount < veh->part_info(p).size)
            {
                ptank = p;
            }
            if (veh->part_flag(p, vpf_wheel) && veh->parts[p].amount < veh->part_info(p).size)
            {
                wheel = p;
            }
        }
    }
    has_fuel = ptank >= 0 ? g->pl_refill_vehicle(*veh, ptank, true) : false;
    werase (w_msg);
    wrefresh (w_msg);
    display_mode (' ');
}
Ejemplo n.º 5
0
void game::construction_menu()
{
 WINDOW *w_con = newwin(25, 80, 0, 0);
 wborder(w_con, LINE_XOXO, LINE_XOXO, LINE_OXOX, LINE_OXOX,
                LINE_OXXO, LINE_OOXX, LINE_XXOO, LINE_XOOX );
 mvwprintz(w_con, 0, 1, c_red, "Construction");
 mvwputch(w_con,  0, 30, c_white, LINE_OXXX);
 mvwputch(w_con, 24, 30, c_white, LINE_XXOX);
 for (int i = 1; i < 24; i++)
  mvwputch(w_con, i, 30, c_white, LINE_XOXO);

 mvwprintz(w_con,  1, 31, c_white, "Difficulty:");

 wrefresh(w_con);

 bool update_info = true;
 int select = 0;
 char ch;

 inventory total_inv = crafting_inventory();

 do {
// Erase existing list of constructions
  for (int i = 1; i < 24; i++) {
   for (int j = 1; j < 29; j++)
    mvwputch(w_con, i, j, c_black, 'x');
  }
// Determine where in the master list to start printing
  //int offset = select - 11;
  int offset = 0;
  if (select >= 22)
   offset = select - 22;
// Print the constructions between offset and max (or how many will fit)
  for (int i = 0; i <= 22 && (i + offset) < constructions.size(); i++) {
   int current = i + offset;
   nc_color col = (player_can_build(u, total_inv, constructions[current]) ?
                   c_white : c_dkgray);
   // Map menu items to hotkey letters, skipping j, k, l, and q.
   char hotkey = current + ((current < 9) ? 97 : ((current < 13) ? 100 : 101));
   if (current == select)
    col = hilite(col);
   mvwprintz(w_con, 1 + i, 1, col, "%c %s", hotkey,
	     constructions[current]->name.c_str());
  }

  if (update_info) {
   update_info = false;
   constructable* current_con = constructions[select];
// Print difficulty
   int pskill = u.skillLevel("carpentry").level();
   int diff = current_con->difficulty > 0 ? current_con->difficulty : 0;
   mvwprintz(w_con, 1, 43, (pskill >= diff ? c_white : c_red),
             "%d   ", diff);
// Clear out lines for tools & materials
   for (int i = 2; i < 24; i++) {
    for (int j = 31; j < 79; j++)
     mvwputch(w_con, i, j, c_black, 'x');
   }

// Print stages and their requirements
   int posx = 33, posy = 2;
   for (int n = 0; n < current_con->stages.size(); n++) {
     nc_color color_stage = (player_can_build(u, total_inv, current_con, n,
					      false, true) ?
                            c_white : c_dkgray);
    mvwprintz(w_con, posy, 31, color_stage, "Stage %d: %s", n + 1,
              current_con->stages[n].terrain == t_null? "" : terlist[current_con->stages[n].terrain].name.c_str());
    posy++;
// Print tools
    construction_stage stage = current_con->stages[n];
    bool has_tool[3] = {stage.tools[0].empty(),
                        stage.tools[1].empty(),
                        stage.tools[2].empty()};
    for (int i = 0; i < 3 && !has_tool[i]; i++) {
     posy++;
     posx = 33;
     for (int j = 0; j < stage.tools[i].size(); j++) {
      itype_id tool = stage.tools[i][j];
      nc_color col = c_red;
      if (total_inv.has_amount(tool, 1)) {
       has_tool[i] = true;
       col = c_green;
      }
      int length = itypes[tool]->name.length();
      if (posx + length > 79) {
       posy++;
       posx = 33;
      }
      mvwprintz(w_con, posy, posx, col, itypes[tool]->name.c_str());
      posx += length + 1; // + 1 for an empty space
      if (j < stage.tools[i].size() - 1) { // "OR" if there's more
       if (posx > 77) {
        posy++;
        posx = 33;
       }
       mvwprintz(w_con, posy, posx, c_white, "OR");
       posx += 3;
      }
     }
    }
// Print components
    posy++;
    posx = 33;
    bool has_component[3] = {stage.components[0].empty(),
                             stage.components[1].empty(),
                             stage.components[2].empty()};
    for (int i = 0; i < 3; i++) {
     posx = 33;
     while (has_component[i])
      i++;
     for (int j = 0; j < stage.components[i].size() && i < 3; j++) {
      nc_color col = c_red;
      component comp = stage.components[i][j];
      if (( itypes[comp.type]->is_ammo() &&
           total_inv.has_charges(comp.type, comp.count)) ||
          (!itypes[comp.type]->is_ammo() &&
           total_inv.has_amount(comp.type, comp.count))) {
       has_component[i] = true;
       col = c_green;
      }
      int length = itypes[comp.type]->name.length();
      if (posx + length > 79) {
       posy++;
       posx = 33;
      }
      mvwprintz(w_con, posy, posx, col, "%s x%d",
                itypes[comp.type]->name.c_str(), comp.count);
      posx += length + 3; // + 2 for " x", + 1 for an empty space
// Add more space for the length of the count
      if (comp.count < 10)
       posx++;
      else if (comp.count < 100)
       posx += 2;
      else
       posx += 3;

      if (j < stage.components[i].size() - 1) { // "OR" if there's more
       if (posx > 77) {
        posy++;
        posx = 33;
       }
       mvwprintz(w_con, posy, posx, c_white, "OR");
       posx += 3;
      }
     }
     posy++;
    }
   }
   wrefresh(w_con);
  } // Finished updating

  ch = input();
  switch (ch) {
   case 'j':
    update_info = true;
    if (select < constructions.size() - 1)
     select++;
    else
     select = 0;
    break;
   case 'k':
    update_info = true;
    if (select > 0)
     select--;
    else
     select = constructions.size() - 1;
    break;
   case '\n':
   case 'l':
    if (player_can_build(u, total_inv, constructions[select])) {
     place_construction(constructions[select]);
     ch = 'q';
    } else {
     popup("You can't build that!");
     for (int i = 1; i < 24; i++)
      mvwputch(w_con, i, 30, c_white, LINE_XOXO);
     update_info = true;
    }
    break;
  case 'q':
  case 'Q':
  case KEY_ESCAPE:
   break;
  default:
   if (ch < 96 || ch > constructions.size() + 101) break;
   // Map menu items to hotkey letters, skipping j, k, l, and q.
   char hotkey = ch - ((ch < 106) ? 97 : ((ch < 112) ? 100 : 101));
   if (player_can_build(u, total_inv, constructions[hotkey])) {
    place_construction(constructions[hotkey]);
    ch = 'q';
   } else {
    popup("You can't build that!");
    for (int i = 1; i < 24; i++)
     mvwputch(w_con, i, 30, c_white, LINE_XOXO);
    update_info = true;
   }
   break;
  }
 } while (ch != 'q' && ch != 'Q' && ch != KEY_ESCAPE);
 refresh_all();
}
Ejemplo n.º 6
0
int main(int argc, char **argv)
{
    FILE  *fp;
    int    i;
    static char *title[] = { "Normal Text", "Bold Text", "Status Line" };
    int    colors[COLORCNT];
    int    cur;

    /* initialize the console */
    oss_con_init();

    /* use a different default color scheme for monochrome */
    if (ossmon())
        colors[2] = 0x70;
    else
        colors[2] = 23;
    colors[0] = 7;
    colors[1] = 15;

    /* read existing trcolor.dat if present */
    if (fp = fopen("trcolor.dat", "r"))
    {
        for (i = 0 ; i < COLORCNT ; ++i)
        {
            char buf[128];

            fgets(buf, sizeof(buf), fp);
            colors[i] = atoi(buf);
        }
        fclose(fp);
    }

    /* set up the screen */
    ossclr(0, 0, 25, 80, 0);
    ossdsp(3, 8, TNORMAL,
           "TADS Runtime Color Setup - Copyright (c) 1993, 2007 "
           "Michael J. Roberts");                  /* copyright-date-string */
    for (i = 0 ; i < 128 ; ++i)
        ossdsp((i / 16) + CYOFS, (i % 16) + CXOFS, i, "+");
    for (i = 0 ; i < COLORCNT ; ++i)
        hilitetitle(i, title[i], colors[i], i == 0);

    /* show instructions */
    ossdsp(16, 17, TNORMAL, "Use Tab and Shift-Tab to select text types.");
    ossdsp(17, 17, TNORMAL, "Use cursor arrows to change colors.");
    ossdsp(18, 17, TNORMAL, "Press S to save changes and exit.");
    ossdsp(19, 17, TNORMAL, "Press Esc or Q to quit without saving changes.");

    /* hilite current color */
    hilite(colors[0], TRUE);

    for (cur = 0 ;; )
    {
        ossloc(0, 0);
        switch(getch())
        {
        case 0:
            switch(getch())
            {
            case 0115:                                       /* right arrow */
                hilite(colors[cur], FALSE);
                if (++colors[cur] >= 128) colors[cur] = 0;
                hilite(colors[cur], TRUE);
                hilitetitle(cur, title[cur], colors[cur], TRUE);
                break;

            case 0113:                                        /* left arrow */
                hilite(colors[cur], FALSE);
                if (--colors[cur] <= 0) colors[cur] = 127;
                hilite(colors[cur], TRUE);
                hilitetitle(cur, title[cur], colors[cur], TRUE);
                break;

            case 0120:                                        /* down arrow */
                hilite(colors[cur], FALSE);
                if ((colors[cur] += 16) >= 128) colors[cur] -= 128;
                hilite(colors[cur], TRUE);              
                hilitetitle(cur, title[cur], colors[cur], TRUE);
                break;

            case 0110:                                          /* up arrow */
                hilite(colors[cur], FALSE);
                if ((colors[cur] -= 16) <= 0) colors[cur] += 128;
                hilite(colors[cur], TRUE);
                hilitetitle(cur, title[cur], colors[cur], TRUE);
                break;

            case 15:                                             /* backtab */
                /* unhilite current color */
                hilitetitle(cur, title[cur], colors[cur], FALSE);
                hilite(colors[cur], FALSE);

                /* select new color and hilite it */
                if (--cur < 0) cur = COLORCNT - 1;
                hilitetitle(cur, title[cur], colors[cur], TRUE);
                hilite(colors[cur], TRUE);
                break;
            }
            break;

        case 9:
            /* unhilite current color */
            hilitetitle(cur, title[cur], colors[cur], FALSE);
            hilite(colors[cur], FALSE);
            
            /* select new color and hilite it */
            if (++cur >= COLORCNT) cur = 0;
            hilitetitle(cur, title[cur], colors[cur], TRUE);
            hilite(colors[cur], TRUE);
            break;

        case 27:
        case 'q':
        case 'Q':
            ossloc(24, 0);
            oss_con_uninit();
            printf("\n\nNo changes saved.\n");
            exit(0);

        case 's':
        case 'S':
            ossloc(24, 0);
            printf("\n\n");
            if (!(fp = fopen("trcolor.dat", "w")))
            {
                oss_con_uninit();
                printf("Error - unable to create TRCOLOR.DAT\n");
                exit(1);
            }
            
            for (i = 0 ; i < COLORCNT ; ++i)
                fprintf(fp, "%d\n", colors[i]);
            fclose(fp);

            oss_con_uninit();
            printf("TRCOLOR.DAT successfully updated!\n");
            exit(0);
        }
    }

    return 0;
}
Ejemplo n.º 7
0
void auto_pickup::test_pattern(const int iCurrentPage, const int iCurrentLine)
{
    std::vector<std::string> vMatchingItems;
    std::string sItemName = "";

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

    //Loop through all itemfactory items
    //APU now ignores prefixes, bottled items and suffix combinations still not generated
    for( auto &p : item_controller->get_all_itypes() ) {
        sItemName = p.second->nname(1);
        if (vRules[iCurrentPage][iCurrentLine].bActive &&
            match(sItemName, vRules[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::ostringstream sTemp;

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

    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, vRules[iCurrentPage][iCurrentLine].sRule.c_str());
    mvwprintz(w_test_rule_border, 0, iContentWidth / 2 - utf8_width(buf) / 2, hilite(c_white),
              "%s", buf.c_str());

    mvwprintz(w_test_rule_border, iContentHeight + 1, 1, red_background(c_white),
              _("Won't display bottled and suffixes=(fits)"));

    wrefresh(w_test_rule_border);

    int iLine = 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, iLine, iContentHeight, vMatchingItems.size());

        // display auto pickup
        for (int i = iStartPos; i < (int)vMatchingItems.size(); i++) {
            if (i >= iStartPos &&
                i < iStartPos + ((iContentHeight > (int)vMatchingItems.size()) ? (int)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 (iLine == i) {
                    wprintz(w_test_rule_content, c_yellow, ">> ");
                } else {
                    wprintz(w_test_rule_content, c_yellow, "   ");
                }

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

        wrefresh(w_test_rule_content);

        const std::string action = ctxt.handle_input();
        if (action == "DOWN") {
            iLine++;
            if (iLine >= (int)vMatchingItems.size()) {
                iLine = 0;
            }
        } else if (action == "UP") {
            iLine--;
            if (iLine < 0) {
                iLine = vMatchingItems.size() - 1;
            }
        } else {
            break;
        }
    }
}
Ejemplo n.º 8
0
void auto_pickup::show()
{
    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, _(" AUTO PICKUP MANAGER "));
    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("SWAP_RULE_GLOBAL_CHAR");
    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("SWITCH_AUTO_PICKUP_OPTION");
    ctxt.register_action("HELP_KEYBINDINGS");

    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") {
            OPTIONS["AUTO_PICKUP"].setNext();
            get_options().save((g->u.name != ""));
        }
    }

    if (bStuffChanged) {
        if(query_yn(_("Save changes?"))) {
            save(false);

            if (g->u.name != "") {
                save(true);
            }
        } else {
            save_reset_changes(true);
        }
    }
}