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