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