1 /* 2 * Functions to implement the various sticks one might find 3 * while wandering around the dungeon. 4 * 5 * @(#)sticks.c 1.2 (AI Design) 2/12/84 6 */ 7 8 #include "rogue.h" 9 #include "curses.h" 10 11 /* 12 * fix_stick: 13 * Set up a new stick 14 */ 15 fix_stick(cur) 16 register THING *cur; 17 { 18 if (strcmp(ws_type[cur->o_which], "staff") == 0) 19 cur->o_damage = "2d3"; 20 else 21 cur->o_damage = "1d1"; 22 cur->o_hurldmg = "1d1"; 23 24 cur->o_charges = 3 + rnd(5); 25 switch (cur->o_which) 26 { 27 when WS_HIT: 28 cur->o_hplus = 100; 29 cur->o_dplus = 3; 30 cur->o_damage = "1d8"; 31 when WS_LIGHT: 32 cur->o_charges = 10 + rnd(10); 33 } 34 } 35 36 /* 37 * do_zap: 38 * Perform a zap with a wand 39 */ 40 do_zap() 41 { 42 THING *obj; 43 THING *tp; 44 register int y, x; 45 register char *name; 46 int which_one; 47 48 if ((obj = get_item("zap with", STICK)) == NULL) 49 return; 50 which_one = obj->o_which; 51 if (obj->o_type != STICK) 52 { 53 if (obj->o_enemy && obj->o_charges) 54 which_one = MAXSTICKS; 55 else 56 { 57 msg("you can't zap with that!"); 58 after = FALSE; 59 return; 60 } 61 } 62 if (obj->o_charges == 0) 63 { 64 msg("nothing happens"); 65 return; 66 } 67 switch (which_one) 68 { 69 when WS_LIGHT: 70 /* 71 * Reddy Kilowat wand. Light up the room 72 */ 73 if (on(player,ISBLIND)) 74 msg("you feel a warm glow around you"); 75 else 76 { 77 ws_know[WS_LIGHT] = TRUE; 78 if (proom->r_flags & ISGONE) 79 msg("the corridor glows and then fades"); 80 else 81 msg("the room is lit by a shimmering blue light"); 82 } 83 if (!(proom->r_flags & ISGONE)) 84 { 85 proom->r_flags &= ~ISDARK; 86 /* 87 * Light the room and put the player back up 88 */ 89 enter_room(&hero); 90 } 91 when WS_DRAIN: 92 /* 93 * Take away 1/2 of hero's hit points, then take it away 94 * evenly from the monsters in the room (or next to hero 95 * if he is in a passage) 96 */ 97 if (pstats.s_hpt < 2) 98 { 99 msg("you are too weak to use it"); 100 return; 101 } 102 else 103 drain(); 104 when WS_POLYMORPH: 105 case WS_TELAWAY: 106 case WS_TELTO: 107 case WS_CANCEL: 108 case MAXSTICKS: /* Special case for vorpal weapon */ 109 { 110 register byte monster, oldch; 111 register int rm; 112 coord new_yx; 113 114 y = hero.y; 115 x = hero.x; 116 while (step_ok(winat(y, x))) 117 { 118 y += delta.y; 119 x += delta.x; 120 } 121 if ((tp = moat(y, x)) != NULL) 122 { 123 register byte omonst; 124 125 omonst = monster = tp->t_type; 126 if (monster == 'F') 127 player.t_flags &= ~ISHELD; 128 if (which_one == MAXSTICKS) 129 { 130 if (monster == obj->o_enemy) 131 { 132 msg("the %s vanishes in a puff of smoke", 133 monsters[monster-'A'].m_name); 134 killed(tp, FALSE); 135 } 136 else 137 msg("you hear a maniacal chuckle in the distance."); 138 } 139 else if (which_one == WS_POLYMORPH) 140 { 141 register THING *pp; 142 143 pp = tp->t_pack; 144 detach(mlist, tp); 145 if (see_monst(tp)) 146 mvaddch(y, x, chat(y, x)); 147 oldch = tp->t_oldch; 148 delta.y = y; 149 delta.x = x; 150 new_monster(tp, monster = rnd(26) + 'A', &delta); 151 if (see_monst(tp)) 152 mvaddch(y, x, monster); 153 tp->t_oldch = oldch; 154 tp->t_pack = pp; 155 ws_know[WS_POLYMORPH] |= (monster != omonst); 156 } 157 else if (which_one == WS_CANCEL) 158 { 159 tp->t_flags |= ISCANC; 160 tp->t_flags &= ~(ISINVIS|CANHUH); 161 tp->t_disguise = tp->t_type; 162 } 163 else 164 { 165 if (see_monst(tp)) 166 mvaddch(y, x, tp->t_oldch); 167 if (which_one == WS_TELAWAY) 168 { 169 tp->t_oldch = '@'; 170 do 171 { 172 rm = rnd_room(); 173 new_yx = tp->t_pos; 174 rnd_pos(&rooms[rm], &new_yx); 175 } while (!(isfloor(winat(new_yx.y, new_yx.x)))); 176 tp->t_pos = new_yx; 177 if (see_monst(tp)) 178 mvaddch(tp->t_pos.y, tp->t_pos.x, tp->t_disguise); 179 else if (on(player, SEEMONST)) 180 { 181 standout(); 182 mvaddch(tp->t_pos.y, tp->t_pos.x, tp->t_disguise); 183 standend(); 184 } 185 } 186 else /* it MUST BE at WS_TELTO */ 187 { 188 tp->t_pos.y = hero.y + delta.y; 189 tp->t_pos.x = hero.x + delta.x; 190 } 191 if (tp->t_type == 'F') 192 player.t_flags &= ~ISHELD; 193 if (tp->t_pos.y != y || tp->t_pos.x != x) 194 tp->t_oldch = mvinch(tp->t_pos.y, tp->t_pos.x); 195 } 196 tp->t_dest = &hero; 197 tp->t_flags |= ISRUN; 198 } 199 } 200 when WS_MISSILE: 201 { 202 THING bolt; 203 204 ws_know[WS_MISSILE] = TRUE; 205 bolt.o_type = '*'; 206 bolt.o_hurldmg = "1d8"; 207 bolt.o_hplus = 1000; 208 bolt.o_dplus = 1; 209 bolt.o_flags = ISMISL; 210 if (cur_weapon != NULL) 211 bolt.o_launch = cur_weapon->o_which; 212 do_motion(&bolt, delta.y, delta.x); 213 if ((tp = moat(bolt.o_pos.y, bolt.o_pos.x)) != NULL && !save_throw(VS_MAGIC, tp)) 214 hit_monster(unc(bolt.o_pos), &bolt); 215 else 216 msg("the missle vanishes with a puff of smoke"); 217 } 218 when WS_HIT: 219 delta.y += hero.y; 220 delta.x += hero.x; 221 if ((tp = moat(delta.y, delta.x)) != NULL) 222 { 223 if (rnd(20) == 0) 224 { 225 obj->o_damage = "3d8"; 226 obj->o_dplus = 9; 227 } 228 else 229 { 230 obj->o_damage = "2d8"; 231 obj->o_dplus = 4; 232 } 233 fight(&delta, tp->t_type, obj, FALSE); 234 } 235 when WS_HASTE_M: 236 case WS_SLOW_M: 237 y = hero.y; 238 x = hero.x; 239 while (step_ok(winat(y, x))) 240 { 241 y += delta.y; 242 x += delta.x; 243 } 244 if ((tp = moat(y, x)) != NULL) 245 { 246 if (which_one == WS_HASTE_M) 247 { 248 if (on(*tp, ISSLOW)) 249 tp->t_flags &= ~ISSLOW; 250 else 251 tp->t_flags |= ISHASTE; 252 } 253 else 254 { 255 if (on(*tp, ISHASTE)) 256 tp->t_flags &= ~ISHASTE; 257 else 258 tp->t_flags |= ISSLOW; 259 tp->t_turn = TRUE; 260 } 261 delta.y = y; 262 delta.x = x; 263 start_run(&delta); 264 } 265 when WS_ELECT: 266 case WS_FIRE: 267 case WS_COLD: 268 if (which_one == WS_ELECT) 269 name = "bolt"; 270 else if (which_one == WS_FIRE) 271 name = "flame"; 272 else 273 name = "ice"; 274 fire_bolt(&hero, &delta, name); 275 ws_know[which_one] = TRUE; 276 #ifdef DEBUG 277 otherwise: 278 msg("what a bizarre schtick!"); 279 #endif 280 } 281 if (--obj->o_charges < 0) 282 obj->o_charges = 0; 283 } 284 285 /* 286 * drain: 287 * Do drain hit points from player schtick 288 */ 289 drain() 290 { 291 THING *mp; 292 register int cnt; 293 register struct room *corp; 294 register THING **dp; 295 register bool inpass; 296 THING *drainee[40]; 297 298 /* 299 * First cnt how many things we need to spread the hit points among 300 */ 301 cnt = 0; 302 if (chat(hero.y, hero.x) == DOOR) 303 corp = &passages[flat(hero.y, hero.x) & F_PNUM]; 304 else 305 corp = NULL; 306 inpass = (proom->r_flags & ISGONE); 307 dp = drainee; 308 for (mp = mlist; mp != NULL; mp = next(mp)) 309 if (mp->t_room == proom || mp->t_room == corp || 310 (inpass && chat(mp->t_pos.y, mp->t_pos.x) == DOOR && 311 &passages[flat(mp->t_pos.y, mp->t_pos.x) & F_PNUM] == proom)) 312 *dp++ = mp; 313 if ((cnt = dp - drainee) == 0) 314 { 315 msg("you have a tingling feeling"); 316 return; 317 } 318 *dp = NULL; 319 pstats.s_hpt /= 2; 320 cnt = pstats.s_hpt / cnt + 1; 321 /* 322 * Now zot all of the monsters 323 */ 324 for (dp = drainee; *dp; dp++) 325 { 326 mp = *dp; 327 if ((mp->t_stats.s_hpt -= cnt) <= 0) 328 killed(mp, see_monst(mp)); 329 else 330 start_run(&mp->t_pos); 331 } 332 } 333 334 /* 335 * fire_bolt: 336 * Fire a bolt in a given direction from a specific starting place 337 */ 338 fire_bolt(start, dir, name) 339 coord *start, *dir; 340 char *name; 341 { 342 register byte dirch, ch; 343 register THING *tp; 344 register bool hit_hero, used, changed; 345 register int i, j; 346 coord pos; 347 struct { 348 coord s_pos; 349 byte s_under; 350 } spotpos[BOLT_LENGTH*2]; 351 THING bolt; 352 bool is_frost; 353 354 is_frost = (strcmp(name, "frost") == 0); 355 bolt.o_type = WEAPON; 356 bolt.o_which = FLAME; 357 bolt.o_damage = bolt.o_hurldmg = "6d6"; 358 bolt.o_hplus = 30; 359 bolt.o_dplus = 0; 360 w_names[FLAME] = name; 361 switch (dir->y + dir->x) { 362 when 0: dirch = '/'; 363 when 1: case -1: dirch = (dir->y == 0 ? '-' : '|'); 364 when 2: case -2: dirch = '\\'; 365 } 366 pos = *start; 367 hit_hero = (start != &hero); 368 used = FALSE; 369 changed = FALSE; 370 for (i = 0; i < BOLT_LENGTH && !used; i++) { 371 pos.y += dir->y; 372 pos.x += dir->x; 373 ch = winat(pos.y, pos.x); 374 spotpos[i].s_pos = pos; 375 if ((spotpos[i].s_under = mvinch(pos.y, pos.x)) == dirch) 376 spotpos[i].s_under = 0; 377 switch (ch) { 378 case DOOR: 379 case HWALL: 380 case VWALL: 381 case ULWALL: 382 case URWALL: 383 case LLWALL: 384 case LRWALL: 385 case ' ': 386 if (!changed) 387 hit_hero = !hit_hero; 388 changed = FALSE; 389 dir->y = -dir->y; 390 dir->x = -dir->x; 391 i--; 392 msg("the %s bounces", name); 393 break; 394 default: 395 if (!hit_hero && (tp = moat(pos.y, pos.x)) != NULL) { 396 hit_hero = TRUE; 397 changed = !changed; 398 if (tp->t_oldch != '@') 399 tp->t_oldch = chat(pos.y, pos.x); 400 if (!save_throw(VS_MAGIC, tp) || is_frost) { 401 bolt.o_pos = pos; 402 used = TRUE; 403 if (tp->t_type == 'D' && strcmp(name, "flame") == 0) 404 msg("the flame bounces off the dragon"); 405 else { 406 hit_monster(unc(pos), &bolt); 407 if (mvinch(unc(pos)) != dirch) 408 spotpos[i].s_under = mvinch(unc(pos)); 409 } 410 } else if (ch != 'X' || tp->t_disguise == 'X') { 411 if (start == &hero) 412 start_run(&pos); 413 msg("the %s whizzes past the %s", 414 name, monsters[ch-'A'].m_name); 415 } 416 } else if (hit_hero && ce(pos, hero)) { 417 hit_hero = FALSE; 418 changed = !changed; 419 if (!save(VS_MAGIC)) { 420 if (is_frost) { 421 msg("You are frozen by a blast of frost%s.", noterse(" from the Ice Monster")); 422 if (no_command < 20) 423 no_command += spread(7); 424 } else if ((pstats.s_hpt -= roll(6, 6)) <= 0) 425 if (start == &hero) 426 death('b'); 427 else 428 death(moat(start->y, start->x)->t_type); 429 used = TRUE; 430 if (!is_frost) 431 msg("you are hit by the %s", name); 432 } else 433 msg("the %s whizzes by you", name); 434 } 435 if (is_frost) 436 blue(); 437 else 438 red(); 439 tick_pause(); 440 mvaddch(pos.y, pos.x, dirch); 441 standend(); 442 } 443 } 444 for (j = 0; j < i; j++) { 445 tick_pause(); 446 if (spotpos[j].s_under) 447 mvaddch(spotpos[j].s_pos.y, spotpos[j].s_pos.x, spotpos[j].s_under); 448 } 449 } 450 451 /* 452 * charge_str: 453 * Return an appropriate string for a wand charge 454 */ 455 char * 456 charge_str(obj) 457 register THING *obj; 458 { 459 static char buf[20]; 460 461 if (!(obj->o_flags & ISKNOW)) 462 buf[0] = '\0'; 463 else 464 sprintf(buf, " [%d charges]", obj->o_charges); 465 return buf; 466 } 467 ÿ