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