Mercurial > hg > early-roguelike
diff rogue5/sticks.c @ 33:f502bf60e6e4
Import Rogue 5.4 from the Roguelike Restoration Project (r1490)
author | elwin |
---|---|
date | Mon, 24 May 2010 20:10:59 +0000 |
parents | |
children | 1e1c81fbb533 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue5/sticks.c Mon May 24 20:10:59 2010 +0000 @@ -0,0 +1,431 @@ +/* + * Functions to implement the various sticks one might find + * while wandering around the dungeon. + * + * @(#)sticks.c 4.39 (Berkeley) 02/05/99 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include <curses.h> +#include <string.h> +#include <ctype.h> +#include "rogue.h" + +/* + * fix_stick: + * Set up a new stick + */ + +void +fix_stick(THING *cur) +{ + if (strcmp(ws_type[cur->o_which], "staff") == 0) + strncpy(cur->o_damage,"2x3",sizeof(cur->o_damage)); + else + strncpy(cur->o_damage,"1x1",sizeof(cur->o_damage)); + strncpy(cur->o_hurldmg,"1x1",sizeof(cur->o_hurldmg)); + + switch (cur->o_which) + { + case WS_LIGHT: + cur->o_charges = rnd(10) + 10; + otherwise: + cur->o_charges = rnd(5) + 3; + } +} + +/* + * do_zap: + * Perform a zap with a wand + */ + +void +do_zap(void) +{ + THING *obj, *tp; + int y, x; + char *name; + int monster, oldch; + THING bolt; + + 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_info[WS_LIGHT].oi_know = 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 %s light", pick_color("blue")); + 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_INVIS: + case WS_POLYMORPH: + case WS_TELAWAY: + case WS_TELTO: + case WS_CANCEL: + y = hero.y; + x = hero.x; + while (step_ok(winat(y, x))) + { + y += delta.y; + x += delta.x; + } + if ((tp = moat(y, x)) != NULL) + { + monster = tp->t_type; + if (monster == 'F') + player.t_flags &= ~ISHELD; + switch (obj->o_which) { + case WS_INVIS: + tp->t_flags |= ISINVIS; + if (cansee(y, x)) + mvaddch(y, x, tp->t_oldch); + break; + case WS_POLYMORPH: + { + 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_info[WS_POLYMORPH].oi_know |= see_monst(tp); + break; + } + case WS_CANCEL: + tp->t_flags |= ISCANC; + tp->t_flags &= ~(ISINVIS|CANHUH); + tp->t_disguise = tp->t_type; + if (see_monst(tp)) + mvaddch(y, x, tp->t_disguise); + break; + case WS_TELAWAY: + case WS_TELTO: + { + coord new_pos; + + if (obj->o_which == WS_TELAWAY) + { + do + { + find_floor(NULL, &new_pos, FALSE, TRUE); + } while (ce(new_pos, hero)); + } + else + { + new_pos.y = hero.y + delta.y; + new_pos.x = hero.x + delta.x; + } + tp->t_dest = &hero; + tp->t_flags |= ISRUN; + relocate(tp, &new_pos); + } + } + } + when WS_MISSILE: + ws_info[WS_MISSILE].oi_know = TRUE; + bolt.o_type = '*'; + strncpy(bolt.o_hurldmg,"1x4",sizeof(bolt.o_hurldmg)); + 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_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); + } + 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_info[obj->o_which].oi_know = TRUE; + when WS_NOP: + break; +#ifdef MASTER + otherwise: + msg("what a bizarre schtick!"); +#endif + } + obj->o_charges--; +} + +/* + * drain: + * Do drain hit points from player shtick + */ + +void +drain(void) +{ + THING *mp; + struct room *corp; + THING **dp; + int cnt; + int inpass; + 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 = (int)(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); + } +} + +/* + * fire_bolt: + * Fire a bolt in a given direction from a specific starting place + */ + +void +fire_bolt(const coord *start, coord *dir, const char *name) +{ + coord *c1, *c2; + THING *tp; + int dirch = 0, ch; + int hit_hero, used, changed; + coord pos; + coord spotpos[BOLT_LENGTH]; + THING bolt; + + bolt.o_type = WEAPON; + bolt.o_which = FLAME; + strncpy(bolt.o_hurldmg,"6x6",sizeof(bolt.o_hurldmg)); + bolt.o_hplus = 100; + bolt.o_dplus = 0; + weap_info[FLAME].oi_name = 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 (c1 = spotpos; c1 <= &spotpos[BOLT_LENGTH-1] && !used; c1++) + { + pos.y += dir->y; + pos.x += dir->x; + *c1 = pos; + ch = winat(pos.y, pos.x); + 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 + */ + 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; + c1--; + 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) + addmsg(" off the dragon"); + endmsg(); + } + else + hit_monster(unc(pos), &bolt); + } + else if (ch != 'M' || tp->t_disguise == 'M') + { + if (start == &hero) + runto(&pos); + if (terse) + msg("%s misses", name); + else + msg("the %s whizzes past %s", name, set_mname(tp)); + } + } + 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 (c2 = spotpos; c2 < c1; c2++) + mvaddch(c2->y, c2->x, chat(c2->y, c2->x)); +} + +/* + * charge_str: + * Return an appropriate string for a wand charge + */ +const char * +charge_str(const 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; +}