1 /* 2 * Copyright (c) 1988 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Timothy C. Stoehr. 7 * 8 * Redistribution and use in source and binary forms are permitted 9 * provided that the above copyright notice and this paragraph are 10 * duplicated in all such forms and that any documentation, 11 * advertising materials, and other materials related to such 12 * distribution and use acknowledge that the software was developed 13 * by the University of California, Berkeley. The name of the 14 * University may not be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19 */ 20 21 #ifndef lint 22 static char sccsid[] = "@(#)inventory.c 5.3 (Berkeley) 02/07/89"; 23 #endif /* not lint */ 24 25 /* 26 * inventory.c 27 * 28 * This source herein may be modified and/or distributed by anybody who 29 * so desires, with the following restrictions: 30 * 1.) No portion of this notice shall be removed. 31 * 2.) Credit shall not be taken for the creation of this source. 32 * 3.) This code is not to be traded, sold, or used for personal 33 * gain or profit. 34 * 35 */ 36 37 #include "rogue.h" 38 39 boolean is_wood[WANDS]; 40 char *press_space = " --press space to continue--"; 41 42 char *wand_materials[WAND_MATERIALS] = { 43 "steel ", 44 "bronze ", 45 "gold ", 46 "silver ", 47 "copper ", 48 "nickel ", 49 "cobalt ", 50 "tin ", 51 "iron ", 52 "magnesium ", 53 "chrome ", 54 "carbon ", 55 "platinum ", 56 "silicon ", 57 "titanium ", 58 59 "teak ", 60 "oak ", 61 "cherry ", 62 "birch ", 63 "pine ", 64 "cedar ", 65 "redwood ", 66 "balsa ", 67 "ivory ", 68 "walnut ", 69 "maple ", 70 "mahogany ", 71 "elm ", 72 "palm ", 73 "wooden " 74 }; 75 76 char *gems[GEMS] = { 77 "diamond ", 78 "stibotantalite ", 79 "lapi-lazuli ", 80 "ruby ", 81 "emerald ", 82 "sapphire ", 83 "amethyst ", 84 "quartz ", 85 "tiger-eye ", 86 "opal ", 87 "agate ", 88 "turquoise ", 89 "pearl ", 90 "garnet " 91 }; 92 93 char *syllables[MAXSYLLABLES] = { 94 "blech ", 95 "foo ", 96 "barf ", 97 "rech ", 98 "bar ", 99 "blech ", 100 "quo ", 101 "bloto ", 102 "oh ", 103 "caca ", 104 "blorp ", 105 "erp ", 106 "festr ", 107 "rot ", 108 "slie ", 109 "snorf ", 110 "iky ", 111 "yuky ", 112 "ooze ", 113 "ah ", 114 "bahl ", 115 "zep ", 116 "druhl ", 117 "flem ", 118 "behil ", 119 "arek ", 120 "mep ", 121 "zihr ", 122 "grit ", 123 "kona ", 124 "kini ", 125 "ichi ", 126 "tims ", 127 "ogr ", 128 "oo ", 129 "ighr ", 130 "coph ", 131 "swerr ", 132 "mihln ", 133 "poxi " 134 }; 135 136 #define COMS 48 137 138 struct id_com_s { 139 short com_char; 140 char *com_desc; 141 }; 142 143 struct id_com_s com_id_tab[COMS] = { 144 '?', "? prints help", 145 'r', "r read scroll", 146 '/', "/ identify object", 147 'e', "e eat food", 148 'h', "h left ", 149 'w', "w wield a weapon", 150 'j', "j down", 151 'W', "W wear armor", 152 'k', "k up", 153 'T', "T take armor off", 154 'l', "l right", 155 'P', "P put on ring", 156 'y', "y up & left", 157 'R', "R remove ring", 158 'u', "u up & right", 159 'd', "d drop object", 160 'b', "b down & left", 161 'c', "c call object", 162 'n', "n down & right", 163 NULL, "<SHIFT><dir>: run that way", 164 ')', ") print current weapon", 165 NULL, "<CTRL><dir>: run till adjacent", 166 ']', "] print current armor", 167 'f', "f<dir> fight till death or near death", 168 '=', "= print current rings", 169 't', "t<dir> throw something", 170 '\001', "^A print Hp-raise average", 171 'm', "m<dir> move onto without picking up", 172 'z', "z<dir> zap a wand in a direction", 173 'o', "o examine/set options", 174 '^', "^<dir> identify trap type", 175 '\022', "^R redraw screen", 176 '&', "& save screen into 'rogue.screen'", 177 's', "s search for trap/secret door", 178 '\020', "^P repeat last message", 179 '>', "> go down a staircase", 180 '\033', "^[ cancel command", 181 '<', "< go up a staircase", 182 'S', "S save game", 183 '.', ". rest for a turn", 184 'Q', "Q quit", 185 ',', ", pick something up", 186 '!', "! shell escape", 187 'i', "i inventory", 188 'F', "F<dir> fight till either of you dies", 189 'I', "I inventory single item", 190 'v', "v print version number", 191 'q', "q quaff potion" 192 }; 193 194 extern boolean wizard; 195 extern char *m_names[], *more; 196 197 inventory(pack, mask) 198 object *pack; 199 unsigned short mask; 200 { 201 object *obj; 202 short i = 0, j, maxlen = 0, n; 203 char descs[MAX_PACK_COUNT+1][DCOLS]; 204 short row, col; 205 206 obj = pack->next_object; 207 208 if (!obj) { 209 message("your pack is empty", 0); 210 return; 211 } 212 while (obj) { 213 if (obj->what_is & mask) { 214 descs[i][0] = ' '; 215 descs[i][1] = obj->ichar; 216 descs[i][2] = ((obj->what_is & ARMOR) && obj->is_protected) 217 ? '}' : ')'; 218 descs[i][3] = ' '; 219 get_desc(obj, descs[i]+4); 220 if ((n = strlen(descs[i])) > maxlen) { 221 maxlen = n; 222 } 223 i++; 224 } 225 obj = obj->next_object; 226 } 227 (void) strcpy(descs[i++], press_space); 228 if (maxlen < 27) maxlen = 27; 229 col = DCOLS - (maxlen + 2); 230 231 for (row = 0; ((row < i) && (row < DROWS)); row++) { 232 if (row > 0) { 233 for (j = col; j < DCOLS; j++) { 234 descs[row-1][j-col] = mvinch(row, j); 235 } 236 descs[row-1][j-col] = 0; 237 } 238 mvaddstr(row, col, descs[row]); 239 clrtoeol(); 240 } 241 refresh(); 242 wait_for_ack(); 243 244 move(0, 0); 245 clrtoeol(); 246 247 for (j = 1; ((j < i) && (j < DROWS)); j++) { 248 mvaddstr(j, col, descs[j-1]); 249 } 250 } 251 252 id_com() 253 { 254 int ch = 0; 255 short i, j, k; 256 257 while (ch != CANCEL) { 258 check_message(); 259 message("Character you want help for (* for all):", 0); 260 261 refresh(); 262 ch = getchar(); 263 264 switch(ch) { 265 case LIST: 266 { 267 char save[(((COMS / 2) + (COMS % 2)) + 1)][DCOLS]; 268 short rows = (((COMS / 2) + (COMS % 2)) + 1); 269 boolean need_two_screens; 270 271 if (rows > LINES) { 272 need_two_screens = 1; 273 rows = LINES; 274 } 275 k = 0; 276 277 for (i = 0; i < rows; i++) { 278 for (j = 0; j < DCOLS; j++) { 279 save[i][j] = mvinch(i, j); 280 } 281 } 282 MORE: 283 for (i = 0; i < rows; i++) { 284 move(i, 0); 285 clrtoeol(); 286 } 287 for (i = 0; i < (rows-1); i++) { 288 if (i < (LINES-1)) { 289 if (((i + i) < COMS) && ((i+i+k) < COMS)) { 290 mvaddstr(i, 0, com_id_tab[i+i+k].com_desc); 291 } 292 if (((i + i + 1) < COMS) && ((i+i+k+1) < COMS)) { 293 mvaddstr(i, (DCOLS/2), 294 com_id_tab[i+i+k+1].com_desc); 295 } 296 } 297 } 298 mvaddstr(rows - 1, 0, need_two_screens ? more : press_space); 299 refresh(); 300 wait_for_ack(); 301 302 if (need_two_screens) { 303 k += ((rows-1) * 2); 304 need_two_screens = 0; 305 goto MORE; 306 } 307 for (i = 0; i < rows; i++) { 308 move(i, 0); 309 for (j = 0; j < DCOLS; j++) { 310 addch(save[i][j]); 311 } 312 } 313 } 314 break; 315 default: 316 if (!pr_com_id(ch)) { 317 if (!pr_motion_char(ch)) { 318 check_message(); 319 message("unknown character", 0); 320 } 321 } 322 ch = CANCEL; 323 break; 324 } 325 } 326 } 327 328 pr_com_id(ch) 329 int ch; 330 { 331 int i; 332 333 if (!get_com_id(&i, ch)) { 334 return(0); 335 } 336 check_message(); 337 message(com_id_tab[i].com_desc, 0); 338 return(1); 339 } 340 341 get_com_id(index, ch) 342 int *index; 343 short ch; 344 { 345 short i; 346 347 for (i = 0; i < COMS; i++) { 348 if (com_id_tab[i].com_char == ch) { 349 *index = i; 350 return(1); 351 } 352 } 353 return(0); 354 } 355 356 pr_motion_char(ch) 357 int ch; 358 { 359 if ( (ch == 'J') || 360 (ch == 'K') || 361 (ch == 'L') || 362 (ch == 'H') || 363 (ch == 'Y') || 364 (ch == 'U') || 365 (ch == 'N') || 366 (ch == 'B') || 367 (ch == '\012') || 368 (ch == '\013') || 369 (ch == '\010') || 370 (ch == '\014') || 371 (ch == '\025') || 372 (ch == '\031') || 373 (ch == '\016') || 374 (ch == '\002')) { 375 char until[18], buf[DCOLS]; 376 int n; 377 378 if (ch <= '\031') { 379 ch += 96; 380 (void) strcpy(until, "until adjascent"); 381 } else { 382 ch += 32; 383 until[0] = '\0'; 384 } 385 (void) get_com_id(&n, ch); 386 sprintf(buf, "run %s %s", com_id_tab[n].com_desc + 8, until); 387 check_message(); 388 message(buf, 0); 389 return(1); 390 } else { 391 return(0); 392 } 393 } 394 395 mix_colors() 396 { 397 short i, j, k; 398 char *t; 399 400 for (i = 0; i <= 32; i++) { 401 j = get_rand(0, (POTIONS - 1)); 402 k = get_rand(0, (POTIONS - 1)); 403 t = id_potions[j].title; 404 id_potions[j].title = id_potions[k].title; 405 id_potions[k].title = t; 406 } 407 } 408 409 make_scroll_titles() 410 { 411 short i, j, n; 412 short sylls, s; 413 414 for (i = 0; i < SCROLS; i++) { 415 sylls = get_rand(2, 5); 416 (void) strcpy(id_scrolls[i].title, "'"); 417 418 for (j = 0; j < sylls; j++) { 419 s = get_rand(1, (MAXSYLLABLES-1)); 420 (void) strcat(id_scrolls[i].title, syllables[s]); 421 } 422 n = strlen(id_scrolls[i].title); 423 (void) strcpy(id_scrolls[i].title+(n-1), "' "); 424 } 425 } 426 427 get_desc(obj, desc) 428 object *obj; 429 char *desc; 430 { 431 char *item_name; 432 struct id *id_table; 433 char more_info[32]; 434 short i; 435 436 if (obj->what_is == AMULET) { 437 (void) strcpy(desc, "the amulet of Yendor "); 438 return; 439 } 440 item_name = name_of(obj); 441 442 if (obj->what_is == GOLD) { 443 sprintf(desc, "%d pieces of gold", obj->quantity); 444 return; 445 } 446 447 if (obj->what_is != ARMOR) { 448 if (obj->quantity == 1) { 449 (void) strcpy(desc, "a "); 450 } else { 451 sprintf(desc, "%d ", obj->quantity); 452 } 453 } 454 if (obj->what_is == FOOD) { 455 if (obj->which_kind == RATION) { 456 if (obj->quantity > 1) { 457 sprintf(desc, "%d rations of ", obj->quantity); 458 } else { 459 (void) strcpy(desc, "some "); 460 } 461 } else { 462 (void) strcpy(desc, "a "); 463 } 464 (void) strcat(desc, item_name); 465 goto ANA; 466 } 467 id_table = get_id_table(obj); 468 469 if (wizard) { 470 goto ID; 471 } 472 if (obj->what_is & (WEAPON | ARMOR | WAND | RING)) { 473 goto CHECK; 474 } 475 476 switch(id_table[obj->which_kind].id_status) { 477 case UNIDENTIFIED: 478 CHECK: 479 switch(obj->what_is) { 480 case SCROL: 481 (void) strcat(desc, item_name); 482 (void) strcat(desc, "entitled: "); 483 (void) strcat(desc, id_table[obj->which_kind].title); 484 break; 485 case POTION: 486 (void) strcat(desc, id_table[obj->which_kind].title); 487 (void) strcat(desc, item_name); 488 break; 489 case WAND: 490 case RING: 491 if (obj->identified || 492 (id_table[obj->which_kind].id_status == IDENTIFIED)) { 493 goto ID; 494 } 495 if (id_table[obj->which_kind].id_status == CALLED) { 496 goto CALL; 497 } 498 (void) strcat(desc, id_table[obj->which_kind].title); 499 (void) strcat(desc, item_name); 500 break; 501 case ARMOR: 502 if (obj->identified) { 503 goto ID; 504 } 505 (void) strcpy(desc, id_table[obj->which_kind].title); 506 break; 507 case WEAPON: 508 if (obj->identified) { 509 goto ID; 510 } 511 (void) strcat(desc, name_of(obj)); 512 break; 513 } 514 break; 515 case CALLED: 516 CALL: switch(obj->what_is) { 517 case SCROL: 518 case POTION: 519 case WAND: 520 case RING: 521 (void) strcat(desc, item_name); 522 (void) strcat(desc, "called "); 523 (void) strcat(desc, id_table[obj->which_kind].title); 524 break; 525 } 526 break; 527 case IDENTIFIED: 528 ID: switch(obj->what_is) { 529 case SCROL: 530 case POTION: 531 (void) strcat(desc, item_name); 532 (void) strcat(desc, id_table[obj->which_kind].real); 533 break; 534 case RING: 535 if (wizard || obj->identified) { 536 if ((obj->which_kind == DEXTERITY) || 537 (obj->which_kind == ADD_STRENGTH)) { 538 sprintf(more_info, "%s%d ", ((obj->class > 0) ? "+" : ""), 539 obj->class); 540 (void) strcat(desc, more_info); 541 } 542 } 543 (void) strcat(desc, item_name); 544 (void) strcat(desc, id_table[obj->which_kind].real); 545 break; 546 case WAND: 547 (void) strcat(desc, item_name); 548 (void) strcat(desc, id_table[obj->which_kind].real); 549 if (wizard || obj->identified) { 550 sprintf(more_info, "[%d]", obj->class); 551 (void) strcat(desc, more_info); 552 } 553 break; 554 case ARMOR: 555 sprintf(desc, "%s%d ", ((obj->d_enchant >= 0) ? "+" : ""), 556 obj->d_enchant); 557 (void) strcat(desc, id_table[obj->which_kind].title); 558 sprintf(more_info, "[%d] ", get_armor_class(obj)); 559 (void) strcat(desc, more_info); 560 break; 561 case WEAPON: 562 sprintf(desc+strlen(desc), "%s%d,%s%d ", 563 ((obj->hit_enchant >= 0) ? "+" : ""), obj->hit_enchant, 564 ((obj->d_enchant >= 0) ? "+" : ""), obj->d_enchant); 565 (void) strcat(desc, name_of(obj)); 566 break; 567 } 568 break; 569 } 570 ANA: 571 if (!strncmp(desc, "a ", 2)) { 572 if (is_vowel(desc[2])) { 573 for (i = strlen(desc) + 1; i > 1; i--) { 574 desc[i] = desc[i-1]; 575 } 576 desc[1] = 'n'; 577 } 578 } 579 if (obj->in_use_flags & BEING_WIELDED) { 580 (void) strcat(desc, "in hand"); 581 } else if (obj->in_use_flags & BEING_WORN) { 582 (void) strcat(desc, "being worn"); 583 } else if (obj->in_use_flags & ON_LEFT_HAND) { 584 (void) strcat(desc, "on left hand"); 585 } else if (obj->in_use_flags & ON_RIGHT_HAND) { 586 (void) strcat(desc, "on right hand"); 587 } 588 } 589 590 get_wand_and_ring_materials() 591 { 592 short i, j; 593 boolean used[WAND_MATERIALS]; 594 595 for (i = 0; i < WAND_MATERIALS; i++) { 596 used[i] = 0; 597 } 598 for (i = 0; i < WANDS; i++) { 599 do { 600 j = get_rand(0, WAND_MATERIALS-1); 601 } while (used[j]); 602 used[j] = 1; 603 (void) strcpy(id_wands[i].title, wand_materials[j]); 604 is_wood[i] = (j > MAX_METAL); 605 } 606 for (i = 0; i < GEMS; i++) { 607 used[i] = 0; 608 } 609 for (i = 0; i < RINGS; i++) { 610 do { 611 j = get_rand(0, GEMS-1); 612 } while (used[j]); 613 used[j] = 1; 614 (void) strcpy(id_rings[i].title, gems[j]); 615 } 616 } 617 618 single_inv(ichar) 619 short ichar; 620 { 621 short ch; 622 char desc[DCOLS]; 623 object *obj; 624 625 ch = ichar ? ichar : pack_letter("inventory what?", ALL_OBJECTS); 626 627 if (ch == CANCEL) { 628 return; 629 } 630 if (!(obj = get_letter_object(ch))) { 631 message("no such item.", 0); 632 return; 633 } 634 desc[0] = ch; 635 desc[1] = ((obj->what_is & ARMOR) && obj->is_protected) ? '}' : ')'; 636 desc[2] = ' '; 637 desc[3] = 0; 638 get_desc(obj, desc+3); 639 message(desc, 0); 640 } 641 642 struct id * 643 get_id_table(obj) 644 object *obj; 645 { 646 switch(obj->what_is) { 647 case SCROL: 648 return(id_scrolls); 649 case POTION: 650 return(id_potions); 651 case WAND: 652 return(id_wands); 653 case RING: 654 return(id_rings); 655 case WEAPON: 656 return(id_weapons); 657 case ARMOR: 658 return(id_armors); 659 } 660 return((struct id *) 0); 661 } 662 663 inv_armor_weapon(is_weapon) 664 boolean is_weapon; 665 { 666 if (is_weapon) { 667 if (rogue.weapon) { 668 single_inv(rogue.weapon->ichar); 669 } else { 670 message("not wielding anything", 0); 671 } 672 } else { 673 if (rogue.armor) { 674 single_inv(rogue.armor->ichar); 675 } else { 676 message("not wearing anything", 0); 677 } 678 } 679 } 680 681 id_type() 682 { 683 char *id; 684 int ch; 685 char buf[DCOLS]; 686 687 message("what do you want identified?", 0); 688 689 ch = rgetchar(); 690 691 if ((ch >= 'A') && (ch <= 'Z')) { 692 id = m_names[ch-'A']; 693 } else if (ch < 32) { 694 check_message(); 695 return; 696 } else { 697 switch(ch) { 698 case '@': 699 id = "you"; 700 break; 701 case '%': 702 id = "staircase"; 703 break; 704 case '^': 705 id = "trap"; 706 break; 707 case '+': 708 id = "door"; 709 break; 710 case '-': 711 case '|': 712 id = "wall of a room"; 713 break; 714 case '.': 715 id = "floor"; 716 break; 717 case '#': 718 id = "passage"; 719 break; 720 case ' ': 721 id = "solid rock"; 722 break; 723 case '=': 724 id = "ring"; 725 break; 726 case '?': 727 id = "scroll"; 728 break; 729 case '!': 730 id = "potion"; 731 break; 732 case '/': 733 id = "wand or staff"; 734 break; 735 case ')': 736 id = "weapon"; 737 break; 738 case ']': 739 id = "armor"; 740 break; 741 case '*': 742 id = "gold"; 743 break; 744 case ':': 745 id = "food"; 746 break; 747 case ',': 748 id = "the Amulet of Yendor"; 749 break; 750 default: 751 id = "unknown character"; 752 break; 753 } 754 } 755 check_message(); 756 sprintf(buf, "'%c': %s", ch, id); 757 message(buf, 0); 758 } 759