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 } 499