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