1 /* 2 * object.c 3 * 4 * This source herein may be modified and/or distributed by anybody who 5 * so desires, with the following restrictions: 6 * 1.) No portion of this notice shall be removed. 7 * 2.) Credit shall not be taken for the creation of this source. 8 * 3.) This code is not to be traded, sold, or used for personal 9 * gain or profit. 10 * 11 */ 12 13 #ifndef lint 14 static char sccsid[] = "@(#)object.c 5.1 (Berkeley) 11/25/87"; 15 #endif /* not lint */ 16 17 #include "rogue.h" 18 19 object level_objects; 20 unsigned short dungeon[DROWS][DCOLS]; 21 short foods = 0; 22 object *free_list = (object *) 0; 23 char *fruit = (char *) 0; 24 25 fighter rogue = { 26 INIT_AW, /* armor, weapon */ 27 INIT_RINGS, /* rings */ 28 INIT_HP, /* Hp current,max */ 29 INIT_STR, /* Str current,max */ 30 INIT_PACK, /* pack */ 31 INIT_GOLD, /* gold */ 32 INIT_EXP, /* exp level,points */ 33 0, 0, /* row, col */ 34 INIT_CHAR, /* char */ 35 INIT_MOVES /* moves */ 36 }; 37 38 struct id id_potions[POTIONS] = { 39 {100, "blue \0 ", "of increase strength ", 0}, 40 {250, "red \0 ", "of restore strength ", 0}, 41 {100, "green \0 ", "of healing ", 0}, 42 {200, "grey \0 ", "of extra healing ", 0}, 43 {10, "brown \0 ", "of poison ", 0}, 44 {300, "clear \0 ", "of raise level ", 0}, 45 {10, "pink \0 ", "of blindness ", 0}, 46 {25, "white \0 ", "of hallucination ", 0}, 47 {100, "purple \0 ", "of detect monster ", 0}, 48 {100, "black \0 ", "of detect things ", 0}, 49 {10, "yellow \0 ", "of confusion ", 0}, 50 {80, "plaid \0 ", "of levitation ", 0}, 51 {150, "burgundy \0 ", "of haste self ", 0}, 52 {145, "beige \0 ", "of see invisible ", 0} 53 }; 54 55 struct id id_scrolls[SCROLS] = { 56 {505, " ", "of protect armor ", 0}, 57 {200, " ", "of hold monster ", 0}, 58 {235, " ", "of enchant weapon ", 0}, 59 {235, " ", "of enchant armor ", 0}, 60 {175, " ", "of identify ", 0}, 61 {190, " ", "of teleportation ", 0}, 62 {25, " ", "of sleep ", 0}, 63 {610, " ", "of scare monster ", 0}, 64 {210, " ", "of remove curse ", 0}, 65 {80, " ", "of create monster ",0}, 66 {25, " ", "of aggravate monster ",0}, 67 {180, " ", "of magic mapping ", 0}, 68 {90, " ", "of confuse monster ", 0} 69 }; 70 71 struct id id_weapons[WEAPONS] = { 72 {150, "short bow ", "", 0}, 73 {8, "darts ", "", 0}, 74 {15, "arrows ", "", 0}, 75 {27, "daggers ", "", 0}, 76 {35, "shurikens ", "", 0}, 77 {360, "mace ", "", 0}, 78 {470, "long sword ", "", 0}, 79 {580, "two-handed sword ", "", 0} 80 }; 81 82 struct id id_armors[ARMORS] = { 83 {300, "leather armor ", "", (UNIDENTIFIED)}, 84 {300, "ring mail ", "", (UNIDENTIFIED)}, 85 {400, "scale mail ", "", (UNIDENTIFIED)}, 86 {500, "chain mail ", "", (UNIDENTIFIED)}, 87 {600, "banded mail ", "", (UNIDENTIFIED)}, 88 {600, "splint mail ", "", (UNIDENTIFIED)}, 89 {700, "plate mail ", "", (UNIDENTIFIED)} 90 }; 91 92 struct id id_wands[WANDS] = { 93 {25, " ", "of teleport away ",0}, 94 {50, " ", "of slow monster ", 0}, 95 {8, " ", "of invisibility ",0}, 96 {55, " ", "of polymorph ",0}, 97 {2, " ", "of haste monster ",0}, 98 {20, " ", "of magic missile ",0}, 99 {20, " ", "of cancellation ",0}, 100 {0, " ", "of do nothing ",0}, 101 {35, " ", "of drain life ",0}, 102 {20, " ", "of cold ",0}, 103 {20, " ", "of fire ",0} 104 }; 105 106 struct id id_rings[RINGS] = { 107 {250, " ", "of stealth ",0}, 108 {100, " ", "of teleportation ", 0}, 109 {255, " ", "of regeneration ",0}, 110 {295, " ", "of slow digestion ",0}, 111 {200, " ", "of add strength ",0}, 112 {250, " ", "of sustain strength ",0}, 113 {250, " ", "of dexterity ",0}, 114 {25, " ", "of adornment ",0}, 115 {300, " ", "of see invisible ",0}, 116 {290, " ", "of maintain armor ",0}, 117 {270, " ", "of searching ",0}, 118 }; 119 120 extern short cur_level, max_level; 121 extern short party_room; 122 extern char *error_file; 123 extern boolean is_wood[]; 124 125 put_objects() 126 { 127 short i, n; 128 object *obj; 129 130 if (cur_level < max_level) { 131 return; 132 } 133 n = coin_toss() ? get_rand(2, 4) : get_rand(3, 5); 134 while (rand_percent(33)) { 135 n++; 136 } 137 if (party_room != NO_ROOM) { 138 make_party(); 139 } 140 for (i = 0; i < n; i++) { 141 obj = gr_object(); 142 rand_place(obj); 143 } 144 put_gold(); 145 } 146 147 put_gold() 148 { 149 short i, j; 150 short row,col; 151 boolean is_maze, is_room; 152 153 for (i = 0; i < MAXROOMS; i++) { 154 is_maze = (rooms[i].is_room & R_MAZE) ? 1 : 0; 155 is_room = (rooms[i].is_room & R_ROOM) ? 1 : 0; 156 157 if (!(is_room || is_maze)) { 158 continue; 159 } 160 if (is_maze || rand_percent(GOLD_PERCENT)) { 161 for (j = 0; j < 50; j++) { 162 row = get_rand(rooms[i].top_row+1, 163 rooms[i].bottom_row-1); 164 col = get_rand(rooms[i].left_col+1, 165 rooms[i].right_col-1); 166 if ((dungeon[row][col] == FLOOR) || 167 (dungeon[row][col] == TUNNEL)) { 168 plant_gold(row, col, is_maze); 169 break; 170 } 171 } 172 } 173 } 174 } 175 176 plant_gold(row, col, is_maze) 177 short row, col; 178 boolean is_maze; 179 { 180 object *obj; 181 182 obj = alloc_object(); 183 obj->row = row; obj->col = col; 184 obj->what_is = GOLD; 185 obj->quantity = get_rand((2 * cur_level), (16 * cur_level)); 186 if (is_maze) { 187 obj->quantity += obj->quantity / 2; 188 } 189 dungeon[row][col] |= OBJECT; 190 (void) add_to_pack(obj, &level_objects, 0); 191 } 192 193 place_at(obj, row, col) 194 object *obj; 195 { 196 obj->row = row; 197 obj->col = col; 198 dungeon[row][col] |= OBJECT; 199 (void) add_to_pack(obj, &level_objects, 0); 200 } 201 202 object * 203 object_at(pack, row, col) 204 register object *pack; 205 short row, col; 206 { 207 object *obj = (object *) 0; 208 209 if (dungeon[row][col] & (MONSTER | OBJECT)) { 210 obj = pack->next_object; 211 212 while (obj && ((obj->row != row) || (obj->col != col))) { 213 obj = obj->next_object; 214 } 215 if (!obj) { 216 message("object_at(): inconsistent", 1); 217 } 218 } 219 return(obj); 220 } 221 222 object * 223 get_letter_object(ch) 224 { 225 object *obj; 226 227 obj = rogue.pack.next_object; 228 229 while (obj && (obj->ichar != ch)) { 230 obj = obj->next_object; 231 } 232 return(obj); 233 } 234 235 free_stuff(objlist) 236 object *objlist; 237 { 238 object *obj; 239 240 while (objlist->next_object) { 241 obj = objlist->next_object; 242 objlist->next_object = 243 objlist->next_object->next_object; 244 free_object(obj); 245 } 246 } 247 248 char * 249 name_of(obj) 250 object *obj; 251 { 252 char *retstring; 253 254 switch(obj->what_is) { 255 case SCROL: 256 retstring = obj->quantity > 1 ? "scrolls " : "scroll "; 257 break; 258 case POTION: 259 retstring = obj->quantity > 1 ? "potions " : "potion "; 260 break; 261 case FOOD: 262 if (obj->which_kind == RATION) { 263 retstring = "food "; 264 } else { 265 retstring = fruit; 266 } 267 break; 268 case WAND: 269 retstring = is_wood[obj->which_kind] ? "staff " : "wand "; 270 break; 271 case WEAPON: 272 switch(obj->which_kind) { 273 case DART: 274 retstring=obj->quantity > 1 ? "darts " : "dart "; 275 break; 276 case ARROW: 277 retstring=obj->quantity > 1 ? "arrows " : "arrow "; 278 break; 279 case DAGGER: 280 retstring=obj->quantity > 1 ? "daggers " : "dagger "; 281 break; 282 case SHURIKEN: 283 retstring=obj->quantity > 1?"shurikens ":"shuriken "; 284 break; 285 default: 286 retstring = id_weapons[obj->which_kind].title; 287 } 288 break; 289 case ARMOR: 290 retstring = "armor "; 291 break; 292 case RING: 293 retstring = "ring "; 294 break; 295 case AMULET: 296 retstring = "amulet "; 297 break; 298 default: 299 retstring = "unknown "; 300 break; 301 } 302 return(retstring); 303 } 304 305 object * 306 gr_object() 307 { 308 object *obj; 309 310 obj = alloc_object(); 311 312 if (foods < (cur_level / 3)) { 313 obj->what_is = FOOD; 314 foods++; 315 } else { 316 obj->what_is = gr_what_is(); 317 } 318 switch(obj->what_is) { 319 case SCROL: 320 gr_scroll(obj); 321 break; 322 case POTION: 323 gr_potion(obj); 324 break; 325 case WEAPON: 326 gr_weapon(obj, 1); 327 break; 328 case ARMOR: 329 gr_armor(obj); 330 break; 331 case WAND: 332 gr_wand(obj); 333 break; 334 case FOOD: 335 get_food(obj, 0); 336 break; 337 case RING: 338 gr_ring(obj, 1); 339 break; 340 } 341 return(obj); 342 } 343 344 unsigned short 345 gr_what_is() 346 { 347 short percent; 348 unsigned short what_is; 349 350 percent = get_rand(1, 91); 351 352 if (percent <= 30) { 353 what_is = SCROL; 354 } else if (percent <= 60) { 355 what_is = POTION; 356 } else if (percent <= 64) { 357 what_is = WAND; 358 } else if (percent <= 74) { 359 what_is = WEAPON; 360 } else if (percent <= 83) { 361 what_is = ARMOR; 362 } else if (percent <= 88) { 363 what_is = FOOD; 364 } else { 365 what_is = RING; 366 } 367 return(what_is); 368 } 369 370 gr_scroll(obj) 371 object *obj; 372 { 373 short percent; 374 375 percent = get_rand(0, 91); 376 377 obj->what_is = SCROL; 378 379 if (percent <= 5) { 380 obj->which_kind = PROTECT_ARMOR; 381 } else if (percent <= 10) { 382 obj->which_kind = HOLD_MONSTER; 383 } else if (percent <= 20) { 384 obj->which_kind = CREATE_MONSTER; 385 } else if (percent <= 35) { 386 obj->which_kind = IDENTIFY; 387 } else if (percent <= 43) { 388 obj->which_kind = TELEPORT; 389 } else if (percent <= 50) { 390 obj->which_kind = SLEEP; 391 } else if (percent <= 55) { 392 obj->which_kind = SCARE_MONSTER; 393 } else if (percent <= 64) { 394 obj->which_kind = REMOVE_CURSE; 395 } else if (percent <= 69) { 396 obj->which_kind = ENCH_ARMOR; 397 } else if (percent <= 74) { 398 obj->which_kind = ENCH_WEAPON; 399 } else if (percent <= 80) { 400 obj->which_kind = AGGRAVATE_MONSTER; 401 } else if (percent <= 86) { 402 obj->which_kind = CON_MON; 403 } else { 404 obj->which_kind = MAGIC_MAPPING; 405 } 406 } 407 408 gr_potion(obj) 409 object *obj; 410 { 411 short percent; 412 413 percent = get_rand(1, 118); 414 415 obj->what_is = POTION; 416 417 if (percent <= 5) { 418 obj->which_kind = RAISE_LEVEL; 419 } else if (percent <= 15) { 420 obj->which_kind = DETECT_OBJECTS; 421 } else if (percent <= 25) { 422 obj->which_kind = DETECT_MONSTER; 423 } else if (percent <= 35) { 424 obj->which_kind = INCREASE_STRENGTH; 425 } else if (percent <= 45) { 426 obj->which_kind = RESTORE_STRENGTH; 427 } else if (percent <= 55) { 428 obj->which_kind = HEALING; 429 } else if (percent <= 65) { 430 obj->which_kind = EXTRA_HEALING; 431 } else if (percent <= 75) { 432 obj->which_kind = BLINDNESS; 433 } else if (percent <= 85) { 434 obj->which_kind = HALLUCINATION; 435 } else if (percent <= 95) { 436 obj->which_kind = CONFUSION; 437 } else if (percent <= 105) { 438 obj->which_kind = POISON; 439 } else if (percent <= 110) { 440 obj->which_kind = LEVITATION; 441 } else if (percent <= 114) { 442 obj->which_kind = HASTE_SELF; 443 } else { 444 obj->which_kind = SEE_INVISIBLE; 445 } 446 } 447 448 gr_weapon(obj, assign_wk) 449 object *obj; 450 int assign_wk; 451 { 452 short percent; 453 short i; 454 short blessing, increment; 455 456 obj->what_is = WEAPON; 457 if (assign_wk) { 458 obj->which_kind = get_rand(0, (WEAPONS - 1)); 459 } 460 if ((obj->which_kind == ARROW) || (obj->which_kind == DAGGER) || 461 (obj->which_kind == SHURIKEN) | (obj->which_kind == DART)) { 462 obj->quantity = get_rand(3, 15); 463 obj->quiver = get_rand(0, 126); 464 } else { 465 obj->quantity = 1; 466 } 467 obj->hit_enchant = obj->d_enchant = 0; 468 469 percent = get_rand(1, 96); 470 blessing = get_rand(1, 3); 471 472 if (percent <= 16) { 473 increment = 1; 474 } else if (percent <= 32) { 475 increment = -1; 476 obj->is_cursed = 1; 477 } 478 if (percent <= 32) { 479 for (i = 0; i < blessing; i++) { 480 if (coin_toss()) { 481 obj->hit_enchant += increment; 482 } else { 483 obj->d_enchant += increment; 484 } 485 } 486 } 487 switch(obj->which_kind) { 488 case BOW: 489 case DART: 490 obj->damage = "1d1"; 491 break; 492 case ARROW: 493 obj->damage = "1d2"; 494 break; 495 case DAGGER: 496 obj->damage = "1d3"; 497 break; 498 case SHURIKEN: 499 obj->damage = "1d4"; 500 break; 501 case MACE: 502 obj->damage = "2d3"; 503 break; 504 case LONG_SWORD: 505 obj->damage = "3d4"; 506 break; 507 case TWO_HANDED_SWORD: 508 obj->damage = "4d5"; 509 break; 510 } 511 } 512 513 gr_armor(obj) 514 object *obj; 515 { 516 short percent; 517 short blessing; 518 519 obj->what_is = ARMOR; 520 obj->which_kind = get_rand(0, (ARMORS - 1)); 521 obj->class = obj->which_kind + 2; 522 if ((obj->which_kind == PLATE) || (obj->which_kind == SPLINT)) { 523 obj->class--; 524 } 525 obj->is_protected = 0; 526 obj->d_enchant = 0; 527 528 percent = get_rand(1, 100); 529 blessing = get_rand(1, 3); 530 531 if (percent <= 16) { 532 obj->is_cursed = 1; 533 obj->d_enchant -= blessing; 534 } else if (percent <= 33) { 535 obj->d_enchant += blessing; 536 } 537 } 538 539 gr_wand(obj) 540 object *obj; 541 { 542 obj->what_is = WAND; 543 obj->which_kind = get_rand(0, (WANDS - 1)); 544 obj->class = get_rand(3, 7); 545 } 546 547 get_food(obj, force_ration) 548 object *obj; 549 boolean force_ration; 550 { 551 obj->what_is = FOOD; 552 553 if (force_ration || rand_percent(80)) { 554 obj->which_kind = RATION; 555 } else { 556 obj->which_kind = FRUIT; 557 } 558 } 559 560 put_stairs() 561 { 562 short row, col; 563 564 gr_row_col(&row, &col, (FLOOR | TUNNEL)); 565 dungeon[row][col] |= STAIRS; 566 } 567 568 get_armor_class(obj) 569 object *obj; 570 { 571 if (obj) { 572 return(obj->class + obj->d_enchant); 573 } 574 return(0); 575 } 576 577 object * 578 alloc_object() 579 { 580 object *obj; 581 582 if (free_list) { 583 obj = free_list; 584 free_list = free_list->next_object; 585 } else if (!(obj = (object *) md_malloc(sizeof(object)))) { 586 message("cannot allocate object, saving game", 0); 587 save_into_file(error_file); 588 } 589 obj->quantity = 1; 590 obj->ichar = 'L'; 591 obj->picked_up = obj->is_cursed = 0; 592 obj->in_use_flags = NOT_USED; 593 obj->identified = UNIDENTIFIED; 594 obj->damage = "1d1"; 595 return(obj); 596 } 597 598 free_object(obj) 599 object *obj; 600 { 601 obj->next_object = free_list; 602 free_list = obj; 603 } 604 605 make_party() 606 { 607 short n; 608 609 party_room = gr_room(); 610 611 n = rand_percent(99) ? party_objects(party_room) : 11; 612 if (rand_percent(99)) { 613 party_monsters(party_room, n); 614 } 615 } 616 617 show_objects() 618 { 619 object *obj; 620 short mc, rc, row, col; 621 object *monster; 622 623 obj = level_objects.next_object; 624 625 while (obj) { 626 row = obj->row; 627 col = obj->col; 628 629 rc = get_mask_char(obj->what_is); 630 631 if (dungeon[row][col] & MONSTER) { 632 if (monster = object_at(&level_monsters, row, col)) { 633 monster->trail_char = rc; 634 } 635 } 636 mc = mvinch(row, col); 637 if (((mc < 'A') || (mc > 'Z')) && 638 ((row != rogue.row) || (col != rogue.col))) { 639 mvaddch(row, col, rc); 640 } 641 obj = obj->next_object; 642 } 643 644 monster = level_monsters.next_object; 645 646 while (monster) { 647 if (monster->m_flags & IMITATES) { 648 mvaddch(monster->row, monster->col, (int) monster->disguise); 649 } 650 monster = monster->next_monster; 651 } 652 } 653 654 put_amulet() 655 { 656 object *obj; 657 658 obj = alloc_object(); 659 obj->what_is = AMULET; 660 rand_place(obj); 661 } 662 663 rand_place(obj) 664 object *obj; 665 { 666 short row, col; 667 668 gr_row_col(&row, &col, (FLOOR | TUNNEL)); 669 place_at(obj, row, col); 670 } 671 672 c_object_for_wizard() 673 { 674 short ch, max, wk; 675 object *obj; 676 char buf[80]; 677 678 if (pack_count((object *) 0) >= MAX_PACK_COUNT) { 679 message("pack full", 0); 680 return; 681 } 682 message("type of object?", 0); 683 684 while (r_index("!?:)]=/,\033", (ch = rgetchar()), 0) == -1) { 685 sound_bell(); 686 } 687 check_message(); 688 689 if (ch == '\033') { 690 return; 691 } 692 obj = alloc_object(); 693 694 switch(ch) { 695 case '!': 696 obj->what_is = POTION; 697 max = POTIONS - 1; 698 break; 699 case '?': 700 obj->what_is = SCROL; 701 max = SCROLS - 1; 702 break; 703 case ',': 704 obj->what_is = AMULET; 705 break; 706 case ':': 707 get_food(obj, 0); 708 break; 709 case ')': 710 gr_weapon(obj, 0); 711 max = WEAPONS - 1; 712 break; 713 case ']': 714 gr_armor(obj); 715 max = ARMORS - 1; 716 break; 717 case '/': 718 gr_wand(obj); 719 max = WANDS - 1; 720 break; 721 case '=': 722 max = RINGS - 1; 723 obj->what_is = RING; 724 break; 725 } 726 if ((ch != ',') && (ch != ':')) { 727 GIL: 728 if (get_input_line("which kind?", "", buf, "", 0, 1)) { 729 wk = get_number(buf); 730 if ((wk >= 0) && (wk <= max)) { 731 obj->which_kind = (unsigned short) wk; 732 if (obj->what_is == RING) { 733 gr_ring(obj, 0); 734 } 735 } else { 736 sound_bell(); 737 goto GIL; 738 } 739 } else { 740 free_object(obj); 741 return; 742 } 743 } 744 get_desc(obj, buf); 745 message(buf, 0); 746 (void) add_to_pack(obj, &rogue.pack, 1); 747 } 748