1 /* $NetBSD: use.c,v 1.5 1998/11/10 13:01:32 hubertf Exp $ */ 2 3 /* 4 * Copyright (c) 1988, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Timothy C. Stoehr. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 */ 38 39 #include <sys/cdefs.h> 40 #ifndef lint 41 #if 0 42 static char sccsid[] = "@(#)use.c 8.1 (Berkeley) 5/31/93"; 43 #else 44 __RCSID("$NetBSD: use.c,v 1.5 1998/11/10 13:01:32 hubertf Exp $"); 45 #endif 46 #endif /* not lint */ 47 48 /* 49 * use.c 50 * 51 * This source herein may be modified and/or distributed by anybody who 52 * so desires, with the following restrictions: 53 * 1.) No portion of this notice shall be removed. 54 * 2.) Credit shall not be taken for the creation of this source. 55 * 3.) This code is not to be traded, sold, or used for personal 56 * gain or profit. 57 * 58 */ 59 60 #include "rogue.h" 61 62 short halluc = 0; 63 short blind = 0; 64 short confused = 0; 65 short levitate = 0; 66 short haste_self = 0; 67 boolean see_invisible = 0; 68 short extra_hp = 0; 69 boolean detect_monster = 0; 70 boolean con_mon = 0; 71 const char *strange_feeling = "you have a strange feeling for a moment, then it passes"; 72 73 void 74 quaff() 75 { 76 short ch; 77 char buf[80]; 78 object *obj; 79 80 ch = pack_letter("quaff what?", POTION); 81 82 if (ch == CANCEL) { 83 return; 84 } 85 if (!(obj = get_letter_object(ch))) { 86 message("no such item.", 0); 87 return; 88 } 89 if (obj->what_is != POTION) { 90 message("you can't drink that", 0); 91 return; 92 } 93 switch(obj->which_kind) { 94 case INCREASE_STRENGTH: 95 message("you feel stronger now, what bulging muscles!", 96 0); 97 rogue.str_current++; 98 if (rogue.str_current > rogue.str_max) { 99 rogue.str_max = rogue.str_current; 100 } 101 break; 102 case RESTORE_STRENGTH: 103 rogue.str_current = rogue.str_max; 104 message("this tastes great, you feel warm all over", 0); 105 break; 106 case HEALING: 107 message("you begin to feel better", 0); 108 potion_heal(0); 109 break; 110 case EXTRA_HEALING: 111 message("you begin to feel much better", 0); 112 potion_heal(1); 113 break; 114 case POISON: 115 if (!sustain_strength) { 116 rogue.str_current -= get_rand(1, 3); 117 if (rogue.str_current < 1) { 118 rogue.str_current = 1; 119 } 120 } 121 message("you feel very sick now", 0); 122 if (halluc) { 123 unhallucinate(); 124 } 125 break; 126 case RAISE_LEVEL: 127 rogue.exp_points = level_points[rogue.exp - 1]; 128 message("you suddenly feel much more skillful", 0); 129 add_exp(1, 1); 130 break; 131 case BLINDNESS: 132 go_blind(); 133 break; 134 case HALLUCINATION: 135 message("oh wow, everything seems so cosmic", 0); 136 halluc += get_rand(500, 800); 137 break; 138 case DETECT_MONSTER: 139 show_monsters(); 140 if (!(level_monsters.next_monster)) { 141 message(strange_feeling, 0); 142 } 143 break; 144 case DETECT_OBJECTS: 145 if (level_objects.next_object) { 146 if (!blind) { 147 show_objects(); 148 } 149 } else { 150 message(strange_feeling, 0); 151 } 152 break; 153 case CONFUSION: 154 message((halluc ? "what a trippy feeling" : 155 "you feel confused"), 0); 156 cnfs(); 157 break; 158 case LEVITATION: 159 message("you start to float in the air", 0); 160 levitate += get_rand(15, 30); 161 being_held = bear_trap = 0; 162 break; 163 case HASTE_SELF: 164 message("you feel yourself moving much faster", 0); 165 haste_self += get_rand(11, 21); 166 if (!(haste_self % 2)) { 167 haste_self++; 168 } 169 break; 170 case SEE_INVISIBLE: 171 sprintf(buf, "hmm, this potion tastes like %sjuice", fruit); 172 message(buf, 0); 173 if (blind) { 174 unblind(); 175 } 176 see_invisible = 1; 177 relight(); 178 break; 179 } 180 print_stats((STAT_STRENGTH | STAT_HP)); 181 if (id_potions[obj->which_kind].id_status != CALLED) { 182 id_potions[obj->which_kind].id_status = IDENTIFIED; 183 } 184 vanish(obj, 1, &rogue.pack); 185 } 186 187 void 188 read_scroll() 189 { 190 short ch; 191 object *obj; 192 char msg[DCOLS]; 193 194 ch = pack_letter("read what?", SCROL); 195 196 if (ch == CANCEL) { 197 return; 198 } 199 if (!(obj = get_letter_object(ch))) { 200 message("no such item.", 0); 201 return; 202 } 203 if (obj->what_is != SCROL) { 204 message("you can't read that", 0); 205 return; 206 } 207 switch(obj->which_kind) { 208 case SCARE_MONSTER: 209 message("you hear a maniacal laughter in the distance", 210 0); 211 break; 212 case HOLD_MONSTER: 213 hold_monster(); 214 break; 215 case ENCH_WEAPON: 216 if (rogue.weapon) { 217 if (rogue.weapon->what_is == WEAPON) { 218 sprintf(msg, "your %sglow%s %sfor a moment", 219 name_of(rogue.weapon), 220 ((rogue.weapon->quantity <= 1) ? "s" : ""), 221 get_ench_color()); 222 message(msg, 0); 223 if (coin_toss()) { 224 rogue.weapon->hit_enchant++; 225 } else { 226 rogue.weapon->d_enchant++; 227 } 228 } 229 rogue.weapon->is_cursed = 0; 230 } else { 231 message("your hands tingle", 0); 232 } 233 break; 234 case ENCH_ARMOR: 235 if (rogue.armor) { 236 sprintf(msg, "your armor glows %sfor a moment", 237 get_ench_color()); 238 message(msg, 0); 239 rogue.armor->d_enchant++; 240 rogue.armor->is_cursed = 0; 241 print_stats(STAT_ARMOR); 242 } else { 243 message("your skin crawls", 0); 244 } 245 break; 246 case IDENTIFY: 247 message("this is a scroll of identify", 0); 248 obj->identified = 1; 249 id_scrolls[obj->which_kind].id_status = IDENTIFIED; 250 idntfy(); 251 break; 252 case TELEPORT: 253 tele(); 254 break; 255 case SLEEP: 256 message("you fall asleep", 0); 257 take_a_nap(); 258 break; 259 case PROTECT_ARMOR: 260 if (rogue.armor) { 261 message( "your armor is covered by a shimmering gold shield",0); 262 rogue.armor->is_protected = 1; 263 rogue.armor->is_cursed = 0; 264 } else { 265 message("your acne seems to have disappeared", 0); 266 } 267 break; 268 case REMOVE_CURSE: 269 message((!halluc) ? 270 "you feel as though someone is watching over you" : 271 "you feel in touch with the universal oneness", 0); 272 uncurse_all(); 273 break; 274 case CREATE_MONSTER: 275 create_monster(); 276 break; 277 case AGGRAVATE_MONSTER: 278 aggravate(); 279 break; 280 case MAGIC_MAPPING: 281 message("this scroll seems to have a map on it", 0); 282 draw_magic_map(); 283 break; 284 case CON_MON: 285 con_mon = 1; 286 sprintf(msg, "your hands glow %sfor a moment", get_ench_color()); 287 message(msg, 0); 288 break; 289 } 290 if (id_scrolls[obj->which_kind].id_status != CALLED) { 291 id_scrolls[obj->which_kind].id_status = IDENTIFIED; 292 } 293 vanish(obj, (obj->which_kind != SLEEP), &rogue.pack); 294 } 295 296 /* vanish() does NOT handle a quiver of weapons with more than one 297 * arrow (or whatever) in the quiver. It will only decrement the count. 298 */ 299 300 void 301 vanish(obj, rm, pack) 302 object *obj; 303 short rm; 304 object *pack; 305 { 306 if (obj->quantity > 1) { 307 obj->quantity--; 308 } else { 309 if (obj->in_use_flags & BEING_WIELDED) { 310 unwield(obj); 311 } else if (obj->in_use_flags & BEING_WORN) { 312 unwear(obj); 313 } else if (obj->in_use_flags & ON_EITHER_HAND) { 314 un_put_on(obj); 315 } 316 take_from_pack(obj, pack); 317 free_object(obj); 318 } 319 if (rm) { 320 (void) reg_move(); 321 } 322 } 323 324 void 325 potion_heal(extra) 326 int extra; 327 { 328 float ratio; 329 short add; 330 331 rogue.hp_current += rogue.exp; 332 333 ratio = ((float)rogue.hp_current) / rogue.hp_max; 334 335 if (ratio >= 1.00) { 336 rogue.hp_max += (extra ? 2 : 1); 337 extra_hp += (extra ? 2 : 1); 338 rogue.hp_current = rogue.hp_max; 339 } else if (ratio >= 0.90) { 340 rogue.hp_max += (extra ? 1 : 0); 341 extra_hp += (extra ? 1 : 0); 342 rogue.hp_current = rogue.hp_max; 343 } else { 344 if (ratio < 0.33) { 345 ratio = 0.33; 346 } 347 if (extra) { 348 ratio += ratio; 349 } 350 add = (short)(ratio * ((float)rogue.hp_max - rogue.hp_current)); 351 rogue.hp_current += add; 352 if (rogue.hp_current > rogue.hp_max) { 353 rogue.hp_current = rogue.hp_max; 354 } 355 } 356 if (blind) { 357 unblind(); 358 } 359 if (confused && extra) { 360 unconfuse(); 361 } else if (confused) { 362 confused = (confused / 2) + 1; 363 } 364 if (halluc && extra) { 365 unhallucinate(); 366 } else if (halluc) { 367 halluc = (halluc / 2) + 1; 368 } 369 } 370 371 void 372 idntfy() 373 { 374 short ch; 375 object *obj; 376 struct id *id_table; 377 char desc[DCOLS]; 378 AGAIN: 379 ch = pack_letter("what would you like to identify?", ALL_OBJECTS); 380 381 if (ch == CANCEL) { 382 return; 383 } 384 if (!(obj = get_letter_object(ch))) { 385 message("no such item, try again", 0); 386 message("", 0); 387 check_message(); 388 goto AGAIN; 389 } 390 obj->identified = 1; 391 if (obj->what_is & (SCROL | POTION | WEAPON | ARMOR | WAND | RING)) { 392 id_table = get_id_table(obj); 393 id_table[obj->which_kind].id_status = IDENTIFIED; 394 } 395 get_desc(obj, desc); 396 message(desc, 0); 397 } 398 399 void 400 eat() 401 { 402 short ch; 403 short moves; 404 object *obj; 405 char buf[70]; 406 407 ch = pack_letter("eat what?", FOOD); 408 409 if (ch == CANCEL) { 410 return; 411 } 412 if (!(obj = get_letter_object(ch))) { 413 message("no such item.", 0); 414 return; 415 } 416 if (obj->what_is != FOOD) { 417 message("you can't eat that", 0); 418 return; 419 } 420 if ((obj->which_kind == FRUIT) || rand_percent(60)) { 421 moves = get_rand(950, 1150); 422 if (obj->which_kind == RATION) { 423 message("yum, that tasted good", 0); 424 } else { 425 sprintf(buf, "my, that was a yummy %s", fruit); 426 message(buf, 0); 427 } 428 } else { 429 moves = get_rand(750, 950); 430 message("yuk, that food tasted awful", 0); 431 add_exp(2, 1); 432 } 433 rogue.moves_left /= 3; 434 rogue.moves_left += moves; 435 hunger_str[0] = 0; 436 print_stats(STAT_HUNGER); 437 438 vanish(obj, 1, &rogue.pack); 439 } 440 441 void 442 hold_monster() 443 { 444 short i, j; 445 short mcount = 0; 446 object *monster; 447 short row, col; 448 449 for (i = -2; i <= 2; i++) { 450 for (j = -2; j <= 2; j++) { 451 row = rogue.row + i; 452 col = rogue.col + j; 453 if ((row < MIN_ROW) || (row > (DROWS-2)) || (col < 0) || 454 (col > (DCOLS-1))) { 455 continue; 456 } 457 if (dungeon[row][col] & MONSTER) { 458 monster = object_at(&level_monsters, row, col); 459 monster->m_flags |= ASLEEP; 460 monster->m_flags &= (~WAKENS); 461 mcount++; 462 } 463 } 464 } 465 if (mcount == 0) { 466 message("you feel a strange sense of loss", 0); 467 } else if (mcount == 1) { 468 message("the monster freezes", 0); 469 } else { 470 message("the monsters around you freeze", 0); 471 } 472 } 473 474 void 475 tele() 476 { 477 mvaddch(rogue.row, rogue.col, get_dungeon_char(rogue.row, rogue.col)); 478 479 if (cur_room >= 0) { 480 darken_room(cur_room); 481 } 482 put_player(get_room_number(rogue.row, rogue.col)); 483 being_held = 0; 484 bear_trap = 0; 485 } 486 487 void 488 hallucinate() 489 { 490 object *obj, *monster; 491 short ch; 492 493 if (blind) return; 494 495 obj = level_objects.next_object; 496 497 while (obj) { 498 ch = mvinch(obj->row, obj->col); 499 if (((ch < 'A') || (ch > 'Z')) && 500 ((obj->row != rogue.row) || (obj->col != rogue.col))) 501 if ((ch != ' ') && (ch != '.') && (ch != '#') && (ch != '+')) { 502 addch(gr_obj_char()); 503 } 504 obj = obj->next_object; 505 } 506 monster = level_monsters.next_monster; 507 508 while (monster) { 509 ch = mvinch(monster->row, monster->col); 510 if ((ch >= 'A') && (ch <= 'Z')) { 511 addch(get_rand('A', 'Z')); 512 } 513 monster = monster->next_monster; 514 } 515 } 516 517 void 518 unhallucinate() 519 { 520 halluc = 0; 521 relight(); 522 message("everything looks SO boring now", 1); 523 } 524 525 void 526 unblind() 527 { 528 blind = 0; 529 message("the veil of darkness lifts", 1); 530 relight(); 531 if (halluc) { 532 hallucinate(); 533 } 534 if (detect_monster) { 535 show_monsters(); 536 } 537 } 538 539 void 540 relight() 541 { 542 if (cur_room == PASSAGE) { 543 light_passage(rogue.row, rogue.col); 544 } else { 545 light_up_room(cur_room); 546 } 547 mvaddch(rogue.row, rogue.col, rogue.fchar); 548 } 549 550 void 551 take_a_nap() 552 { 553 short i; 554 555 i = get_rand(2, 5); 556 md_sleep(1); 557 558 while (i--) { 559 mv_mons(); 560 } 561 md_sleep(1); 562 message(you_can_move_again, 0); 563 } 564 565 void 566 go_blind() 567 { 568 short i, j; 569 570 if (!blind) { 571 message("a cloak of darkness falls around you", 0); 572 } 573 blind += get_rand(500, 800); 574 575 if (detect_monster) { 576 object *monster; 577 578 monster = level_monsters.next_monster; 579 580 while (monster) { 581 mvaddch(monster->row, monster->col, monster->trail_char); 582 monster = monster->next_monster; 583 } 584 } 585 if (cur_room >= 0) { 586 for (i = rooms[cur_room].top_row + 1; 587 i < rooms[cur_room].bottom_row; i++) { 588 for (j = rooms[cur_room].left_col + 1; 589 j < rooms[cur_room].right_col; j++) { 590 mvaddch(i, j, ' '); 591 } 592 } 593 } 594 mvaddch(rogue.row, rogue.col, rogue.fchar); 595 } 596 597 const char * 598 get_ench_color() 599 { 600 if (halluc) { 601 return(id_potions[get_rand(0, POTIONS-1)].title); 602 } else if (con_mon) { 603 return("red "); 604 } 605 return("blue "); 606 } 607 608 void 609 cnfs() 610 { 611 confused += get_rand(12, 22); 612 } 613 614 void 615 unconfuse() 616 { 617 char msg[80]; 618 619 confused = 0; 620 sprintf(msg, "you feel less %s now", (halluc ? "trippy" : "confused")); 621 message(msg, 1); 622 } 623 624 void 625 uncurse_all() 626 { 627 object *obj; 628 629 obj = rogue.pack.next_object; 630 631 while (obj) { 632 obj->is_cursed = 0; 633 obj = obj->next_object; 634 } 635 } 636