/* * Functions to implement the various sticks one might find * while wandering around the dungeon. * * @(#)sticks.c 4.22 (Berkeley) 5/19/82 * * Rogue: Exploring the Dungeons of Doom * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman * All rights reserved. * * See the file LICENSE.TXT for full copyright and licensing information. */ #include #include #include #include "rogue.h" void drain(void); /* * fix_stick: * Set up a new stick */ void fix_stick(THING *cur) { if (strcmp(ws_type[cur->o_which], "staff") == 0) strcpy(cur->o_damage,"2d3"); else strcpy(cur->o_damage,"1d1"); strcpy(cur->o_hurldmg,"1d1"); cur->o_charges = 3 + rnd(5); switch (cur->o_which) { case WS_HIT: cur->o_hplus = 100; cur->o_dplus = 3; strcpy(cur->o_damage,"1d8"); when WS_LIGHT: cur->o_charges = 10 + rnd(10); } } /* * do_zap: * Perform a zap with a wand */ void do_zap(void) { register THING *obj, *tp; register int y, x; register char *name; if ((obj = get_item("zap with", STICK)) == NULL) return; if (obj->o_type != STICK) { after = FALSE; msg("you can't zap with that!"); return; } if (obj->o_charges == 0) { msg("nothing happens"); return; } switch (obj->o_which) { case WS_LIGHT: /* * Reddy Kilowat wand. Light up the room */ ws_know[WS_LIGHT] = TRUE; if (proom->r_flags & ISGONE) msg("the corridor glows and then fades"); else { proom->r_flags &= ~ISDARK; /* * Light the room and put the player back up */ enter_room(&hero); addmsg("the room is lit"); if (!terse) addmsg(" by a shimmering blue light"); endmsg(); } when WS_DRAIN: /* * Take away 1/2 of hero's hit points, then take it away * evenly from the monsters in the room (or next to hero * if he is in a passage) */ if (pstats.s_hpt < 2) { msg("you are too weak to use it"); return; } else drain(); when WS_POLYMORPH: case WS_TELAWAY: case WS_TELTO: case WS_CANCEL: { register char monster, oldch; register int rm; y = hero.y; x = hero.x; while (step_ok(winat(y, x))) { y += delta.y; x += delta.x; } if ((tp = moat(y, x)) != NULL) { register char omonst; omonst = monster = tp->t_type; if (monster == 'F') player.t_flags &= ~ISHELD; if (obj->o_which == WS_POLYMORPH) { register THING *pp; pp = tp->t_pack; detach(mlist, tp); if (see_monst(tp)) mvaddch(y, x, chat(y, x)); oldch = tp->t_oldch; delta.y = y; delta.x = x; new_monster(tp, monster = rnd(26) + 'A', &delta); if (see_monst(tp)) mvaddch(y, x, monster); tp->t_oldch = oldch; tp->t_pack = pp; ws_know[WS_POLYMORPH] |= (monster != omonst); } else if (obj->o_which == WS_CANCEL) { tp->t_flags |= ISCANC; tp->t_flags &= ~(ISINVIS|CANHUH); tp->t_disguise = tp->t_type; } else { if (isupper(toascii(mvinch(y,x)))) mvaddch(y, x, tp->t_oldch); if (obj->o_which == WS_TELAWAY) { do { rm = rnd_room(); rnd_pos(&rooms[rm], &tp->t_pos); } until (winat(tp->t_pos.y, tp->t_pos.x) == FLOOR); tp->t_room = roomin(&tp->t_pos); tp->t_oldch = mvinch(tp->t_pos.y, tp->t_pos.x); if (see_monst(tp)) mvaddch(tp->t_pos.y, tp->t_pos.x, tp->t_disguise); else if (on(player, SEEMONST)) { standout(); mvaddch(tp->t_pos.y, tp->t_pos.x, tp->t_disguise); standend(); } } else { tp->t_pos.y = hero.y + delta.y; tp->t_pos.x = hero.x + delta.x; if (tp->t_pos.y != y || tp->t_pos.x != x) tp->t_oldch = mvinch(tp->t_pos.y, tp->t_pos.x); } moat(y, x) = NULL; moat(tp->t_pos.y, tp->t_pos.x) = tp; if (tp->t_type == 'F') player.t_flags &= ~ISHELD; } tp->t_dest = &hero; tp->t_flags |= ISRUN; } } when WS_MISSILE: { THING bolt; ws_know[WS_MISSILE] = TRUE; bolt.o_type = '*'; strcpy(bolt.o_hurldmg,"1d4"); bolt.o_hplus = 100; bolt.o_dplus = 1; bolt.o_flags = ISMISL; if (cur_weapon != NULL) bolt.o_launch = cur_weapon->o_which; do_motion(&bolt, delta.y, delta.x); if ((tp = moat(bolt.o_pos.y, bolt.o_pos.x)) != NULL && !save_throw(VS_MAGIC, tp)) hit_monster(unc(bolt.o_pos), &bolt); else if (terse) msg("missle vanishes"); else msg("the missle vanishes with a puff of smoke"); } when WS_HIT: delta.y += hero.y; delta.x += hero.x; if ((tp = moat(delta.y, delta.x)) != NULL) { if (rnd(20) == 0) { strcpy(obj->o_damage,"3d8"); obj->o_dplus = 9; } else { strcpy(obj->o_damage,"1d8"); obj->o_dplus = 3; } fight(&delta, tp->t_type, obj, FALSE); } when WS_HASTE_M: case WS_SLOW_M: y = hero.y; x = hero.x; while (step_ok(winat(y, x))) { y += delta.y; x += delta.x; } if ((tp = moat(y, x)) != NULL) { if (obj->o_which == WS_HASTE_M) { if (on(*tp, ISSLOW)) tp->t_flags &= ~ISSLOW; else tp->t_flags |= ISHASTE; } else { if (on(*tp, ISHASTE)) tp->t_flags &= ~ISHASTE; else tp->t_flags |= ISSLOW; tp->t_turn = TRUE; } delta.y = y; delta.x = x; runto(&delta, &hero); } when WS_ELECT: case WS_FIRE: case WS_COLD: if (obj->o_which == WS_ELECT) name = "bolt"; else if (obj->o_which == WS_FIRE) name = "flame"; else name = "ice"; fire_bolt(&hero, &delta, name); ws_know[obj->o_which] = TRUE; when WS_NOP: otherwise: msg("what a bizarre schtick!"); } obj->o_charges--; } /* * drain: * Do drain hit points from player shtick */ void drain(void) { register THING *mp; register int cnt; register struct room *corp; register THING **dp; register bool inpass; static THING *drainee[40]; /* * First cnt how many things we need to spread the hit points among */ cnt = 0; if (chat(hero.y, hero.x) == DOOR) corp = &passages[flat(hero.y, hero.x) & F_PNUM]; else corp = NULL; inpass = (proom->r_flags & ISGONE); dp = drainee; for (mp = mlist; mp != NULL; mp = next(mp)) if (mp->t_room == proom || mp->t_room == corp || (inpass && chat(mp->t_pos.y, mp->t_pos.x) == DOOR && &passages[flat(mp->t_pos.y, mp->t_pos.x) & F_PNUM] == proom)) *dp++ = mp; if ((cnt = dp - drainee) == 0) { msg("you have a tingling feeling"); return; } *dp = NULL; pstats.s_hpt /= 2; cnt = pstats.s_hpt / cnt; /* * Now zot all of the monsters */ for (dp = drainee; *dp; dp++) { mp = *dp; if ((mp->t_stats.s_hpt -= cnt) <= 0) killed(mp, see_monst(mp)); else runto(&mp->t_pos, &hero); } } /* * fire_bolt: * Fire a bolt in a given direction from a specific starting place */ void fire_bolt(coord *start, coord *dir, char *name) { register char dirch, ch; register THING *tp; register bool hit_hero, used, changed; register int i, j; coord pos; coord spotpos[BOLT_LENGTH]; THING bolt; bolt.o_type = WEAPON; bolt.o_which = FLAME; strcpy(bolt.o_hurldmg,"6d6"); bolt.o_hplus = 100; bolt.o_dplus = 0; bolt.o_flags = 0; w_names[FLAME] = name; switch (dir->y + dir->x) { case 0: dirch = '/'; when 1: case -1: dirch = (dir->y == 0 ? '-' : '|'); when 2: case -2: dirch = '\\'; } pos = *start; hit_hero = (start != &hero); used = FALSE; changed = FALSE; for (i = 0; i < BOLT_LENGTH && !used; i++) { pos.y += dir->y; pos.x += dir->x; ch = winat(pos.y, pos.x); spotpos[i] = pos; switch (ch) { case DOOR: /* * this code is necessary if the hero is on a door * and he fires at the wall the door is in, it would * otherwise loop infinitely * It is also needed if a dragon flames at the hero. * If the hero is at a door, the dragon flame would bounce * and could kill other monsters inadvertly. */ if (ce(hero, pos)) goto def; /* FALLTHROUGH */ case '|': case '-': case ' ': if (!changed) hit_hero = !hit_hero; changed = FALSE; dir->y = -dir->y; dir->x = -dir->x; i--; msg("the %s bounces", name); break; default: def: if (!hit_hero && (tp = moat(pos.y, pos.x)) != NULL) { hit_hero = TRUE; changed = !changed; tp->t_oldch = chat(pos.y, pos.x); if (!save_throw(VS_MAGIC, tp)) { bolt.o_pos = pos; used = TRUE; if (tp->t_type == 'D' && strcmp(name, "flame") == 0) { addmsg("the flame bounces"); if (!terse) msg("off the dragon"); endmsg(); } else hit_monster(unc(pos), &bolt); } else if (ch != 'M' || tp->t_disguise == 'M') { if (start == &hero) runto(&pos, &hero); if (terse) msg("%s misses", name); else msg("the %s whizzes past the %s", name, monsters[ch-'A'].m_name); } } else if (hit_hero && ce(pos, hero)) { hit_hero = FALSE; changed = !changed; if (!save(VS_MAGIC)) { if ((pstats.s_hpt -= roll(6, 6)) <= 0) if (start == &hero) death('b'); else death(moat(start->y, start->x)->t_type); used = TRUE; if (terse) msg("the %s hits", name); else msg("you are hit by the %s", name); } else msg("the %s whizzes by you", name); } mvaddch(pos.y, pos.x, dirch); refresh(); } } for (j = 0; j < i; j++) mvaddch(spotpos[j].y, spotpos[j].x, chat(spotpos[j].y, spotpos[j].x)); } /* * charge_str: * Return an appropriate string for a wand charge */ char * charge_str(THING *obj) { static char buf[20]; if (!(obj->o_flags & ISKNOW)) buf[0] = '\0'; else if (terse) sprintf(buf, " [%d]", obj->o_charges); else sprintf(buf, " [%d charges]", obj->o_charges); return buf; }