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