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.2 2003/06/17 04:25:25 dillon 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 char hunger_str[]; 68 extern short cur_room; 69 extern long level_points[]; 70 extern boolean being_held; 71 extern char *fruit, *you_can_move_again; 72 extern boolean sustain_strength; 73 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 read_scroll() 188 { 189 short ch; 190 object *obj; 191 char msg[DCOLS]; 192 193 ch = pack_letter("read what?", SCROL); 194 195 if (ch == CANCEL) { 196 return; 197 } 198 if (!(obj = get_letter_object(ch))) { 199 message("no such item.", 0); 200 return; 201 } 202 if (obj->what_is != SCROL) { 203 message("you can't read that", 0); 204 return; 205 } 206 switch(obj->which_kind) { 207 case SCARE_MONSTER: 208 message("you hear a maniacal laughter in the distance", 209 0); 210 break; 211 case HOLD_MONSTER: 212 hold_monster(); 213 break; 214 case ENCH_WEAPON: 215 if (rogue.weapon) { 216 if (rogue.weapon->what_is == WEAPON) { 217 sprintf(msg, "your %sglow%s %sfor a moment", 218 name_of(rogue.weapon), 219 ((rogue.weapon->quantity <= 1) ? "s" : ""), 220 get_ench_color()); 221 message(msg, 0); 222 if (coin_toss()) { 223 rogue.weapon->hit_enchant++; 224 } else { 225 rogue.weapon->d_enchant++; 226 } 227 } 228 rogue.weapon->is_cursed = 0; 229 } else { 230 message("your hands tingle", 0); 231 } 232 break; 233 case ENCH_ARMOR: 234 if (rogue.armor) { 235 sprintf(msg, "your armor glows %sfor a moment", 236 get_ench_color()); 237 message(msg, 0); 238 rogue.armor->d_enchant++; 239 rogue.armor->is_cursed = 0; 240 print_stats(STAT_ARMOR); 241 } else { 242 message("your skin crawls", 0); 243 } 244 break; 245 case IDENTIFY: 246 message("this is a scroll of identify", 0); 247 obj->identified = 1; 248 id_scrolls[obj->which_kind].id_status = IDENTIFIED; 249 idntfy(); 250 break; 251 case TELEPORT: 252 tele(); 253 break; 254 case SLEEP: 255 message("you fall asleep", 0); 256 take_a_nap(); 257 break; 258 case PROTECT_ARMOR: 259 if (rogue.armor) { 260 message( "your armor is covered by a shimmering gold shield",0); 261 rogue.armor->is_protected = 1; 262 rogue.armor->is_cursed = 0; 263 } else { 264 message("your acne seems to have disappeared", 0); 265 } 266 break; 267 case REMOVE_CURSE: 268 message((!halluc) ? 269 "you feel as though someone is watching over you" : 270 "you feel in touch with the universal oneness", 0); 271 uncurse_all(); 272 break; 273 case CREATE_MONSTER: 274 create_monster(); 275 break; 276 case AGGRAVATE_MONSTER: 277 aggravate(); 278 break; 279 case MAGIC_MAPPING: 280 message("this scroll seems to have a map on it", 0); 281 draw_magic_map(); 282 break; 283 case CON_MON: 284 con_mon = 1; 285 sprintf(msg, "your hands glow %sfor a moment", get_ench_color()); 286 message(msg, 0); 287 break; 288 } 289 if (id_scrolls[obj->which_kind].id_status != CALLED) { 290 id_scrolls[obj->which_kind].id_status = IDENTIFIED; 291 } 292 vanish(obj, (obj->which_kind != SLEEP), &rogue.pack); 293 } 294 295 /* vanish() does NOT handle a quiver of weapons with more than one 296 * arrow (or whatever) in the quiver. It will only decrement the count. 297 */ 298 299 vanish(obj, rm, pack) 300 object *obj; 301 short rm; 302 object *pack; 303 { 304 if (obj->quantity > 1) { 305 obj->quantity--; 306 } else { 307 if (obj->in_use_flags & BEING_WIELDED) { 308 unwield(obj); 309 } else if (obj->in_use_flags & BEING_WORN) { 310 unwear(obj); 311 } else if (obj->in_use_flags & ON_EITHER_HAND) { 312 un_put_on(obj); 313 } 314 take_from_pack(obj, pack); 315 free_object(obj); 316 } 317 if (rm) { 318 (void) reg_move(); 319 } 320 } 321 322 potion_heal(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 idntfy() 368 { 369 short ch; 370 object *obj; 371 struct id *id_table; 372 char desc[DCOLS]; 373 AGAIN: 374 ch = pack_letter("what would you like to identify?", ALL_OBJECTS); 375 376 if (ch == CANCEL) { 377 return; 378 } 379 if (!(obj = get_letter_object(ch))) { 380 message("no such item, try again", 0); 381 message("", 0); 382 check_message(); 383 goto AGAIN; 384 } 385 obj->identified = 1; 386 if (obj->what_is & (SCROL | POTION | WEAPON | ARMOR | WAND | RING)) { 387 id_table = get_id_table(obj); 388 id_table[obj->which_kind].id_status = IDENTIFIED; 389 } 390 get_desc(obj, desc); 391 message(desc, 0); 392 } 393 394 eat() 395 { 396 short ch; 397 short moves; 398 object *obj; 399 char buf[70]; 400 401 ch = pack_letter("eat what?", FOOD); 402 403 if (ch == CANCEL) { 404 return; 405 } 406 if (!(obj = get_letter_object(ch))) { 407 message("no such item.", 0); 408 return; 409 } 410 if (obj->what_is != FOOD) { 411 message("you can't eat that", 0); 412 return; 413 } 414 if ((obj->which_kind == FRUIT) || rand_percent(60)) { 415 moves = get_rand(950, 1150); 416 if (obj->which_kind == RATION) { 417 message("yum, that tasted good", 0); 418 } else { 419 sprintf(buf, "my, that was a yummy %s", fruit); 420 message(buf, 0); 421 } 422 } else { 423 moves = get_rand(750, 950); 424 message("yuk, that food tasted awful", 0); 425 add_exp(2, 1); 426 } 427 rogue.moves_left /= 3; 428 rogue.moves_left += moves; 429 hunger_str[0] = 0; 430 print_stats(STAT_HUNGER); 431 432 vanish(obj, 1, &rogue.pack); 433 } 434 435 hold_monster() 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 tele() 468 { 469 mvaddch(rogue.row, rogue.col, get_dungeon_char(rogue.row, rogue.col)); 470 471 if (cur_room >= 0) { 472 darken_room(cur_room); 473 } 474 put_player(get_room_number(rogue.row, rogue.col)); 475 being_held = 0; 476 bear_trap = 0; 477 } 478 479 hallucinate() 480 { 481 object *obj, *monster; 482 short ch; 483 484 if (blind) return; 485 486 obj = level_objects.next_object; 487 488 while (obj) { 489 ch = mvinch(obj->row, obj->col); 490 if (((ch < 'A') || (ch > 'Z')) && 491 ((obj->row != rogue.row) || (obj->col != rogue.col))) 492 if ((ch != ' ') && (ch != '.') && (ch != '#') && (ch != '+')) { 493 addch(gr_obj_char()); 494 } 495 obj = obj->next_object; 496 } 497 monster = level_monsters.next_monster; 498 499 while (monster) { 500 ch = mvinch(monster->row, monster->col); 501 if ((ch >= 'A') && (ch <= 'Z')) { 502 addch(get_rand('A', 'Z')); 503 } 504 monster = monster->next_monster; 505 } 506 } 507 508 unhallucinate() 509 { 510 halluc = 0; 511 relight(); 512 message("everything looks SO boring now", 1); 513 } 514 515 unblind() 516 { 517 blind = 0; 518 message("the veil of darkness lifts", 1); 519 relight(); 520 if (halluc) { 521 hallucinate(); 522 } 523 if (detect_monster) { 524 show_monsters(); 525 } 526 } 527 528 relight() 529 { 530 if (cur_room == PASSAGE) { 531 light_passage(rogue.row, rogue.col); 532 } else { 533 light_up_room(cur_room); 534 } 535 mvaddch(rogue.row, rogue.col, rogue.fchar); 536 } 537 538 take_a_nap() 539 { 540 short i; 541 542 i = get_rand(2, 5); 543 md_sleep(1); 544 545 while (i--) { 546 mv_mons(); 547 } 548 md_sleep(1); 549 message(you_can_move_again, 0); 550 } 551 552 go_blind() 553 { 554 short i, j; 555 556 if (!blind) { 557 message("a cloak of darkness falls around you", 0); 558 } 559 blind += get_rand(500, 800); 560 561 if (detect_monster) { 562 object *monster; 563 564 monster = level_monsters.next_monster; 565 566 while (monster) { 567 mvaddch(monster->row, monster->col, monster->trail_char); 568 monster = monster->next_monster; 569 } 570 } 571 if (cur_room >= 0) { 572 for (i = rooms[cur_room].top_row + 1; 573 i < rooms[cur_room].bottom_row; i++) { 574 for (j = rooms[cur_room].left_col + 1; 575 j < rooms[cur_room].right_col; j++) { 576 mvaddch(i, j, ' '); 577 } 578 } 579 } 580 mvaddch(rogue.row, rogue.col, rogue.fchar); 581 } 582 583 const char * 584 get_ench_color() 585 { 586 if (halluc) { 587 return(id_potions[get_rand(0, POTIONS-1)].title); 588 } else if (con_mon) { 589 return("red "); 590 } 591 return("blue "); 592 } 593 594 cnfs() 595 { 596 confused += get_rand(12, 22); 597 } 598 599 unconfuse() 600 { 601 char msg[80]; 602 603 confused = 0; 604 sprintf(msg, "you feel less %s now", (halluc ? "trippy" : "confused")); 605 message(msg, 1); 606 } 607 608 uncurse_all() 609 { 610 object *obj; 611 612 obj = rogue.pack.next_object; 613 614 while (obj) { 615 obj->is_cursed = 0; 616 obj = obj->next_object; 617 } 618 } 619