1: /* 2: * special_hit.c 3: * 4: * This source herein may be modified and/or distributed by anybody who 5: * so desires, with the following restrictions: 6: * 1.) No portion of this notice shall be removed. 7: * 2.) Credit shall not be taken for the creation of this source. 8: * 3.) This code is not to be traded, sold, or used for personal 9: * gain or profit. 10: * 11: */ 12: 13: #ifndef lint 14: static char sccsid[] = "@(#)spec_hit.c 5.1 (Berkeley) 11/25/87"; 15: #endif /* not lint */ 16: 17: #include "rogue.h" 18: 19: short less_hp = 0; 20: boolean being_held; 21: 22: extern short cur_level, max_level, blind, levitate, ring_exp; 23: extern long level_points[]; 24: extern boolean detect_monster, mon_disappeared; 25: extern boolean sustain_strength, maintain_armor; 26: extern char *you_can_move_again; 27: 28: special_hit(monster) 29: object *monster; 30: { 31: if ((monster->m_flags & CONFUSED) && rand_percent(66)) { 32: return; 33: } 34: if (monster->m_flags & RUSTS) { 35: rust(monster); 36: } 37: if ((monster->m_flags & HOLDS) && !levitate) { 38: being_held = 1; 39: } 40: if (monster->m_flags & FREEZES) { 41: freeze(monster); 42: } 43: if (monster->m_flags & STINGS) { 44: sting(monster); 45: } 46: if (monster->m_flags & DRAINS_LIFE) { 47: drain_life(); 48: } 49: if (monster->m_flags & DROPS_LEVEL) { 50: drop_level(); 51: } 52: if (monster->m_flags & STEALS_GOLD) { 53: steal_gold(monster); 54: } else if (monster->m_flags & STEALS_ITEM) { 55: steal_item(monster); 56: } 57: } 58: 59: rust(monster) 60: object *monster; 61: { 62: if ((!rogue.armor) || (get_armor_class(rogue.armor) <= 1) || 63: (rogue.armor->which_kind == LEATHER)) { 64: return; 65: } 66: if ((rogue.armor->is_protected) || maintain_armor) { 67: if (monster && (!(monster->m_flags & RUST_VANISHED))) { 68: message("the rust vanishes instantly", 0); 69: monster->m_flags |= RUST_VANISHED; 70: } 71: } else { 72: rogue.armor->d_enchant--; 73: message("your armor weakens", 0); 74: print_stats(STAT_ARMOR); 75: } 76: } 77: 78: freeze(monster) 79: object *monster; 80: { 81: short freeze_percent = 99; 82: short i, n; 83: 84: if (rand_percent(12)) { 85: return; 86: } 87: freeze_percent -= (rogue.str_current+(rogue.str_current / 2)); 88: freeze_percent -= ((rogue.exp + ring_exp) * 4); 89: freeze_percent -= (get_armor_class(rogue.armor) * 5); 90: freeze_percent -= (rogue.hp_max / 3); 91: 92: if (freeze_percent > 10) { 93: monster->m_flags |= FREEZING_ROGUE; 94: message("you are frozen", 1); 95: 96: n = get_rand(4, 8); 97: for (i = 0; i < n; i++) { 98: mv_mons(); 99: } 100: if (rand_percent(freeze_percent)) { 101: for (i = 0; i < 50; i++) { 102: mv_mons(); 103: } 104: killed_by((object *)0, HYPOTHERMIA); 105: } 106: message(you_can_move_again, 1); 107: monster->m_flags &= (~FREEZING_ROGUE); 108: } 109: } 110: 111: steal_gold(monster) 112: object *monster; 113: { 114: int amount; 115: 116: if ((rogue.gold <= 0) || rand_percent(10)) { 117: return; 118: } 119: 120: amount = get_rand((cur_level * 10), (cur_level * 30)); 121: 122: if (amount > rogue.gold) { 123: amount = rogue.gold; 124: } 125: rogue.gold -= amount; 126: message("your purse feels lighter", 0); 127: print_stats(STAT_GOLD); 128: disappear(monster); 129: } 130: 131: steal_item(monster) 132: object *monster; 133: { 134: object *obj; 135: short i, n, t; 136: char desc[80]; 137: boolean has_something = 0; 138: 139: if (rand_percent(15)) { 140: return; 141: } 142: obj = rogue.pack.next_object; 143: 144: if (!obj) { 145: goto DSPR; 146: } 147: while (obj) { 148: if (!(obj->in_use_flags & BEING_USED)) { 149: has_something = 1; 150: break; 151: } 152: obj = obj->next_object; 153: } 154: if (!has_something) { 155: goto DSPR; 156: } 157: n = get_rand(0, MAX_PACK_COUNT); 158: obj = rogue.pack.next_object; 159: 160: for (i = 0; i <= n; i++) { 161: obj = obj->next_object; 162: while ((!obj) || (obj->in_use_flags & BEING_USED)) { 163: if (!obj) { 164: obj = rogue.pack.next_object; 165: } else { 166: obj = obj->next_object; 167: } 168: } 169: } 170: (void) strcpy(desc, "she stole "); 171: if (obj->what_is != WEAPON) { 172: t = obj->quantity; 173: obj->quantity = 1; 174: } 175: get_desc(obj, desc+10); 176: message(desc, 0); 177: 178: obj->quantity = ((obj->what_is != WEAPON) ? t : 1); 179: 180: vanish(obj, 0, &rogue.pack); 181: DSPR: 182: disappear(monster); 183: } 184: 185: disappear(monster) 186: object *monster; 187: { 188: short row, col; 189: 190: row = monster->row; 191: col = monster->col; 192: 193: dungeon[row][col] &= ~MONSTER; 194: if (rogue_can_see(row, col)) { 195: mvaddch(row, col, get_dungeon_char(row, col)); 196: } 197: take_from_pack(monster, &level_monsters); 198: free_object(monster); 199: mon_disappeared = 1; 200: } 201: 202: cough_up(monster) 203: object *monster; 204: { 205: object *obj; 206: short row, col, i, n; 207: 208: if (cur_level < max_level) { 209: return; 210: } 211: 212: if (monster->m_flags & STEALS_GOLD) { 213: obj = alloc_object(); 214: obj->what_is = GOLD; 215: obj->quantity = get_rand((cur_level * 15), (cur_level * 30)); 216: } else { 217: if (!rand_percent((int) monster->drop_percent)) { 218: return; 219: } 220: obj = gr_object(); 221: } 222: row = monster->row; 223: col = monster->col; 224: 225: for (n = 0; n <= 5; n++) { 226: for (i = -n; i <= n; i++) { 227: if (try_to_cough(row+n, col+i, obj)) { 228: return; 229: } 230: if (try_to_cough(row-n, col+i, obj)) { 231: return; 232: } 233: } 234: for (i = -n; i <= n; i++) { 235: if (try_to_cough(row+i, col-n, obj)) { 236: return; 237: } 238: if (try_to_cough(row+i, col+n, obj)) { 239: return; 240: } 241: } 242: } 243: free_object(obj); 244: } 245: 246: try_to_cough(row, col, obj) 247: short row, col; 248: object *obj; 249: { 250: if ((row < MIN_ROW) || (row > (DROWS-2)) || (col < 0) || (col>(DCOLS-1))) { 251: return(0); 252: } 253: if ((!(dungeon[row][col] & (OBJECT | STAIRS | TRAP))) && 254: (dungeon[row][col] & (TUNNEL | FLOOR | DOOR))) { 255: place_at(obj, row, col); 256: if (((row != rogue.row) || (col != rogue.col)) && 257: (!(dungeon[row][col] & MONSTER))) { 258: mvaddch(row, col, get_dungeon_char(row, col)); 259: } 260: return(1); 261: } 262: return(0); 263: } 264: 265: seek_gold(monster) 266: object *monster; 267: { 268: short i, j, rn, s; 269: 270: if ((rn = get_room_number(monster->row, monster->col)) < 0) { 271: return(0); 272: } 273: for (i = rooms[rn].top_row+1; i < rooms[rn].bottom_row; i++) { 274: for (j = rooms[rn].left_col+1; j < rooms[rn].right_col; j++) { 275: if ((gold_at(i, j)) && !(dungeon[i][j] & MONSTER)) { 276: monster->m_flags |= CAN_FLIT; 277: s = mon_can_go(monster, i, j); 278: monster->m_flags &= (~CAN_FLIT); 279: if (s) { 280: move_mon_to(monster, i, j); 281: monster->m_flags |= ASLEEP; 282: monster->m_flags &= (~(WAKENS | SEEKS_GOLD)); 283: return(1); 284: } 285: monster->m_flags &= (~SEEKS_GOLD); 286: monster->m_flags |= CAN_FLIT; 287: mv_1_monster(monster, i, j); 288: monster->m_flags &= (~CAN_FLIT); 289: monster->m_flags |= SEEKS_GOLD; 290: return(1); 291: } 292: } 293: } 294: return(0); 295: } 296: 297: gold_at(row, col) 298: short row, col; 299: { 300: if (dungeon[row][col] & OBJECT) { 301: object *obj; 302: 303: if ((obj = object_at(&level_objects, row, col)) && 304: (obj->what_is == GOLD)) { 305: return(1); 306: } 307: } 308: return(0); 309: } 310: 311: check_gold_seeker(monster) 312: object *monster; 313: { 314: monster->m_flags &= (~SEEKS_GOLD); 315: } 316: 317: check_imitator(monster) 318: object *monster; 319: { 320: char msg[80]; 321: 322: if (monster->m_flags & IMITATES) { 323: wake_up(monster); 324: if (!blind) { 325: mvaddch(monster->row, monster->col, 326: get_dungeon_char(monster->row, monster->col)); 327: check_message(); 328: sprintf(msg, "wait, that's a %s!", mon_name(monster)); 329: message(msg, 1); 330: } 331: return(1); 332: } 333: return(0); 334: } 335: 336: imitating(row, col) 337: register short row, col; 338: { 339: if (dungeon[row][col] & MONSTER) { 340: object *object_at(), *monster; 341: 342: if (monster = object_at(&level_monsters, row, col)) { 343: if (monster->m_flags & IMITATES) { 344: return(1); 345: } 346: } 347: } 348: return(0); 349: } 350: 351: sting(monster) 352: object *monster; 353: { 354: short sting_chance = 35; 355: char msg[80]; 356: 357: if ((rogue.str_current <= 3) || sustain_strength) { 358: return; 359: } 360: sting_chance += (6 * (6 - get_armor_class(rogue.armor))); 361: 362: if ((rogue.exp + ring_exp) > 8) { 363: sting_chance -= (6 * ((rogue.exp + ring_exp) - 8)); 364: } 365: if (rand_percent(sting_chance)) { 366: sprintf(msg, "the %s's bite has weakened you", 367: mon_name(monster)); 368: message(msg, 0); 369: rogue.str_current--; 370: print_stats(STAT_STRENGTH); 371: } 372: } 373: 374: drop_level() 375: { 376: int hp; 377: 378: if (rand_percent(80) || (rogue.exp <= 5)) { 379: return; 380: } 381: rogue.exp_points = level_points[rogue.exp-2] - get_rand(9, 29); 382: rogue.exp -= 2; 383: hp = hp_raise(); 384: if ((rogue.hp_current -= hp) <= 0) { 385: rogue.hp_current = 1; 386: } 387: if ((rogue.hp_max -= hp) <= 0) { 388: rogue.hp_max = 1; 389: } 390: add_exp(1, 0); 391: } 392: 393: drain_life() 394: { 395: short n; 396: 397: if (rand_percent(60) || (rogue.hp_max <= 30) || (rogue.hp_current < 10)) { 398: return; 399: } 400: n = get_rand(1, 3); /* 1 Hp, 2 Str, 3 both */ 401: 402: if ((n != 2) || (!sustain_strength)) { 403: message("you feel weaker", 0); 404: } 405: if (n != 2) { 406: rogue.hp_max--; 407: rogue.hp_current--; 408: less_hp++; 409: } 410: if (n != 1) { 411: if ((rogue.str_current > 3) && (!sustain_strength)) { 412: rogue.str_current--; 413: if (coin_toss()) { 414: rogue.str_max--; 415: } 416: } 417: } 418: print_stats((STAT_STRENGTH | STAT_HP)); 419: } 420: 421: m_confuse(monster) 422: object *monster; 423: { 424: char msg[80]; 425: 426: if (!rogue_can_see(monster->row, monster->col)) { 427: return(0); 428: } 429: if (rand_percent(45)) { 430: monster->m_flags &= (~CONFUSES); /* will not confuse the rogue */ 431: return(0); 432: } 433: if (rand_percent(55)) { 434: monster->m_flags &= (~CONFUSES); 435: sprintf(msg, "the gaze of the %s has confused you", mon_name(monster)); 436: message(msg, 1); 437: cnfs(); 438: return(1); 439: } 440: return(0); 441: } 442: 443: flame_broil(monster) 444: object *monster; 445: { 446: short row, col, dir; 447: 448: if ((!mon_sees(monster, rogue.row, rogue.col)) || coin_toss()) { 449: return(0); 450: } 451: row = rogue.row - monster->row; 452: col = rogue.col - monster->col; 453: if (row < 0) { 454: row = -row; 455: } 456: if (col < 0) { 457: col = -col; 458: } 459: if (((row != 0) && (col != 0) && (row != col)) || 460: ((row > 7) || (col > 7))) { 461: return(0); 462: } 463: dir = get_dir(monster->row, monster->col, row, col); 464: bounce(FIRE, dir, monster->row, monster->col, 0); 465: 466: return(1); 467: } 468: 469: get_dir(srow, scol, drow, dcol) 470: short srow, scol, drow, dcol; 471: { 472: if (srow == drow) { 473: if (scol < dcol) { 474: return(RIGHT); 475: } else { 476: return(LEFT); 477: } 478: } 479: if (scol == dcol) { 480: if (srow < drow) { 481: return(DOWN); 482: } else { 483: return(UPWARD); 484: } 485: } 486: if ((srow > drow) && (scol > dcol)) { 487: return(UPLEFT); 488: } 489: if ((srow < drow) && (scol < dcol)) { 490: return(DOWNRIGHT); 491: } 492: if ((srow < drow) && (scol > dcol)) { 493: return(DOWNLEFT); 494: } 495: /*if ((srow > drow) && (scol < dcol)) {*/ 496: return(UPRIGHT); 497: /*}*/ 498: }