summaryrefslogtreecommitdiffstats
path: root/trunk/source/invent.cc
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2006-08-02 12:54:15 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2006-08-02 12:54:15 +0000
commitd5e5340c3926d1cf97f6cba151ffaecb20bfb35f (patch)
treed1faf7d5b27df8f3c523a8dd33357804118e62b1 /trunk/source/invent.cc
parent7b2204d69f21d7075e4666ee032d7a129081bc4b (diff)
downloadcrawl-ref-d5e5340c3926d1cf97f6cba151ffaecb20bfb35f.tar.gz
crawl-ref-d5e5340c3926d1cf97f6cba151ffaecb20bfb35f.zip
Integrated travel patch as of 20060727
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'trunk/source/invent.cc')
-rw-r--r--trunk/source/invent.cc802
1 files changed, 599 insertions, 203 deletions
diff --git a/trunk/source/invent.cc b/trunk/source/invent.cc
index 1a6db7d1bc..2145f80f72 100644
--- a/trunk/source/invent.cc
+++ b/trunk/source/invent.cc
@@ -25,6 +25,7 @@
#include "externs.h"
+#include "clua.h"
#include "itemname.h"
#include "items.h"
#include "macro.h"
@@ -32,237 +33,467 @@
#include "shopping.h"
#include "stuff.h"
#include "view.h"
-
+#include "menu.h"
const char *command_string( int i );
const char *wizard_string( int i );
-unsigned char get_invent( int invent_type )
+struct InvTitle : public MenuEntry
{
- unsigned char nothing = invent( invent_type, false );
-
- redraw_screen();
+ Menu *m;
+ std::string (*titlefn)( int menuflags, const std::string &oldt );
+
+ InvTitle( Menu *mn, const char *title,
+ std::string (*tfn)( int menuflags, const std::string &oldt ) )
+ : MenuEntry( title )
+ {
+ m = mn;
+ titlefn = tfn;
+ }
- return (nothing);
-} // end get_invent()
+ std::string get_text() const
+ {
+ return titlefn? titlefn( m->get_flags(), MenuEntry::get_text() ) :
+ MenuEntry::get_text();
+ }
+};
-unsigned char invent( int item_class_inv, bool show_price )
+class InvShowPrices;
+class InvEntry : public MenuEntry
{
- char st_pass[ ITEMNAME_SIZE ] = "";
+private:
+ static bool show_prices;
+ static char temp_id[4][50];
+ static void set_show_prices(bool doshow);
- int i, j;
- char lines = 0;
- unsigned char anything = 0;
- char tmp_quant[20] = "";
- char yps = 0;
- char temp_id[4][50];
+ friend class InvShowPrices;
+public:
+ const item_def *item;
- const int num_lines = get_number_of_lines();
+ InvEntry( const item_def &i ) : MenuEntry( "", MEL_ITEM ), item( &i )
+ {
+ data = const_cast<item_def *>( item );
+
+ char buf[ITEMNAME_SIZE];
+ if (i.base_type == OBJ_GOLD)
+ snprintf(buf, sizeof buf, "%d gold piece%s", i.quantity,
+ (i.quantity > 1? "s" : ""));
+ else
+ item_name(i,
+ in_inventory(i)?
+ DESC_INVENTORY_EQUIP : DESC_NOCAP_A, buf, false);
+ text = buf;
- FixedVector< int, NUM_OBJECT_CLASSES > inv_class2;
- int inv_count = 0;
- unsigned char ki = 0;
+ if (i.base_type != OBJ_GOLD)
+ {
+ if (in_inventory(i))
+ {
+ text = text.substr( 4 ); // Skip the inventory letter.
+ add_hotkey(index_to_letter( i.link ));
+ }
+ else
+ add_hotkey(' '); // Dummy hotkey
+ }
+ else
+ {
+ // Dummy hotkey for gold.
+ add_hotkey(' ');
+ }
+ add_class_hotkeys(i);
-#ifdef DOS_TERM
- char buffer[4600];
+ quantity = i.quantity;
+ }
- gettext(1, 1, 80, 25, buffer);
- window(1, 1, 80, 25);
-#endif
+ std::string get_text() const
+ {
+ char buf[ITEMNAME_SIZE];
+ char suffix[ITEMNAME_SIZE] = "";
- for (i = 0; i < 4; i++)
+ if (InvEntry::show_prices)
+ {
+ int value = item_value(*item, temp_id, true);
+ if (value > 0)
+ snprintf(suffix, sizeof suffix,
+ " (%d gold)", value);
+ }
+ snprintf( buf, sizeof buf,
+ "%c %c %s%s",
+ hotkeys[0],
+ (!selected_qty? '-' : selected_qty < quantity? '#' : '+'),
+ text.c_str(),
+ suffix );
+ return (buf);
+ }
+private:
+ void add_class_hotkeys(const item_def &i)
{
- for (j = 0; j < 50; j++)
+ switch (i.base_type)
{
- temp_id[i][j] = 1;
+ case OBJ_GOLD:
+ add_hotkey('$');
+ break;
+ case OBJ_MISSILES:
+ add_hotkey('(');
+ break;
+ case OBJ_WEAPONS:
+ add_hotkey(')');
+ break;
+ case OBJ_ARMOUR:
+ add_hotkey('[');
+ break;
+ case OBJ_WANDS:
+ add_hotkey('/');
+ break;
+ case OBJ_FOOD:
+ add_hotkey('%');
+ break;
+ case OBJ_BOOKS:
+ add_hotkey('+');
+ add_hotkey(':');
+ break;
+ case OBJ_SCROLLS:
+ add_hotkey('?');
+ break;
+ case OBJ_JEWELLERY:
+ add_hotkey(i.sub_type >= AMU_RAGE? '"' : '=');
+ break;
+ case OBJ_POTIONS:
+ add_hotkey('!');
+ break;
+ case OBJ_STAVES:
+ add_hotkey('\\');
+ add_hotkey('|');
+ break;
+ case OBJ_MISCELLANY:
+ add_hotkey('}');
+ break;
+ case OBJ_CORPSES:
+ add_hotkey('&');
+ break;
+ default:
+ break;
}
}
+};
- clrscr();
-
- for (i = 0; i < NUM_OBJECT_CLASSES; i++)
- inv_class2[i] = 0;
+bool InvEntry::show_prices = false;
+char InvEntry::temp_id[4][50];
- for (i = 0; i < ENDOFPACK; i++)
+void InvEntry::set_show_prices(bool doshow)
+{
+ if ((show_prices = doshow))
{
- if (you.inv[i].quantity)
- {
- inv_class2[ you.inv[i].base_type ]++;
- inv_count++;
- }
+ memset(temp_id, 1, sizeof temp_id);
}
+}
- if (!inv_count)
+class InvShowPrices {
+public:
+ InvShowPrices(bool doshow = true)
{
- cprintf("You aren't carrying anything.");
+ InvEntry::set_show_prices(doshow);
+ }
+ ~InvShowPrices()
+ {
+ InvEntry::set_show_prices(false);
+ }
+};
- if (getch() == 0)
- getch();
+class InvMenu : public Menu
+{
+public:
+ InvMenu(int flags = MF_MULTISELECT) : Menu(flags) { }
+protected:
+ bool process_key(int key);
+};
- goto putty;
+bool InvMenu::process_key( int key )
+{
+ if (items.size() && (key == CONTROL('D') || key == '@'))
+ {
+ int newflag =
+ is_set(MF_MULTISELECT)?
+ MF_SINGLESELECT | MF_EASY_EXIT | MF_ANYPRINTABLE
+ : MF_MULTISELECT;
+
+ flags &= ~(MF_SINGLESELECT | MF_MULTISELECT |
+ MF_EASY_EXIT | MF_ANYPRINTABLE);
+ flags |= newflag;
+
+ deselect_all();
+ sel->clear();
+ draw_select_count(0);
+ return true;
}
+ return Menu::process_key( key );
+}
- if (item_class_inv != -1)
- {
- for (i = 0; i < NUM_OBJECT_CLASSES; i++)
- {
- if (item_class_inv == OBJ_MISSILES && i == OBJ_WEAPONS)
- i++;
+bool in_inventory( const item_def &i )
+{
+ return i.x == -1 && i.y == -1;
+}
- if (item_class_inv == OBJ_WEAPONS
- && (i == OBJ_STAVES || i == OBJ_MISCELLANY))
- {
- i++;
- }
+unsigned char get_invent( int invent_type )
+{
+ unsigned char nothing = invent_select( invent_type );
+
+ redraw_screen();
- if (item_class_inv == OBJ_SCROLLS && i == OBJ_BOOKS)
- i++;
+ return (nothing);
+} // end get_invent()
- if (i < NUM_OBJECT_CLASSES && item_class_inv != i)
- inv_class2[i] = 0;
+std::string item_class_name( int type, bool terse )
+{
+ if (terse)
+ {
+ switch (type)
+ {
+ case OBJ_GOLD: return ("gold");
+ case OBJ_WEAPONS: return ("weapon");
+ case OBJ_MISSILES: return ("missile");
+ case OBJ_ARMOUR: return ("armour");
+ case OBJ_WANDS: return ("wand");
+ case OBJ_FOOD: return ("food");
+ case OBJ_UNKNOWN_I: return ("book");
+ case OBJ_SCROLLS: return ("scroll");
+ case OBJ_JEWELLERY: return ("jewelry");
+ case OBJ_POTIONS: return ("potion");
+ case OBJ_UNKNOWN_II: return ("gem");
+ case OBJ_BOOKS: return ("book");
+ case OBJ_STAVES: return ("stave");
+ case OBJ_ORBS: return ("orb");
+ case OBJ_MISCELLANY: return ("misc");
+ case OBJ_CORPSES: return ("carrion");
+ }
+ }
+ else
+ {
+ switch (type)
+ {
+ case OBJ_GOLD: return ("Gold");
+ case OBJ_WEAPONS: return ("Hand Weapons");
+ case OBJ_MISSILES: return ("Missiles");
+ case OBJ_ARMOUR: return ("Armour");
+ case OBJ_WANDS: return ("Magical Devices");
+ case OBJ_FOOD: return ("Comestibles");
+ case OBJ_UNKNOWN_I: return ("Books");
+ case OBJ_SCROLLS: return ("Scrolls");
+ case OBJ_JEWELLERY: return ("Jewellery");
+ case OBJ_POTIONS: return ("Potions");
+ case OBJ_UNKNOWN_II: return ("Gems");
+ case OBJ_BOOKS: return ("Books");
+ case OBJ_STAVES: return ("Magical Staves and Rods");
+ case OBJ_ORBS: return ("Orbs of Power");
+ case OBJ_MISCELLANY: return ("Miscellaneous");
+ case OBJ_CORPSES: return ("Carrion");
}
}
+ return ("");
+}
- if ((item_class_inv == -1 && inv_count > 0)
- || (item_class_inv != -1 && inv_class2[item_class_inv] > 0)
- || (item_class_inv == OBJ_MISSILES && inv_class2[OBJ_WEAPONS] > 0)
- || (item_class_inv == OBJ_WEAPONS
- && (inv_class2[OBJ_STAVES] > 0 || inv_class2[OBJ_MISCELLANY] > 0))
- || (item_class_inv == OBJ_SCROLLS && inv_class2[OBJ_BOOKS] > 0))
+void populate_item_menu( Menu *menu, const std::vector<item_def> &items,
+ void (*callback)(MenuEntry *me) )
+{
+ FixedVector< int, NUM_OBJECT_CLASSES > inv_class;
+ for (int i = 0; i < NUM_OBJECT_CLASSES; ++i)
+ inv_class[i] = 0;
+ for (int i = 0, count = items.size(); i < count; ++i)
+ inv_class[ items[i].base_type ]++;
+
+ menu_letter ckey;
+ for (int i = 0; i < NUM_OBJECT_CLASSES; ++i)
{
- const int cap = carrying_capacity();
+ if (!inv_class[i]) continue;
- cprintf( " Inventory: %d.%d aum (%d%% of %d.%d aum maximum)",
- you.burden / 10, you.burden % 10,
- (you.burden * 100) / cap, cap / 10, cap % 10 );
- lines++;
+ menu->add_entry( new MenuEntry( item_class_name(i), MEL_SUBTITLE ) );
- for (i = 0; i < 15; i++)
+ for (int j = 0, count = items.size(); j < count; ++j)
{
- if (inv_class2[i] != 0)
- {
- if (lines > num_lines - 3)
- {
- gotoxy(1, num_lines);
- cprintf("-more-");
+ if (items[j].base_type != i) continue;
- ki = getch();
+ InvEntry *ie = new InvEntry( items[j] );
+ ie->hotkeys[0] = ckey++;
+ callback(ie);
- if (ki == ESCAPE)
- {
-#ifdef DOS_TERM
- puttext(1, 1, 80, 25, buffer);
-#endif
- return (ESCAPE);
- }
- else if (isalpha(ki) || ki == '?' || ki == '*')
- {
-#ifdef DOS_TERM
- puttext(1, 1, 80, 25, buffer);
-#endif
- return (ki);
- }
+ menu->add_entry( ie );
+ }
+ }
+}
- if (ki == 0)
- ki = getch();
+std::vector<SelItem> select_items( std::vector<item_def*> &items,
+ const char *title )
+{
+ std::vector<SelItem> selected;
- lines = 0;
- clrscr();
- gotoxy(1, 1);
- anything = 0;
+ if (items.empty())
+ return selected;
- }
+ FixedVector< int, NUM_OBJECT_CLASSES > inv_class;
+ for (int i = 0; i < NUM_OBJECT_CLASSES; ++i)
+ inv_class[i] = 0;
+ for (int i = 0, count = items.size(); i < count; ++i)
+ inv_class[ items[i]->base_type ]++;
- if (lines > 0)
- cprintf(EOL " ");
+ Menu menu;
+ menu.set_title( new MenuEntry(title) );
- textcolor(BLUE);
+ char ckey = 'a';
+ for (int i = 0; i < NUM_OBJECT_CLASSES; ++i)
+ {
+ if (!inv_class[i]) continue;
- switch (i)
- {
- case OBJ_WEAPONS: cprintf("Hand Weapons"); break;
- case OBJ_MISSILES: cprintf("Missiles"); break;
- case OBJ_ARMOUR: cprintf("Armour"); break;
- case OBJ_WANDS: cprintf("Magical Devices"); break;
- case OBJ_FOOD: cprintf("Comestibles"); break;
- case OBJ_UNKNOWN_I: cprintf("Books"); break;
- case OBJ_SCROLLS: cprintf("Scrolls"); break;
- case OBJ_JEWELLERY: cprintf("Jewellery"); break;
- case OBJ_POTIONS: cprintf("Potions"); break;
- case OBJ_UNKNOWN_II: cprintf("Gems"); break;
- case OBJ_BOOKS: cprintf("Books"); break;
- case OBJ_STAVES: cprintf("Magical Staves and Rods"); break;
- case OBJ_ORBS: cprintf("Orbs of Power"); break;
- case OBJ_MISCELLANY: cprintf("Miscellaneous"); break;
- case OBJ_CORPSES: cprintf("Carrion"); break;
- //case OBJ_GEMSTONES: cprintf("Miscellaneous"); break;
- }
-
- textcolor(LIGHTGREY);
- lines++;
-
- for (j = 0; j < ENDOFPACK; j++)
- {
- if (lines > num_lines - 2 && inv_count > 0)
- {
- gotoxy(1, num_lines);
- cprintf("-more-");
- ki = getch();
+ menu.add_entry( new MenuEntry( item_class_name(i), MEL_SUBTITLE ) );
- if (ki == ESCAPE)
- {
-#ifdef DOS_TERM
- puttext(1, 1, 80, 25, buffer);
-#endif
- return (ESCAPE);
- }
- else if (isalpha(ki) || ki == '?' || ki == '*')
- {
-#ifdef DOS_TERM
- puttext(1, 1, 80, 25, buffer);
+ for (int j = 0, count = items.size(); j < count; ++j)
+ {
+ if (items[j]->base_type != i) continue;
+
+ InvEntry *ie = new InvEntry( *items[j] );
+ ie->hotkeys[0] = ckey;
+
+ menu.add_entry( ie );
+
+ ckey = ckey == 'z'? 'A' :
+ ckey == 'Z'? 'a' :
+ ckey + 1;
+ }
+ }
+ menu.set_flags( MF_MULTISELECT | MF_SELECT_ANY_PAGE );
+ std::vector< MenuEntry * > sel = menu.show();
+ for (int i = 0, count = sel.size(); i < count; ++i)
+ {
+ InvEntry *inv = (InvEntry *) sel[i];
+ selected.push_back( SelItem( inv->hotkeys[0],
+ inv->selected_qty,
+ inv->item ) );
+ }
+
+ return selected;
+}
+
+static bool item_class_selected(const item_def &i, int selector)
+{
+ const int itype = i.base_type;
+ if (selector == OSEL_ANY || selector == itype)
+ return (true);
+
+ switch (selector)
+ {
+ case OBJ_MISSILES:
+ return (itype == OBJ_MISSILES || itype == OBJ_WEAPONS);
+ case OBJ_WEAPONS:
+ case OSEL_WIELD:
+ return (itype == OBJ_WEAPONS || itype == OBJ_STAVES
+ || itype == OBJ_MISCELLANY);
+ case OBJ_SCROLLS:
+ return (itype == OBJ_SCROLLS || itype == OBJ_BOOKS);
+ default:
+ return (false);
+ }
+}
+
+static bool userdef_item_selected(const item_def &i, int selector)
+{
+#if defined(CLUA_BINDINGS)
+ const char *luafn = selector == OSEL_WIELD? "ch_item_wieldable" :
+ NULL;
+ return (luafn && clua.callbooleanfn(false, luafn, "u", &i));
+#else
+ return (false);
#endif
- return (ki);
- }
+}
- if (ki == 0)
- ki = getch();
+static bool is_item_selected(const item_def &i, int selector)
+{
+ return item_class_selected(i, selector)
+ || userdef_item_selected(i, selector);
+}
- lines = 0;
- clrscr();
- gotoxy(1, 1);
- anything = 0;
- }
+static void get_inv_items_to_show(std::vector<item_def*> &v, int selector)
+{
+ for (int i = 0; i < ENDOFPACK; i++)
+ {
+ if (is_valid_item(you.inv[i]) && is_item_selected(you.inv[i], selector))
+ v.push_back( &you.inv[i] );
+ }
+}
- if (is_valid_item(you.inv[j]) && you.inv[j].base_type==i)
- {
- anything++;
+static void set_vectitem_classes(const std::vector<item_def*> &v,
+ FixedVector<int, NUM_OBJECT_CLASSES> &fv)
+{
+ for (int i = 0; i < NUM_OBJECT_CLASSES; i++)
+ fv[i] = 0;
+
+ for (int i = 0, size = v.size(); i < size; i++)
+ fv[ v[i]->base_type ]++;
+}
- if (lines > 0)
- cprintf(EOL);
+unsigned char invent_select(
+ int item_selector,
+ int flags,
+ std::string (*titlefn)( int menuflags,
+ const std::string &oldt ),
+ std::vector<SelItem> *items,
+ std::vector<text_pattern> *filter,
+ Menu::selitem_tfn selitemfn )
+{
+ InvMenu menu;
+
+ menu.selitem_text = selitemfn;
+ if (filter)
+ menu.set_select_filter( *filter );
- lines++;
+ FixedVector< int, NUM_OBJECT_CLASSES > inv_class2;
+ for (int i = 0; i < NUM_OBJECT_CLASSES; i++)
+ inv_class2[i] = 0;
- yps = wherey();
+ int inv_count = 0;
- in_name( j, DESC_INVENTORY_EQUIP, st_pass );
- cprintf( st_pass );
+ for (int i = 0; i < ENDOFPACK; i++)
+ {
+ if (you.inv[i].quantity)
+ {
+ inv_class2[ you.inv[i].base_type ]++;
+ inv_count++;
+ }
+ }
- inv_count--;
+ if (!inv_count)
+ {
+ menu.set_title( new MenuEntry( "You aren't carrying anything." ) );
+ menu.show();
+ return 0;
+ }
+ std::vector<item_def*> tobeshown;
+ get_inv_items_to_show( tobeshown, item_selector );
+ set_vectitem_classes( tobeshown, inv_class2 );
- if (show_price)
- {
- cprintf(" (");
+ if (tobeshown.size())
+ {
+ const int cap = carrying_capacity();
- itoa( item_value( you.inv[j], temp_id, true ),
- tmp_quant, 10 );
+ char title_buf[200];
+ snprintf( title_buf, sizeof title_buf,
+ "Inventory: %d.%d/%d.%d aum (%d%%, %d/52 slots)",
+ you.burden / 10, you.burden % 10,
+ cap / 10, cap % 10,
+ (you.burden * 100) / cap,
+ inv_count );
+ menu.set_title( new InvTitle( &menu, title_buf, titlefn ) );
- cprintf( tmp_quant );
- cprintf( " gold)" );
- }
+ for (int i = 0; i < 15; i++)
+ {
+ if (inv_class2[i] != 0)
+ {
+ std::string s = item_class_name(i);
+ menu.add_entry( new MenuEntry( s, MEL_SUBTITLE ) );
- if (wherey() != yps)
- lines++;
+ for (int j = 0, size = tobeshown.size(); j < size; ++j)
+ {
+ if (tobeshown[j]->base_type == i)
+ {
+ menu.add_entry( new InvEntry( *tobeshown[j] ) );
}
} // end of j loop
} // end of if inv_class2
@@ -270,43 +501,41 @@ unsigned char invent( int item_class_inv, bool show_price )
}
else
{
- if (item_class_inv == -1)
- cprintf("You aren't carrying anything.");
+ std::string s;
+ if (item_selector == -1)
+ s = "You aren't carrying anything.";
else
{
- if (item_class_inv == OBJ_WEAPONS)
- cprintf("You aren't carrying any weapons.");
- else if (item_class_inv == OBJ_MISSILES)
- cprintf("You aren't carrying any ammunition.");
+ if (item_selector == OBJ_WEAPONS || item_selector == OSEL_WIELD)
+ s = "You aren't carrying any weapons.";
+ else if (item_selector == OBJ_MISSILES)
+ s = "You aren't carrying any ammunition.";
else
- cprintf("You aren't carrying any such object.");
-
- anything++;
+ s = "You aren't carrying any such object.";
}
+ menu.set_title( new MenuEntry( s ) );
}
- if (anything > 0)
+ menu.set_flags( flags );
+ std::vector< MenuEntry * > sel = menu.show();
+ if (items)
{
- ki = getch();
-
- if (isalpha(ki) || ki == '?' || ki == '*')
- {
-#ifdef DOS_TERM
- puttext(1, 1, 80, 25, buffer);
-#endif
- return (ki);
- }
-
- if (ki == 0)
- ki = getch();
+ for (int i = 0, count = sel.size(); i < count; ++i)
+ items->push_back( SelItem( sel[i]->hotkeys[0],
+ sel[i]->selected_qty ) );
}
- putty:
-#ifdef DOS_TERM
- puttext(1, 1, 80, 25, buffer);
-#endif
+ unsigned char mkey = menu.getkey();
+ if (!isalnum(mkey) && mkey != '$' && mkey != '-' && mkey != '?'
+ && mkey != '*')
+ mkey = ' ';
+ return mkey;
+}
- return (ki);
+unsigned char invent( int item_class_inv, bool show_price )
+{
+ InvShowPrices show_item_prices(show_price);
+ return (invent_select(item_class_inv));
} // end invent()
@@ -337,6 +566,140 @@ static unsigned char get_invent_quant( unsigned char keyin, int &quant )
return (keyin);
}
+// This function prompts the user for an item, handles the '?' and '*'
+// listings, and returns the inventory slot to the caller (which if
+// must_exist is true (the default) will be an assigned item, with
+// a positive quantity.
+//
+// It returns PROMPT_ABORT if the player hits escape.
+// It returns PROMPT_GOT_SPECIAL if the player hits the "other_valid_char".
+//
+// Note: This function never checks if the item is appropriate.
+std::vector<SelItem> prompt_invent_items(
+ const char *prompt,
+ int type_expect,
+ std::string (*titlefn)( int menuflags,
+ const std::string &oldt ),
+ bool allow_auto_list,
+ bool allow_easy_quit,
+ const char other_valid_char,
+ std::vector<text_pattern> *select_filter,
+ Menu::selitem_tfn fn )
+{
+ unsigned char keyin = 0;
+ int ret = -1;
+
+ bool need_redraw = false;
+ bool need_prompt = true;
+ bool need_getch = true;
+
+ if (Options.auto_list && allow_auto_list)
+ {
+ need_getch = false;
+ need_redraw = false;
+ need_prompt = false;
+ keyin = '?';
+ }
+
+ std::vector< SelItem > items;
+ int count = -1;
+ for (;;)
+ {
+ if (need_redraw)
+ {
+ redraw_screen();
+ mesclr( true );
+ }
+
+ if (need_prompt)
+ mpr( prompt, MSGCH_PROMPT );
+
+ if (need_getch)
+ keyin = get_ch();
+
+ need_redraw = false;
+ need_prompt = true;
+ need_getch = true;
+
+ // Note: We handle any "special" character first, so that
+ // it can be used to override the others.
+ if (other_valid_char != '\0' && keyin == other_valid_char)
+ {
+ ret = PROMPT_GOT_SPECIAL;
+ break;
+ }
+ else if (keyin == '?' || keyin == '*' || keyin == ',')
+ {
+ int selmode = Options.drop_mode == DM_SINGLE?
+ MF_SINGLESELECT | MF_EASY_EXIT | MF_ANYPRINTABLE :
+ MF_MULTISELECT;
+ // The "view inventory listing" mode.
+ int ch = invent_select(
+ keyin == '*'? -1 : type_expect,
+ selmode | MF_SELECT_ANY_PAGE,
+ titlefn, &items, select_filter, fn );
+
+ if (selmode & MF_SINGLESELECT)
+ {
+ keyin = ch;
+ need_getch = false;
+ }
+ else
+ {
+ keyin = 0;
+ need_getch = true;
+ }
+
+ if (items.size())
+ {
+ redraw_screen();
+ mesclr( true );
+
+ for (int i = 0, count = items.size(); i < count; ++i)
+ items[i].slot = letter_to_index( items[i].slot );
+ return items;
+ }
+
+ need_redraw = !(keyin == '?' || keyin == '*'
+ || keyin == ',' || keyin == '+');
+ need_prompt = need_redraw;
+ }
+ else if (isdigit( keyin ))
+ {
+ // The "read in quantity" mode
+ keyin = get_invent_quant( keyin, count );
+
+ need_prompt = false;
+ need_getch = false;
+ }
+ else if (keyin == ESCAPE
+ || (Options.easy_quit_item_prompts
+ && allow_easy_quit
+ && keyin == ' '))
+ {
+ ret = PROMPT_ABORT;
+ break;
+ }
+ else if (isalpha( keyin ))
+ {
+ ret = letter_to_index( keyin );
+
+ if (!is_valid_item( you.inv[ret] ))
+ mpr( "You do not have any such object." );
+ else
+ break;
+ }
+ else if (!isspace( keyin ))
+ {
+ // we've got a character we don't understand...
+ canned_msg( MSG_HUH );
+ }
+ }
+
+ if (ret != PROMPT_ABORT)
+ items.push_back( SelItem( ret, count ) );
+ return items;
+}
// This function prompts the user for an item, handles the '?' and '*'
// listings, and returns the inventory slot to the caller (which if
@@ -362,8 +725,22 @@ int prompt_invent_item( const char *prompt, int type_expect,
if (Options.auto_list && allow_auto_list)
{
+ std::vector< SelItem > items;
+
// pretend the player has hit '?' and setup state.
- keyin = invent( type_expect, false );
+ keyin = invent_select( type_expect,
+ MF_SINGLESELECT | MF_ANYPRINTABLE
+ | MF_EASY_EXIT,
+ NULL, &items );
+
+ if (items.size())
+ {
+ if (count)
+ *count = items[0].quantity;
+ redraw_screen();
+ mesclr( true );
+ return letter_to_index( keyin );
+ }
need_getch = false;
@@ -402,10 +779,21 @@ int prompt_invent_item( const char *prompt, int type_expect,
else if (keyin == '?' || keyin == '*')
{
// The "view inventory listing" mode.
- if (keyin == '*')
- keyin = invent( -1, false );
- else
- keyin = invent( type_expect, false );
+ std::vector< SelItem > items;
+ keyin = invent_select( keyin == '*'? OSEL_ANY : type_expect,
+ MF_SINGLESELECT | MF_ANYPRINTABLE
+ | MF_EASY_EXIT,
+ NULL,
+ &items );
+
+ if (items.size())
+ {
+ if (count)
+ *count = items[0].quantity;
+ redraw_screen();
+ mesclr( true );
+ return letter_to_index( keyin );
+ }
need_getch = false;
@@ -619,7 +1007,15 @@ const char *command_string( int i )
(i == 450) ? "Ctrl-X : Save game without query" :
#ifdef ALLOW_DESTROY_ITEM_COMMAND
- (i == 455) ? "Ctrl-D : Destroy inventory item" :
+ (i == 451) ? "Ctrl-D : Destroy inventory item" :
+#endif
+ (i == 453) ? "Ctrl-G : interlevel travel" :
+ (i == 455) ? "Ctrl-O : explore" :
+
+#ifdef STASH_TRACKING
+ (i == 456) ? "Ctrl-S : mark stash" :
+ (i == 457) ? "Ctrl-E : forget stash" :
+ (i == 458) ? "Ctrl-F : search stashes" :
#endif
(i == 460) ? "Shift & DIR : long walk" :