PageRenderTime 63ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/src/object/obj-ui.c

https://bitbucket.org/ekolis/jackband
C | 1306 lines | 731 code | 262 blank | 313 comment | 205 complexity | e59b1cfaa897335b4064b1f11ec643e7 MD5 | raw file
  1. /*
  2. * File: object1.c
  3. * Purpose: Mainly object descriptions and generic UI functions
  4. *
  5. * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
  6. *
  7. * This work is free software; you can redistribute it and/or modify it
  8. * under the terms of either:
  9. *
  10. * a) the GNU General Public License as published by the Free Software
  11. * Foundation, version 2, or
  12. *
  13. * b) the "Angband licence":
  14. * This software may be copied and distributed for educational, research,
  15. * and not for profit purposes provided that this copyright and statement
  16. * are included in all such copies. Other copyrights may also apply.
  17. */
  18. #include "angband.h"
  19. #include "tvalsval.h"
  20. /*
  21. * Display a list of objects. Each object may be prefixed with a label.
  22. * Used by show_inven(), show_equip(), and show_floor(). Mode flags are
  23. * documented in object.h
  24. */
  25. static void show_obj_list(int num_obj, char labels[50][80], object_type *objects[50], olist_detail_t mode)
  26. {
  27. int i, row = 0, col = 0;
  28. size_t max_len = 0;
  29. int ex_width = 0, ex_offset, ex_offset_ctr;
  30. object_type *o_ptr;
  31. char o_name[50][80];
  32. char tmp_val[80];
  33. bool in_term;
  34. in_term = (mode & OLIST_WINDOW) ? TRUE : FALSE;
  35. if (in_term) max_len = 40;
  36. /* Calculate name offset and max name length */
  37. for (i = 0; i < num_obj; i++)
  38. {
  39. o_ptr = objects[i];
  40. /* Null objects are used to skip lines, or display only a label */
  41. if (o_ptr == NULL) continue;
  42. /* Max length of label + object name */
  43. object_desc(o_name[i], sizeof(o_name[i]), o_ptr, ODESC_PREFIX | ODESC_FULL);
  44. max_len = MAX(max_len, strlen(labels[i]) + strlen(o_name[i]));
  45. }
  46. /* Width of extra fields */
  47. if (mode & OLIST_WEIGHT) ex_width += 9;
  48. if (mode & OLIST_PRICE) ex_width += 9;
  49. if (mode & OLIST_FAIL) ex_width += 10;
  50. /* Determine beginning row and column */
  51. if (in_term)
  52. {
  53. /* Term window */
  54. row = 0;
  55. col = 0;
  56. }
  57. else
  58. {
  59. /* Main window */
  60. row = 1;
  61. col = Term->wid - 1 - max_len - ex_width;
  62. if (col < 3) col = 0;
  63. }
  64. /* Column offset of the first extra field */
  65. ex_offset = MIN(max_len, (size_t)(Term->wid - 1 - ex_width - col));
  66. /* Output the list */
  67. for (i = 0; i < num_obj; i++)
  68. {
  69. o_ptr = objects[i];
  70. /* Clear the line */
  71. prt("", row + i, MAX(col - 2, 0));
  72. /* Print the label */
  73. put_str(labels[i], row + i, col);
  74. /* Print the object */
  75. if (o_ptr != NULL)
  76. {
  77. /* Limit object name */
  78. if (strlen(labels[i]) + strlen(o_name[i]) > (size_t)ex_offset)
  79. {
  80. int truncate = ex_offset - strlen(labels[i]);
  81. if (truncate < 0) truncate = 0;
  82. if ((size_t)truncate > sizeof(o_name[i]) - 1) truncate = sizeof(o_name[i]) - 1;
  83. o_name[i][truncate] = '\0';
  84. }
  85. /* Object name */
  86. c_put_str(tval_to_attr[o_ptr->tval % N_ELEMENTS(tval_to_attr)], o_name[i],
  87. row + i, col + strlen(labels[i]));
  88. /* Extra fields */
  89. ex_offset_ctr = ex_offset;
  90. if (mode & OLIST_PRICE)
  91. {
  92. int price = price_item(o_ptr, TRUE, o_ptr->number);
  93. strnfmt(tmp_val, sizeof(tmp_val), "%6d au", price);
  94. put_str(tmp_val, row + i, col + ex_offset_ctr);
  95. ex_offset_ctr += 9;
  96. }
  97. if (mode & OLIST_FAIL)
  98. {
  99. int fail = (9 + get_use_device_chance(o_ptr)) / 10;
  100. if (object_effect_is_known(o_ptr))
  101. strnfmt(tmp_val, sizeof(tmp_val), "%4d%% fail", fail);
  102. else
  103. my_strcpy(tmp_val, " ? fail", sizeof(tmp_val));
  104. put_str(tmp_val, row + i, col + ex_offset_ctr);
  105. ex_offset_ctr += 10;
  106. }
  107. if (mode & OLIST_WEIGHT)
  108. {
  109. int weight = o_ptr->weight * o_ptr->number;
  110. strnfmt(tmp_val, sizeof(tmp_val), "%4d.%1d lb", weight / 10, weight % 10);
  111. put_str(tmp_val, row + i, col + ex_offset_ctr);
  112. ex_offset_ctr += 9;
  113. }
  114. }
  115. }
  116. /* For the inventory: print the quiver count */
  117. if (mode & OLIST_QUIVER)
  118. {
  119. int count, j;
  120. /* Quiver may take multiple lines */
  121. for(j = 0; j < p_ptr->quiver_slots; j++, i++)
  122. {
  123. /* Number of missiles in this "slot" */
  124. if (j == p_ptr->quiver_slots - 1 && p_ptr->quiver_remainder > 0)
  125. count = p_ptr->quiver_remainder;
  126. else
  127. count = 99;
  128. /* Clear the line */
  129. prt("", row + i, MAX(col - 2, 0));
  130. /* Print the (disabled) label */
  131. strnfmt(tmp_val, sizeof(tmp_val), "%c) ", index_to_label(i));
  132. c_put_str(TERM_SLATE, tmp_val, row + i, col);
  133. /* Print the count */
  134. strnfmt(tmp_val, sizeof(tmp_val), "in Quiver: %d missile%s", count,
  135. count == 1 ? "" : "s");
  136. c_put_str(TERM_L_UMBER, tmp_val, row + i, col + 3);
  137. }
  138. }
  139. /* Clear term windows */
  140. if (in_term)
  141. {
  142. for (; i < Term->hgt; i++)
  143. {
  144. prt("", row + i, MAX(col - 2, 0));
  145. }
  146. }
  147. /* Print a drop shadow for the main window if necessary */
  148. else if (i > 0 && row + i < 24)
  149. {
  150. prt("", row + i, MAX(col - 2, 0));
  151. }
  152. }
  153. /*
  154. * Display the inventory. Builds a list of objects and passes them
  155. * off to show_obj_list() for display. Mode flags documented in
  156. * object.h
  157. */
  158. void show_inven(olist_detail_t mode)
  159. {
  160. int i, last_slot = 0;
  161. int diff = weight_remaining();
  162. object_type *o_ptr;
  163. int num_obj = 0;
  164. char labels[50][80];
  165. object_type *objects[50];
  166. bool in_term = (mode & OLIST_WINDOW) ? TRUE : FALSE;
  167. /* Include burden for term windows */
  168. if (in_term)
  169. {
  170. strnfmt(labels[num_obj], sizeof(labels[num_obj]),
  171. "Burden %d.%d lb (%d.%d lb %s) ",
  172. p_ptr->total_weight / 10, p_ptr->total_weight % 10,
  173. abs(diff) / 10, abs(diff) % 10,
  174. (diff < 0 ? "overweight" : "remaining"));
  175. objects[num_obj] = NULL;
  176. num_obj++;
  177. }
  178. /* Find the last occupied inventory slot */
  179. for (i = 0; i < INVEN_PACK; i++)
  180. {
  181. o_ptr = &inventory[i];
  182. if (o_ptr->k_idx) last_slot = i;
  183. }
  184. /* Build the object list */
  185. for (i = 0; i <= last_slot; i++)
  186. {
  187. o_ptr = &inventory[i];
  188. /* Acceptable items get a label */
  189. if (item_tester_okay(o_ptr))
  190. strnfmt(labels[num_obj], sizeof(labels[num_obj]), "%c) ", index_to_label(i));
  191. /* Unacceptable items are still displayed in term windows */
  192. else if (in_term)
  193. my_strcpy(labels[num_obj], " ", sizeof(labels[num_obj]));
  194. /* Unacceptable items are skipped in the main window */
  195. else continue;
  196. /* Save the object */
  197. objects[num_obj] = o_ptr;
  198. num_obj++;
  199. }
  200. /* Display the object list */
  201. show_obj_list(num_obj, labels, objects, mode);
  202. }
  203. /*
  204. * Display the equipment. Builds a list of objects and passes them
  205. * off to show_obj_list() for display. Mode flags documented in
  206. * object.h
  207. */
  208. void show_equip(olist_detail_t mode)
  209. {
  210. int i, last_slot = 0;
  211. object_type *o_ptr;
  212. int num_obj = 0;
  213. char labels[50][80];
  214. object_type *objects[50];
  215. char tmp_val[80];
  216. bool in_term = (mode & OLIST_WINDOW) ? TRUE : FALSE;
  217. /* Find the last equipment slot to display */
  218. for (i = INVEN_WIELD; i < ALL_INVEN_TOTAL; i++)
  219. {
  220. o_ptr = &inventory[i];
  221. if (i < INVEN_TOTAL || o_ptr->k_idx) last_slot = i;
  222. }
  223. /* Build the object list */
  224. for (i = INVEN_WIELD; i <= last_slot; i++)
  225. {
  226. o_ptr = &inventory[i];
  227. /* May need a blank line to separate the quiver */
  228. if (i == INVEN_TOTAL)
  229. {
  230. int j;
  231. bool need_spacer = FALSE;
  232. /* Scan the rest of the items for acceptable entries */
  233. for (j = i; j < last_slot; j++)
  234. {
  235. o_ptr = &inventory[j];
  236. if (item_tester_okay(o_ptr)) need_spacer = TRUE;
  237. }
  238. /* Add a spacer between equipment and quiver */
  239. if (num_obj > 0 && need_spacer)
  240. {
  241. my_strcpy(labels[num_obj], "", sizeof(labels[num_obj]));
  242. objects[num_obj] = NULL;
  243. num_obj++;
  244. }
  245. continue;
  246. }
  247. /* Acceptable items get a label */
  248. if (item_tester_okay(o_ptr))
  249. strnfmt(labels[num_obj], sizeof(labels[num_obj]), "%c) ", index_to_label(i));
  250. /* Unacceptable items are still displayed in term windows */
  251. else if (in_term)
  252. my_strcpy(labels[num_obj], " ", sizeof(labels[num_obj]));
  253. /* Unacceptable items are skipped in the main window */
  254. else continue;
  255. /* Show full slot labels */
  256. if (OPT(show_labels))
  257. {
  258. strnfmt(tmp_val, sizeof(tmp_val), "%-14s: ", mention_use(i));
  259. my_strcat(labels[num_obj], tmp_val, sizeof(labels[num_obj]));
  260. }
  261. /* Otherwise only show short quiver labels */
  262. else if (i >= QUIVER_START)
  263. {
  264. strnfmt(tmp_val, sizeof(tmp_val), "[f%d]: ", i - QUIVER_START);
  265. my_strcat(labels[num_obj], tmp_val, sizeof(labels[num_obj]));
  266. }
  267. /* Save the object */
  268. objects[num_obj] = o_ptr;
  269. num_obj++;
  270. }
  271. /* Display the object list */
  272. show_obj_list(num_obj, labels, objects, mode);
  273. }
  274. /*
  275. * Display the floor. Builds a list of objects and passes them
  276. * off to show_obj_list() for display. Mode flags documented in
  277. * object.h
  278. */
  279. void show_floor(const int *floor_list, int floor_num, olist_detail_t mode)
  280. {
  281. int i;
  282. object_type *o_ptr;
  283. int num_obj = 0;
  284. char labels[50][80];
  285. object_type *objects[50];
  286. if (floor_num > MAX_FLOOR_STACK) floor_num = MAX_FLOOR_STACK;
  287. /* Build the object list */
  288. for (i = 0; i < floor_num; i++)
  289. {
  290. o_ptr = &o_list[floor_list[i]];
  291. /* Tester always skips gold. When gold should be displayed,
  292. * only test items that are not gold.
  293. */
  294. if ((o_ptr->tval != TV_GOLD || !(mode & OLIST_GOLD)) &&
  295. !item_tester_okay(o_ptr))
  296. continue;
  297. strnfmt(labels[num_obj], sizeof(labels[num_obj]),
  298. "%c) ", index_to_label(i));
  299. /* Save the object */
  300. objects[num_obj] = o_ptr;
  301. num_obj++;
  302. }
  303. /* Display the object list */
  304. show_obj_list(num_obj, labels, objects, mode);
  305. }
  306. /*
  307. * Verify the choice of an item.
  308. *
  309. * The item can be negative to mean "item on floor".
  310. */
  311. bool verify_item(cptr prompt, int item)
  312. {
  313. char o_name[80];
  314. char out_val[160];
  315. object_type *o_ptr;
  316. /* Inventory */
  317. if (item >= 0)
  318. {
  319. o_ptr = &inventory[item];
  320. }
  321. /* Floor */
  322. else
  323. {
  324. o_ptr = &o_list[0 - item];
  325. }
  326. /* Describe */
  327. object_desc(o_name, sizeof(o_name), o_ptr, ODESC_PREFIX | ODESC_FULL);
  328. /* Prompt */
  329. strnfmt(out_val, sizeof(out_val), "%s %s? ", prompt, o_name);
  330. /* Query */
  331. return (get_check(out_val));
  332. }
  333. /*
  334. * Hack -- allow user to "prevent" certain choices.
  335. *
  336. * The item can be negative to mean "item on floor".
  337. */
  338. static bool get_item_allow(int item, bool is_harmless)
  339. {
  340. object_type *o_ptr;
  341. char verify_inscrip[] = "!*";
  342. unsigned n;
  343. /* Inventory or floor */
  344. if (item >= 0)
  345. o_ptr = &inventory[item];
  346. else
  347. o_ptr = &o_list[0 - item];
  348. /* Check for a "prevention" inscription */
  349. verify_inscrip[1] = p_ptr->command_cmd;
  350. /* Find both sets of inscriptions, add togther, and prompt that number of times */
  351. n = check_for_inscrip(o_ptr, verify_inscrip);
  352. if (!is_harmless)
  353. n += check_for_inscrip(o_ptr, "!*");
  354. while (n--)
  355. {
  356. if (!verify_item("Really try", item))
  357. return (FALSE);
  358. }
  359. /* Allow it */
  360. return (TRUE);
  361. }
  362. /*
  363. * Find the "first" inventory object with the given "tag".
  364. *
  365. * A "tag" is a char "n" appearing as "@n" anywhere in the
  366. * inscription of an object.
  367. *
  368. * Also, the tag "@xn" will work as well, where "n" is a tag-char,
  369. * and "x" is the "current" p_ptr->command_cmd code.
  370. */
  371. static int get_tag(int *cp, char tag)
  372. {
  373. int i;
  374. cptr s;
  375. /* (f)ire is handled differently from all others, due to the quiver */
  376. if (p_ptr->command_cmd == 'f')
  377. {
  378. i = QUIVER_START + tag - '0';
  379. if (inventory[i].k_idx)
  380. {
  381. *cp = i;
  382. return (TRUE);
  383. }
  384. return (FALSE);
  385. }
  386. /* Check every object */
  387. for (i = 0; i < ALL_INVEN_TOTAL; ++i)
  388. {
  389. object_type *o_ptr = &inventory[i];
  390. /* Skip non-objects */
  391. if (!o_ptr->k_idx) continue;
  392. /* Skip empty inscriptions */
  393. if (!o_ptr->note) continue;
  394. /* Find a '@' */
  395. s = strchr(quark_str(o_ptr->note), '@');
  396. /* Process all tags */
  397. while (s)
  398. {
  399. /* Check the normal tags */
  400. if (s[1] == tag)
  401. {
  402. /* Save the actual inventory ID */
  403. *cp = i;
  404. /* Success */
  405. return (TRUE);
  406. }
  407. /* Check the special tags */
  408. if ((s[1] == p_ptr->command_cmd) && (s[2] == tag))
  409. {
  410. /* Save the actual inventory ID */
  411. *cp = i;
  412. /* Success */
  413. return (TRUE);
  414. }
  415. /* Find another '@' */
  416. s = strchr(s + 1, '@');
  417. }
  418. }
  419. /* No such tag */
  420. return (FALSE);
  421. }
  422. /*
  423. * Let the user select an item, save its "index"
  424. *
  425. * Return TRUE only if an acceptable item was chosen by the user.
  426. *
  427. * The selected item must satisfy the "item_tester_hook()" function,
  428. * if that hook is set, and the "item_tester_tval", if that value is set.
  429. *
  430. * All "item_tester" restrictions are cleared before this function returns.
  431. *
  432. * The user is allowed to choose acceptable items from the equipment,
  433. * inventory, or floor, respectively, if the proper flag was given,
  434. * and there are any acceptable items in that location.
  435. *
  436. * The equipment or inventory are displayed (even if no acceptable
  437. * items are in that location) if the proper flag was given.
  438. *
  439. * If there are no acceptable items available anywhere, and "str" is
  440. * not NULL, then it will be used as the text of a warning message
  441. * before the function returns.
  442. *
  443. * Note that the user must press "-" to specify the item on the floor,
  444. * and there is no way to "examine" the item on the floor, while the
  445. * use of "capital" letters will "examine" an inventory/equipment item,
  446. * and prompt for its use.
  447. *
  448. * If a legal item is selected from the inventory, we save it in "cp"
  449. * directly (0 to 35), and return TRUE.
  450. *
  451. * If a legal item is selected from the floor, we save it in "cp" as
  452. * a negative (-1 to -511), and return TRUE.
  453. *
  454. * If no item is available, we do nothing to "cp", and we display a
  455. * warning message, using "str" if available, and return FALSE.
  456. *
  457. * If no item is selected, we do nothing to "cp", and return FALSE.
  458. *
  459. * Global "p_ptr->command_new" is used when viewing the inventory or equipment
  460. * to allow the user to enter a command while viewing those screens, and
  461. * also to induce "auto-enter" of stores, and other such stuff.
  462. *
  463. * Global "p_ptr->command_wrk" is used to choose between equip/inven/floor
  464. * listings. It is equal to USE_INVEN or USE_EQUIP or USE_FLOOR, except
  465. * when this function is first called, when it is equal to zero, which will
  466. * cause it to be set to USE_INVEN.
  467. *
  468. * We always erase the prompt when we are done, leaving a blank line,
  469. * or a warning message, if appropriate, if no items are available.
  470. *
  471. * Note that only "acceptable" floor objects get indexes, so between two
  472. * commands, the indexes of floor objects may change. XXX XXX XXX
  473. */
  474. bool get_item(int *cp, cptr pmt, cptr str, int mode)
  475. {
  476. int py = p_ptr->py;
  477. int px = p_ptr->px;
  478. ui_event_data which;
  479. int j, k;
  480. int i1, i2;
  481. int e1, e2;
  482. int f1, f2;
  483. bool done, item;
  484. bool oops = FALSE;
  485. bool use_inven = ((mode & USE_INVEN) ? TRUE : FALSE);
  486. bool use_equip = ((mode & USE_EQUIP) ? TRUE : FALSE);
  487. bool use_floor = ((mode & USE_FLOOR) ? TRUE : FALSE);
  488. bool can_squelch = ((mode & CAN_SQUELCH) ? TRUE : FALSE);
  489. bool is_harmless = ((mode & IS_HARMLESS) ? TRUE : FALSE);
  490. olist_detail_t olist_mode = 0;
  491. bool allow_inven = FALSE;
  492. bool allow_equip = FALSE;
  493. bool allow_floor = FALSE;
  494. bool toggle = FALSE;
  495. char tmp_val[160];
  496. char out_val[160];
  497. int floor_list[MAX_FLOOR_STACK];
  498. int floor_num;
  499. bool show_list = OPT(show_lists) ? TRUE : FALSE;
  500. /* Object list display modes */
  501. if (mode & SHOW_FAIL)
  502. olist_mode |= (OLIST_FAIL);
  503. else
  504. olist_mode |= (OLIST_WEIGHT);
  505. if (mode & SHOW_PRICES)
  506. olist_mode |= (OLIST_PRICE);
  507. /* Paranoia XXX XXX XXX */
  508. message_flush();
  509. /* Not done */
  510. done = FALSE;
  511. /* No item selected */
  512. item = FALSE;
  513. /* Full inventory */
  514. i1 = 0;
  515. i2 = INVEN_PACK - 1;
  516. /* Forbid inventory */
  517. if (!use_inven) i2 = -1;
  518. /* Restrict inventory indexes */
  519. while ((i1 <= i2) && (!get_item_okay(i1))) i1++;
  520. while ((i1 <= i2) && (!get_item_okay(i2))) i2--;
  521. /* Accept inventory */
  522. if (i1 <= i2) allow_inven = TRUE;
  523. /* Full equipment */
  524. e1 = INVEN_WIELD;
  525. e2 = ALL_INVEN_TOTAL - 1;
  526. /* Forbid equipment */
  527. if (!use_equip) e2 = -1;
  528. /* Restrict equipment indexes */
  529. while ((e1 <= e2) && (!get_item_okay(e1))) e1++;
  530. while ((e1 <= e2) && (!get_item_okay(e2))) e2--;
  531. /* Accept equipment */
  532. if (e1 <= e2) allow_equip = TRUE;
  533. /* Scan all non-gold objects in the grid */
  534. floor_num = scan_floor(floor_list, N_ELEMENTS(floor_list), py, px, 0x03);
  535. /* Full floor */
  536. f1 = 0;
  537. f2 = floor_num - 1;
  538. /* Forbid floor */
  539. if (!use_floor) f2 = -1;
  540. /* Restrict floor indexes */
  541. while ((f1 <= f2) && (!get_item_okay(0 - floor_list[f1]))) f1++;
  542. while ((f1 <= f2) && (!get_item_okay(0 - floor_list[f2]))) f2--;
  543. /* Accept floor */
  544. if (f1 <= f2) allow_floor = TRUE;
  545. /* Require at least one legal choice */
  546. if (!allow_inven && !allow_equip && !allow_floor)
  547. {
  548. /* Oops */
  549. oops = TRUE;
  550. done = TRUE;
  551. }
  552. /* Analyze choices */
  553. else
  554. {
  555. /* Hack -- Start on equipment if requested */
  556. if ((p_ptr->command_wrk == USE_EQUIP) && use_equip)
  557. p_ptr->command_wrk = USE_EQUIP;
  558. /* Use inventory if allowed */
  559. else if (use_inven)
  560. p_ptr->command_wrk = USE_INVEN;
  561. /* Use equipment if allowed */
  562. else if (use_equip)
  563. p_ptr->command_wrk = USE_EQUIP;
  564. /* Use floor if allowed */
  565. else if (use_floor)
  566. p_ptr->command_wrk = USE_FLOOR;
  567. /* Hack -- Use (empty) inventory */
  568. else
  569. p_ptr->command_wrk = USE_INVEN;
  570. }
  571. /* Start out in "display" mode */
  572. if (show_list)
  573. {
  574. /* Save screen */
  575. screen_save();
  576. }
  577. /* Repeat until done */
  578. while (!done)
  579. {
  580. int ni = 0;
  581. int ne = 0;
  582. /* Scan windows */
  583. for (j = 0; j < ANGBAND_TERM_MAX; j++)
  584. {
  585. /* Unused */
  586. if (!angband_term[j]) continue;
  587. /* Count windows displaying inven */
  588. if (op_ptr->window_flag[j] & (PW_INVEN)) ni++;
  589. /* Count windows displaying equip */
  590. if (op_ptr->window_flag[j] & (PW_EQUIP)) ne++;
  591. }
  592. /* Toggle if needed */
  593. if (((p_ptr->command_wrk == USE_EQUIP) && ni && !ne) ||
  594. ((p_ptr->command_wrk == USE_INVEN) && !ni && ne))
  595. {
  596. /* Toggle */
  597. toggle_inven_equip();
  598. /* Track toggles */
  599. toggle = !toggle;
  600. }
  601. /* Redraw */
  602. p_ptr->redraw |= (PR_INVEN | PR_EQUIP);
  603. /* Redraw windows */
  604. redraw_stuff();
  605. /* Viewing inventory */
  606. if (p_ptr->command_wrk == USE_INVEN)
  607. {
  608. /* Redraw if needed */
  609. if (show_list) show_inven(olist_mode);
  610. /* Begin the prompt */
  611. strnfmt(out_val, sizeof(out_val), "Inven:");
  612. /* List choices */
  613. if (i1 <= i2)
  614. {
  615. /* Build the prompt */
  616. strnfmt(tmp_val, sizeof(tmp_val), " %c-%c,",
  617. index_to_label(i1), index_to_label(i2));
  618. /* Append */
  619. my_strcat(out_val, tmp_val, sizeof(out_val));
  620. }
  621. /* Indicate ability to "view" */
  622. if (!show_list)
  623. {
  624. my_strcat(out_val, " * to see,", sizeof(out_val));
  625. button_add("[*]", '*');
  626. }
  627. /* Indicate legality of "toggle" */
  628. if (use_equip)
  629. {
  630. my_strcat(out_val, " / for Equip,", sizeof(out_val));
  631. button_add("[/]", '/');
  632. }
  633. /* Indicate legality of the "floor" */
  634. if (allow_floor)
  635. {
  636. my_strcat(out_val, " - for floor,", sizeof(out_val));
  637. button_add("[-]", '-');
  638. }
  639. /* Indicate that squelched items can be selected */
  640. if (can_squelch)
  641. {
  642. my_strcat(out_val, " ! for squelched,", sizeof(out_val));
  643. button_add("[!]", '!');
  644. }
  645. }
  646. /* Viewing equipment */
  647. else if (p_ptr->command_wrk == USE_EQUIP)
  648. {
  649. /* Redraw if needed */
  650. if (show_list) show_equip(olist_mode);
  651. /* Begin the prompt */
  652. strnfmt(out_val, sizeof(out_val), "Equip:");
  653. /* List choices */
  654. if (e1 <= e2)
  655. {
  656. /* Build the prompt */
  657. strnfmt(tmp_val, sizeof(tmp_val), " %c-%c,",
  658. index_to_label(e1), index_to_label(e2));
  659. /* Append */
  660. my_strcat(out_val, tmp_val, sizeof(out_val));
  661. }
  662. /* Indicate ability to "view" */
  663. if (!show_list)
  664. {
  665. my_strcat(out_val, " * to see,", sizeof(out_val));
  666. button_add("[*]", '*');
  667. }
  668. /* Indicate legality of "toggle" */
  669. if (use_inven)
  670. {
  671. my_strcat(out_val, " / for Inven,", sizeof(out_val));
  672. button_add("[/]", '/');
  673. }
  674. /* Indicate legality of the "floor" */
  675. if (allow_floor)
  676. {
  677. my_strcat(out_val, " - for floor,", sizeof(out_val));
  678. button_add("[!]", '!');
  679. }
  680. }
  681. /* Viewing floor */
  682. else
  683. {
  684. /* Redraw if needed */
  685. if (show_list) show_floor(floor_list, floor_num, olist_mode);
  686. /* Begin the prompt */
  687. strnfmt(out_val, sizeof(out_val), "Floor:");
  688. /* List choices */
  689. if (f1 <= f2)
  690. {
  691. /* Build the prompt */
  692. strnfmt(tmp_val, sizeof(tmp_val), " %c-%c,", I2A(f1), I2A(f2));
  693. /* Append */
  694. my_strcat(out_val, tmp_val, sizeof(out_val));
  695. }
  696. /* Indicate ability to "view" */
  697. if (!show_list)
  698. {
  699. my_strcat(out_val, " * to see,", sizeof(out_val));
  700. button_add("[*]", '*');
  701. }
  702. /* Append */
  703. if (use_inven)
  704. {
  705. my_strcat(out_val, " / for Inven,", sizeof(out_val));
  706. button_add("[/]", '/');
  707. }
  708. /* Append */
  709. else if (use_equip)
  710. {
  711. my_strcat(out_val, " / for Equip,", sizeof(out_val));
  712. button_add("[/]", '/');
  713. }
  714. /* Indicate that squelched items can be selected */
  715. if (can_squelch)
  716. {
  717. my_strcat(out_val, " ! for squelched,", sizeof(out_val));
  718. button_add("[!]", '!');
  719. }
  720. }
  721. redraw_stuff();
  722. /* Finish the prompt */
  723. my_strcat(out_val, " ESC", sizeof(out_val));
  724. /* Build the prompt */
  725. strnfmt(tmp_val, sizeof(tmp_val), "(%s) %s", out_val, pmt);
  726. /* Show the prompt */
  727. prt(tmp_val, 0, 0);
  728. /* Get a key */
  729. which = inkey_ex();
  730. /* Parse it */
  731. switch (which.key)
  732. {
  733. case ESCAPE:
  734. {
  735. done = TRUE;
  736. break;
  737. }
  738. case '*':
  739. case '?':
  740. case ' ':
  741. {
  742. if (!OPT(show_lists))
  743. {
  744. /* Hide the list */
  745. if (show_list)
  746. {
  747. /* Flip flag */
  748. show_list = FALSE;
  749. /* Load screen */
  750. screen_load();
  751. }
  752. /* Show the list */
  753. else
  754. {
  755. /* Save screen */
  756. screen_save();
  757. /* Flip flag */
  758. show_list = TRUE;
  759. }
  760. }
  761. break;
  762. }
  763. case '/':
  764. {
  765. /* Toggle to inventory */
  766. if (use_inven && (p_ptr->command_wrk != USE_INVEN))
  767. {
  768. p_ptr->command_wrk = USE_INVEN;
  769. }
  770. /* Toggle to equipment */
  771. else if (use_equip && (p_ptr->command_wrk != USE_EQUIP))
  772. {
  773. p_ptr->command_wrk = USE_EQUIP;
  774. }
  775. /* No toggle allowed */
  776. else
  777. {
  778. bell("Cannot switch item selector!");
  779. break;
  780. }
  781. /* Hack -- Fix screen */
  782. if (show_list)
  783. {
  784. /* Load screen */
  785. screen_load();
  786. /* Save screen */
  787. screen_save();
  788. }
  789. /* Need to redraw */
  790. break;
  791. }
  792. case '-':
  793. {
  794. /* Paranoia */
  795. if (!allow_floor)
  796. {
  797. bell("Cannot select floor!");
  798. break;
  799. }
  800. /* There is only one item */
  801. if (floor_num == 1)
  802. {
  803. /* Auto-select */
  804. if (p_ptr->command_wrk == (USE_FLOOR))
  805. {
  806. /* Special index */
  807. k = 0 - floor_list[0];
  808. /* Allow player to "refuse" certain actions */
  809. if (!get_item_allow(k, is_harmless))
  810. {
  811. done = TRUE;
  812. break;
  813. }
  814. /* Accept that choice */
  815. (*cp) = k;
  816. item = TRUE;
  817. done = TRUE;
  818. break;
  819. }
  820. }
  821. /* Hack -- Fix screen */
  822. if (show_list)
  823. {
  824. /* Load screen */
  825. screen_load();
  826. /* Save screen */
  827. screen_save();
  828. }
  829. p_ptr->command_wrk = (USE_FLOOR);
  830. #if 0
  831. /* Check each legal object */
  832. for (i = 0; i < floor_num; ++i)
  833. {
  834. /* Special index */
  835. k = 0 - floor_list[i];
  836. /* Skip non-okay objects */
  837. if (!get_item_okay(k)) continue;
  838. /* Allow player to "refuse" certain actions */
  839. if (!get_item_allow(k)) continue;
  840. /* Accept that choice */
  841. (*cp) = k;
  842. item = TRUE;
  843. done = TRUE;
  844. break;
  845. }
  846. #endif
  847. break;
  848. }
  849. case '0':
  850. case '1': case '2': case '3':
  851. case '4': case '5': case '6':
  852. case '7': case '8': case '9':
  853. {
  854. /* Look up the tag */
  855. if (!get_tag(&k, which.key))
  856. {
  857. bell("Illegal object choice (tag)!");
  858. break;
  859. }
  860. /* Hack -- Validate the item */
  861. if ((k < INVEN_WIELD) ? !allow_inven : !allow_equip)
  862. {
  863. bell("Illegal object choice (tag)!");
  864. break;
  865. }
  866. /* Validate the item */
  867. if (!get_item_okay(k))
  868. {
  869. bell("Illegal object choice (tag)!");
  870. break;
  871. }
  872. /* Allow player to "refuse" certain actions */
  873. if (!get_item_allow(k, is_harmless))
  874. {
  875. done = TRUE;
  876. break;
  877. }
  878. /* Accept that choice */
  879. (*cp) = k;
  880. item = TRUE;
  881. done = TRUE;
  882. break;
  883. }
  884. case '\n':
  885. case '\r':
  886. {
  887. /* Choose "default" inventory item */
  888. if (p_ptr->command_wrk == USE_INVEN)
  889. {
  890. if (i1 != i2)
  891. {
  892. bell("Illegal object choice (default)!");
  893. break;
  894. }
  895. k = i1;
  896. }
  897. /* Choose the "default" slot (0) of the quiver */
  898. else if(p_ptr->command_cmd == 'f')
  899. k = e1;
  900. /* Choose "default" equipment item */
  901. else if (p_ptr->command_wrk == USE_EQUIP)
  902. {
  903. if (e1 != e2)
  904. {
  905. bell("Illegal object choice (default)!");
  906. break;
  907. }
  908. k = e1;
  909. }
  910. /* Choose "default" floor item */
  911. else
  912. {
  913. if (f1 != f2)
  914. {
  915. bell("Illegal object choice (default)!");
  916. break;
  917. }
  918. k = 0 - floor_list[f1];
  919. }
  920. /* Validate the item */
  921. if (!get_item_okay(k))
  922. {
  923. bell("Illegal object choice (default)!");
  924. break;
  925. }
  926. /* Allow player to "refuse" certain actions */
  927. if (!get_item_allow(k, is_harmless))
  928. {
  929. done = TRUE;
  930. break;
  931. }
  932. /* Accept that choice */
  933. (*cp) = k;
  934. item = TRUE;
  935. done = TRUE;
  936. break;
  937. }
  938. case '!':
  939. {
  940. /* Try squelched items */
  941. if (can_squelch)
  942. {
  943. (*cp) = ALL_SQUELCHED;
  944. item = TRUE;
  945. done = TRUE;
  946. break;
  947. }
  948. /* Just fall through */
  949. }
  950. default:
  951. {
  952. bool verify;
  953. /* Note verify */
  954. verify = (isupper((unsigned char)which.key) ? TRUE : FALSE);
  955. /* Lowercase */
  956. which.key = tolower((unsigned char)which.key);
  957. /* Convert letter to inventory index */
  958. if (p_ptr->command_wrk == USE_INVEN)
  959. {
  960. k = label_to_inven(which.key);
  961. if (k < 0)
  962. {
  963. bell("Illegal object choice (inven)!");
  964. break;
  965. }
  966. }
  967. /* Convert letter to equipment index */
  968. else if (p_ptr->command_wrk == USE_EQUIP)
  969. {
  970. k = label_to_equip(which.key);
  971. if (k < 0)
  972. {
  973. bell("Illegal object choice (equip)!");
  974. break;
  975. }
  976. }
  977. /* Convert letter to floor index */
  978. else
  979. {
  980. k = (islower((unsigned char)which.key) ? A2I(which.key) : -1);
  981. if (k < 0 || k >= floor_num)
  982. {
  983. bell("Illegal object choice (floor)!");
  984. break;
  985. }
  986. /* Special index */
  987. k = 0 - floor_list[k];
  988. }
  989. /* Validate the item */
  990. if (!get_item_okay(k))
  991. {
  992. bell("Illegal object choice (normal)!");
  993. break;
  994. }
  995. /* Verify the item */
  996. if (verify && !verify_item("Try", k))
  997. {
  998. done = TRUE;
  999. break;
  1000. }
  1001. /* Allow player to "refuse" certain actions */
  1002. if (!get_item_allow(k, is_harmless))
  1003. {
  1004. done = TRUE;
  1005. break;
  1006. }
  1007. /* Accept that choice */
  1008. (*cp) = k;
  1009. item = TRUE;
  1010. done = TRUE;
  1011. break;
  1012. }
  1013. }
  1014. }
  1015. /* Fix the screen if necessary */
  1016. if (show_list)
  1017. {
  1018. /* Load screen */
  1019. screen_load();
  1020. /* Hack -- Cancel "display" */
  1021. show_list = FALSE;
  1022. }
  1023. /* Kill buttons */
  1024. button_kill('*');
  1025. button_kill('/');
  1026. button_kill('-');
  1027. button_kill('!');
  1028. redraw_stuff();
  1029. /* Forget the item_tester_tval restriction */
  1030. item_tester_tval = 0;
  1031. /* Forget the item_tester_hook restriction */
  1032. item_tester_hook = NULL;
  1033. /* Toggle again if needed */
  1034. if (toggle) toggle_inven_equip();
  1035. /* Update */
  1036. p_ptr->redraw |= (PR_INVEN | PR_EQUIP);
  1037. redraw_stuff();
  1038. /* Clear the prompt line */
  1039. prt("", 0, 0);
  1040. /* Warning if needed */
  1041. if (oops && str) msg_print(str);
  1042. /* Result */
  1043. return (item);
  1044. }