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