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