Mercurial > hg > early-roguelike
diff rogue3/sticks.c @ 0:527e2150eaf0
Import Rogue 3.6 from the Roguelike Restoration Project (r1490)
author | edwarj4 |
---|---|
date | Tue, 13 Oct 2009 13:33:34 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/sticks.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,401 @@ +/* + * Functions to implement the various sticks one might find + * while wandering around the dungeon. + * + * @(#)sticks.c 3.14 (Berkeley) 6/15/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 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 <ctype.h> +#include <string.h> +#include "rogue.h" + +void +fix_stick(struct object *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 = 3; + cur->o_dplus = 3; + strcpy(cur->o_damage,"1d8"); + when WS_LIGHT: + cur->o_charges = 10 + rnd(10); + } +} + +void +do_zap(int gotdir) +{ + struct linked_list *item; + struct object *obj; + struct room *rp; + struct thing *tp; + int y, x; + + if ((item = get_item("zap with", STICK)) == NULL) + return; + obj = (struct object *) ldata(item); + if (obj->o_type != STICK) + { + msg("You can't zap with that!"); + after = FALSE; + return; + } + if (obj->o_charges == 0) + { + msg("Nothing happens."); + return; + } + if (!gotdir) + do { + delta.y = rnd(3) - 1; + delta.x = rnd(3) - 1; + } while (delta.y == 0 && delta.x == 0); + switch (obj->o_which) + { + case WS_LIGHT: + /* + * Reddy Kilowat wand. Light up the room + */ + ws_know[WS_LIGHT] = TRUE; + if ((rp = roomin(&hero)) == NULL) + msg("The corridor glows and then fades"); + else + { + addmsg("The room is lit"); + if (!terse) + addmsg(" by a shimmering blue light."); + endmsg(); + rp->r_flags &= ~ISDARK; + /* + * Light the room and put the player back up + */ + light(&hero); + mvwaddch(cw, hero.y, hero.x, PLAYER); + } + 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 if ((rp = roomin(&hero)) == NULL) + drain(hero.y-1, hero.y+1, hero.x-1, hero.x+1); + else + drain(rp->r_pos.y, rp->r_pos.y+rp->r_max.y, + rp->r_pos.x, rp->r_pos.x+rp->r_max.x); + when WS_POLYMORPH: + case WS_TELAWAY: + case WS_TELTO: + case WS_CANCEL: + { + int monster; + int oldch; + int rm; + + y = hero.y; + x = hero.x; + while (step_ok(winat(y, x))) + { + y += delta.y; + x += delta.x; + } + if (isupper(monster = mvwinch(mw, y, x))) + { + int omonst = monster; + + if (monster == 'F') + player.t_flags &= ~ISHELD; + item = find_mons(y, x); + tp = (struct thing *) ldata(item); + if (obj->o_which == WS_POLYMORPH) + { + detach(mlist, item); + oldch = tp->t_oldch; + delta.y = y; + delta.x = x; + new_monster(item, monster = rnd(26) + 'A', &delta); + if (!(tp->t_flags & ISRUN)) + runto(&delta, &hero); + if (isupper(mvwinch(cw, y, x))) + mvwaddch(cw, y, x, monster); + tp->t_oldch = oldch; + ws_know[WS_POLYMORPH] |= (monster != omonst); + } + else if (obj->o_which == WS_CANCEL) + { + tp->t_flags |= ISCANC; + tp->t_flags &= ~ISINVIS; + } + else + { + 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); + } + else + { + tp->t_pos.y = hero.y + delta.y; + tp->t_pos.x = hero.x + delta.x; + } + if (isupper(mvwinch(cw, y, x))) + mvwaddch(cw, y, x, tp->t_oldch); + tp->t_dest = &hero; + tp->t_flags |= ISRUN; + mvwaddch(mw, y, x, ' '); + mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, monster); + if (tp->t_pos.y != y || tp->t_pos.x != x) + tp->t_oldch = mvwinch(cw, tp->t_pos.y, tp->t_pos.x); + } + } + } + when WS_MISSILE: + { + static struct object bolt = + { + '*' , {0, 0}, 0, "", "1d4" , 0, 0, 100, 1, 0, 0, 0 + }; + + do_motion(&bolt, delta.y, delta.x); + if (isupper(mvwinch(mw, bolt.o_pos.y, bolt.o_pos.x)) + && !save_throw(VS_MAGIC, THINGPTR(find_mons(unc(bolt.o_pos))))) + hit_monster(unc(bolt.o_pos), &bolt); + else if (terse) + msg("Missile vanishes"); + else + msg("The missile vanishes with a puff of smoke"); + ws_know[WS_MISSILE] = TRUE; + } + when WS_HIT: + { + int ch; + + delta.y += hero.y; + delta.x += hero.x; + ch = winat(delta.y, delta.x); + if (isupper(ch)) + { + 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, ch, 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 (isupper(mvwinch(mw, y, x))) + { + item = find_mons(y, x); + tp = (struct thing *) ldata(item); + 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: + { + int dirch; + char *name; + int ch; + int bounced, used; + coord pos; + coord spotpos[BOLT_LENGTH]; + static struct object bolt = + { + '*' , {0, 0}, 0, "", "6d6" , 0, 0, 100, 0, 0, 0 ,0 + }; + + + switch (delta.y + delta.x) + { + case 0: dirch = '/'; + when 1: case -1: dirch = (delta.y == 0 ? '-' : '|'); + when 2: case -2: dirch = '\\'; + } + pos = hero; + bounced = FALSE; + used = FALSE; + if (obj->o_which == WS_ELECT) + name = "bolt"; + else if (obj->o_which == WS_FIRE) + name = "flame"; + else + name = "ice"; + for (y = 0; y < BOLT_LENGTH && !used; y++) + { + ch = winat(pos.y, pos.x); + spotpos[y] = pos; + switch (ch) + { + case DOOR: + case SECRETDOOR: + case '|': + case '-': + case ' ': + bounced = TRUE; + delta.y = -delta.y; + delta.x = -delta.x; + y--; + msg("The bolt bounces"); + break; + default: + if (!bounced && isupper(ch)) + { + if (!save_throw(VS_MAGIC, THINGPTR(find_mons(unc(pos))))) + { + bolt.o_pos = pos; + hit_monster(unc(pos), &bolt); + used = TRUE; + } + else if (ch != 'M' || show(pos.y, pos.x) == 'M') + { + if (terse) + msg("%s misses", name); + else + msg("The %s whizzes past the %s", name, monsters[ch-'A'].m_name); + runto(&pos, &hero); + } + } + else if (bounced && pos.y == hero.y && pos.x == hero.x) + { + bounced = FALSE; + if (!save(VS_MAGIC)) + { + if (terse) + msg("The %s hits", name); + else + msg("You are hit by the %s", name); + if ((pstats.s_hpt -= roll(6, 6)) <= 0) + death('b'); + used = TRUE; + } + else + msg("The %s whizzes by you", name); + } + mvwaddch(cw, pos.y, pos.x, dirch); + draw(cw); + } + pos.y += delta.y; + pos.x += delta.x; + } + for (x = 0; x < y; x++) + mvwaddch(cw, spotpos[x].y, spotpos[x].x, show(spotpos[x].y, spotpos[x].x)); + 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(int ymin, int ymax, int xmin, int xmax) +{ + int i, j, cnt; + struct thing *ick; + struct linked_list *item; + + /* + * First count how many things we need to spread the hit points among + */ + cnt = 0; + for (i = ymin; i <= ymax; i++) + for (j = xmin; j <= xmax; j++) + if (isupper(mvwinch(mw, i, j))) + cnt++; + if (cnt == 0) + { + msg("You have a tingling feeling"); + return; + } + cnt = pstats.s_hpt / cnt; + pstats.s_hpt /= 2; + /* + * Now zot all of the monsters + */ + for (i = ymin; i <= ymax; i++) + for (j = xmin; j <= xmax; j++) + if (isupper(mvwinch(mw, i, j)) && + ((item = find_mons(i, j)) != NULL)) + { + ick = (struct thing *) ldata(item); + if ((ick->t_stats.s_hpt -= cnt) < 1) + killed(item, cansee(i, j) && !on(*ick, ISINVIS)); + } +} + +/* + * charge a wand for wizards. + */ +char * +charge_str(struct object *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; +}