Annotation of early-roguelike/srogue/sticks.c, Revision 1.1
1.1 ! rubenllo 1: /*
! 2: * Functions to deal with the various sticks one
! 3: * might find while wandering around the dungeon.
! 4: *
! 5: * @(#)sticks.c 9.0 (rdk) 7/17/84
! 6: *
! 7: * Super-Rogue
! 8: * Copyright (C) 1984 Robert D. Kindelberger
! 9: * All rights reserved.
! 10: *
! 11: * Based on "Rogue: Exploring the Dungeons of Doom"
! 12: * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
! 13: * All rights reserved.
! 14: *
! 15: * See the file LICENSE.TXT for full copyright and licensing information.
! 16: */
! 17:
! 18: #include <ctype.h>
! 19: #include <string.h>
! 20: #include "rogue.h"
! 21: #include "rogue.ext"
! 22:
! 23: void drain(int ymin, int ymax, int xmin, int xmax);
! 24:
! 25: /*
! 26: * fix_stick:
! 27: * Init a stick for the hero
! 28: */
! 29: void
! 30: fix_stick(struct object *cur)
! 31: {
! 32: struct rod *rd;
! 33:
! 34: cur->o_type = STICK;
! 35: cur->o_charges = 4 + rnd(5);
! 36: strcpy(cur->o_hurldmg, "1d1");
! 37: rd = &ws_stuff[cur->o_which];
! 38: cur->o_weight = rd->ws_wght;
! 39: cur->o_vol = rd->ws_vol;
! 40: if (strcmp(rd->ws_type, "staff") == 0) {
! 41: strcpy(cur->o_damage, "2d3");
! 42: cur->o_charges += rnd(5) + 3;
! 43: }
! 44: else {
! 45: strcpy(cur->o_damage, "1d1");
! 46: }
! 47: switch (cur->o_which) {
! 48: case WS_HIT:
! 49: if(rnd(100) < 15) {
! 50: cur->o_hplus = 9;
! 51: cur->o_dplus = 9;
! 52: strcpy(cur->o_damage,"3d8");
! 53: }
! 54: else {
! 55: cur->o_hplus = 3;
! 56: cur->o_dplus = 3;
! 57: strcpy(cur->o_damage,"1d8");
! 58: }
! 59: when WS_LIGHT:
! 60: cur->o_charges += 7 + rnd(9);
! 61: }
! 62: }
! 63:
! 64: /*
! 65: * do_zap:
! 66: * Zap a stick at something
! 67: */
! 68: void
! 69: do_zap(bool gotdir)
! 70: {
! 71: reg struct linked_list *item;
! 72: reg struct object *obj;
! 73: reg struct thing *tp;
! 74: reg int y, x, wh;
! 75: struct room *rp;
! 76: bool bless, curse;
! 77: int better = 0;
! 78:
! 79: if ((item = get_item("zap with", STICK)) == NULL)
! 80: return;
! 81: obj = OBJPTR(item);
! 82: wh = obj->o_which;
! 83: bless = o_on(obj, ISBLESS);
! 84: curse = o_on(obj, ISCURSED);
! 85: if (obj->o_type != STICK) {
! 86: msg("You can't zap with that!");
! 87: after = FALSE;
! 88: return;
! 89: }
! 90: if (obj->o_charges == 0) {
! 91: msg("Nothing happens.");
! 92: return;
! 93: }
! 94: if (!gotdir)
! 95: do {
! 96: delta.y = rnd(3) - 1;
! 97: delta.x = rnd(3) - 1;
! 98: } while (delta.y == 0 && delta.x == 0);
! 99: rp = player.t_room;
! 100: if (bless)
! 101: better = 3;
! 102: else if (curse)
! 103: better = -3;
! 104: switch (wh) {
! 105: case WS_SAPLIFE:
! 106: if (!bless) {
! 107: if (him->s_hpt > 1)
! 108: him->s_hpt /= 2; /* zap half his hit points */
! 109: }
! 110: when WS_CURE:
! 111: if (!curse) {
! 112: ws_know[WS_CURE] = TRUE;
! 113: heal_self(6, FALSE);
! 114: unconfuse(FALSE);
! 115: notslow(FALSE);
! 116: sight(FALSE);
! 117: }
! 118: when WS_PYRO:
! 119: if (!bless) {
! 120: msg("The rod explodes !!!");
! 121: chg_hpt(-roll(6,6), FALSE, K_ROD);
! 122: ws_know[WS_PYRO] = TRUE;
! 123: del_pack(item); /* throw it away */
! 124: }
! 125: when WS_HUNGER:
! 126: if (!bless) {
! 127: struct linked_list *ip;
! 128: struct object *lb;
! 129:
! 130: food_left /= 3;
! 131: if ((ip = pack) != NULL) {
! 132: lb = OBJPTR(ip);
! 133: if (lb->o_type == FOOD) {
! 134: if ((lb->o_count -= roll(1,4)) < 1)
! 135: del_pack(ip);
! 136: }
! 137: }
! 138: }
! 139: when WS_PARZ:
! 140: case WS_MREG:
! 141: case WS_MDEG:
! 142: case WS_ANNIH: {
! 143: struct linked_list *mitem;
! 144: struct thing *it;
! 145: reg int i,j;
! 146:
! 147: for (i = hero.y - 3; i <= hero.y + 3; i++) {
! 148: for (j = hero.x - 3; j <= hero.x + 3; j++) {
! 149: if (!cordok(i, j))
! 150: continue;
! 151: if (isalpha(mvwinch(mw,i,j))) {
! 152: mitem = find_mons(i, j);
! 153: if (mitem == NULL)
! 154: continue;
! 155: it = THINGPTR(mitem);
! 156: switch(wh) {
! 157: case WS_ANNIH:
! 158: if (!curse)
! 159: killed(mitem,FALSE);
! 160: when WS_MREG:
! 161: if (!bless)
! 162: it->t_stats.s_hpt *= 2;
! 163: when WS_MDEG:
! 164: if (!curse) {
! 165: it->t_stats.s_hpt /= 2;
! 166: if (it->t_stats.s_hpt < 2)
! 167: killed(mitem,FALSE);
! 168: }
! 169: when WS_PARZ:
! 170: if (!curse) {
! 171: it->t_flags |= ISPARA;
! 172: it->t_flags &= ~ISRUN;
! 173: }
! 174: }
! 175: }
! 176: }
! 177: }
! 178: }
! 179: when WS_LIGHT:
! 180: if (!curse) {
! 181: ws_know[WS_LIGHT] = TRUE;
! 182: if (rp == NULL)
! 183: msg("The corridor glows and then fades.");
! 184: else {
! 185: msg("The room is lit.");
! 186: rp->r_flags &= ~ISDARK;
! 187: light(&hero);
! 188: mvwaddch(cw, hero.y, hero.x, PLAYER);
! 189: }
! 190: }
! 191: when WS_DRAIN:
! 192: /*
! 193: * Take away 1/2 of hero's hit points, then take it away
! 194: * evenly from the monsters in the room (or next to hero
! 195: * if he is in a passage)
! 196: */
! 197: if (him->s_hpt < 2) {
! 198: msg("You are too weak to use it.");
! 199: return;
! 200: }
! 201: else if (!curse) {
! 202: if (rp == NULL)
! 203: drain(hero.y-1, hero.y+1, hero.x-1, hero.x+1);
! 204: else
! 205: drain(rp->r_pos.y, rp->r_pos.y+rp->r_max.y,
! 206: rp->r_pos.x, rp->r_pos.x+rp->r_max.x);
! 207: }
! 208: when WS_POLYM:
! 209: case WS_TELAWAY:
! 210: case WS_TELTO:
! 211: case WS_CANCEL:
! 212: case WS_MINVIS:
! 213: {
! 214: reg char monster, oldch;
! 215:
! 216: y = hero.y;
! 217: x = hero.x;
! 218: do {
! 219: y += delta.y;
! 220: x += delta.x;
! 221: } while (step_ok(winat(y, x)));
! 222: if (isalpha(monster = mvwinch(mw, y, x))) {
! 223: int omonst;
! 224:
! 225: if (wh != WS_MINVIS)
! 226: unhold(monster);
! 227: item = find_mons(y, x);
! 228: if (item == NULL)
! 229: break;
! 230: tp = THINGPTR(item);
! 231: omonst = tp->t_indx;
! 232: if (wh == WS_POLYM && !curse) {
! 233: detach(mlist, item);
! 234: discard(item);
! 235: oldch = tp->t_oldch;
! 236: delta.y = y;
! 237: delta.x = x;
! 238: monster = rnd_mon(FALSE, TRUE);
! 239: item = new_monster(monster, &delta, FALSE);
! 240: if (!(tp->t_flags & ISRUN))
! 241: runto(&delta, &hero);
! 242: if (isalpha(mvwinch(cw, y, x)))
! 243: mvwaddch(cw, y, x, monsters[monster].m_show);
! 244: tp->t_oldch = oldch;
! 245: ws_know[WS_POLYM] |= (monster != omonst);
! 246: }
! 247: else if (wh == WS_MINVIS && !bless) {
! 248: tp->t_flags |= ISINVIS;
! 249: mvwaddch(cw,y,x,tp->t_oldch); /* hide em */
! 250: runto(&tp->t_pos, &hero);
! 251: }
! 252: else if (wh == WS_CANCEL && !curse) {
! 253: tp->t_flags |= ISCANC;
! 254: tp->t_flags &= ~ISINVIS;
! 255: }
! 256: else {
! 257: if (wh == WS_TELAWAY) {
! 258: if (curse)
! 259: break;
! 260: tp->t_pos = *rnd_pos(&rooms[rnd_room()]);
! 261: }
! 262: else { /* WS_TELTO */
! 263: if (bless)
! 264: break;
! 265: tp->t_pos.y = hero.y + delta.y;
! 266: tp->t_pos.x = hero.x + delta.x;
! 267: }
! 268: if (isalpha(mvwinch(cw, y, x)))
! 269: mvwaddch(cw, y, x, tp->t_oldch);
! 270: tp->t_dest = &hero;
! 271: tp->t_flags |= ISRUN;
! 272: mvwaddch(mw, y, x, ' ');
! 273: mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, monster);
! 274: tp->t_oldch = mvwinch(cw,tp->t_pos.y,tp->t_pos.x);
! 275: }
! 276: }
! 277: }
! 278: when WS_MISSILE:
! 279: {
! 280: struct coord *whe;
! 281: static struct object bolt = {
! 282: {0, 0}, "", "6d6", "", '*', 0, 0, 1000, 0, 0, 0, 0, 0, 0,
! 283: };
! 284:
! 285: if (curse)
! 286: strcpy(bolt.o_hurldmg,"3d3");
! 287: else if (bless)
! 288: strcpy(bolt.o_hurldmg,"9d9");
! 289: ws_know[WS_MISSILE] = TRUE;
! 290: do_motion(&bolt, delta.y, delta.x);
! 291: whe = &bolt.o_pos;
! 292: if (isalpha(mvwinch(mw, whe->y, whe->x))) {
! 293: struct linked_list *it;
! 294:
! 295: runto(whe, &hero);
! 296: it = find_mons(whe->y, whe->x);
! 297: if (it != NULL) {
! 298: if (!save_throw(VS_MAGIC + better, THINGPTR(it))) {
! 299: hit_monster(whe, &bolt);
! 300: break;
! 301: }
! 302: }
! 303: }
! 304: msg("Missle vanishes.");
! 305: }
! 306: when WS_NOP:
! 307: msg("Your %s flickers momentarily and then fades",
! 308: ws_stuff[wh].ws_type);
! 309: when WS_HIT: {
! 310: char ch;
! 311:
! 312: delta.y += hero.y;
! 313: delta.x += hero.x;
! 314: ch = winat(delta.y, delta.x);
! 315: if (curse) { /* decrease for cursed */
! 316: strcpy(obj->o_damage,"1d1");
! 317: obj->o_hplus = obj->o_dplus = 0;
! 318: }
! 319: else if (bless) { /* increase for blessed */
! 320: strcpy(obj->o_damage,"5d8");
! 321: obj->o_hplus = obj->o_dplus = 12;
! 322: }
! 323: if (isalpha(ch))
! 324: fight(&delta, obj, FALSE);
! 325: }
! 326: when WS_HASTE_M:
! 327: case WS_CONFMON:
! 328: case WS_SLOW_M:
! 329: case WS_MOREMON: {
! 330: reg int m1,m2;
! 331: struct coord mp;
! 332: struct linked_list *titem;
! 333:
! 334: y = hero.y;
! 335: x = hero.x;
! 336: do {
! 337: y += delta.y;
! 338: x += delta.x;
! 339: } while (step_ok(winat(y, x)));
! 340: if (isalpha(mvwinch(mw, y, x))) {
! 341: item = find_mons(y, x);
! 342: if (item == NULL)
! 343: break;
! 344: tp = THINGPTR(item);
! 345: if (wh == WS_HASTE_M && !bless) { /* haste it */
! 346: if (on(*tp, ISSLOW))
! 347: tp->t_flags &= ~ISSLOW;
! 348: else
! 349: tp->t_flags |= ISHASTE;
! 350: }
! 351: else if (wh == WS_CONFMON && !curse) { /* confuse it */
! 352: tp->t_flags |= ISHUH;
! 353: if (pl_on(ISHELD) && tp->t_type == 'd')
! 354: player.t_flags &= ~ISHELD;
! 355: }
! 356: else if (wh == WS_SLOW_M && !curse) { /* slow it */
! 357: if (on(*tp, ISHASTE))
! 358: tp->t_flags &= ~ISHASTE;
! 359: else
! 360: tp->t_flags |= ISSLOW;
! 361: tp->t_turn = TRUE;
! 362: }
! 363: else if (!bless) { /* WS_MOREMON: multiply it */
! 364: char ch;
! 365: struct thing *th;
! 366:
! 367: for (m1 = tp->t_pos.x-1; m1 <= tp->t_pos.x+1; m1++) {
! 368: for(m2 = tp->t_pos.y-1; m2 <= tp->t_pos.y+1; m2++) {
! 369: if (hero.x == m1 && hero.y == m2)
! 370: continue;
! 371: ch = winat(m2,m1);
! 372: if (step_ok(ch)) {
! 373: mp.x = m1; /* create it */
! 374: mp.y = m2;
! 375: titem = new_monster(tp->t_indx, &mp, FALSE);
! 376: th = THINGPTR(titem);
! 377: th->t_flags |= ISMEAN;
! 378: runto(&mp, &hero);
! 379: }
! 380: }
! 381: }
! 382: }
! 383: delta.y = y;
! 384: delta.x = x;
! 385: runto(&delta, &hero);
! 386: }
! 387: }
! 388: when WS_ELECT:
! 389: case WS_FIRE:
! 390: case WS_COLD: {
! 391: reg char dirch, ch, *name;
! 392: reg bool bounced, used;
! 393: int boingcnt, boltlen;
! 394: struct coord pos;
! 395: struct coord spotpos[BOLT_LENGTH * 2];
! 396: static struct object bolt = {
! 397: {0, 0}, "", "6d6", "", '*', 0, 0, 1000, 0, 0, 0, 0, 0, 0,
! 398: };
! 399:
! 400: boltlen = BOLT_LENGTH;
! 401: if (curse) {
! 402: strcpy(bolt.o_hurldmg,"3d3");
! 403: boltlen -= 3;
! 404: }
! 405: else if (bless) {
! 406: strcpy(bolt.o_hurldmg,"9d9");
! 407: boltlen += 3;
! 408: }
! 409: switch (delta.y + delta.x) {
! 410: case 0: dirch = '/';
! 411: when 1: case -1: dirch = (delta.y == 0 ? '-' : '|');
! 412: when 2: case -2: dirch = '\\';
! 413: }
! 414: pos = hero;
! 415: bounced = FALSE;
! 416: boingcnt = 0;
! 417: used = FALSE;
! 418: if (wh == WS_ELECT)
! 419: name = "bolt";
! 420: else if (wh == WS_FIRE)
! 421: name = "flame";
! 422: else
! 423: name = "ice";
! 424: for (y = 0; y < boltlen && !used; y++) {
! 425: ch = winat(pos.y, pos.x);
! 426: spotpos[y] = pos;
! 427: switch (ch) {
! 428: case SECRETDOOR:
! 429: case '|':
! 430: case '-':
! 431: case ' ':
! 432: bounced = TRUE;
! 433: if (++boingcnt > 6)
! 434: used = TRUE; /* only so many bounces */
! 435: delta.y = -delta.y;
! 436: delta.x = -delta.x;
! 437: y--;
! 438: msg("The bolt bounces");
! 439: break;
! 440: default:
! 441: if (isalpha(ch)) {
! 442: struct linked_list *it;
! 443:
! 444: it = find_mons(pos.y, pos.x);
! 445: runto(&pos, &hero);
! 446: if (it != NULL) {
! 447: if (!save_throw(VS_MAGIC+better,THINGPTR(it))) {
! 448: bolt.o_pos = pos;
! 449: hit_monster(&pos, &bolt);
! 450: used = TRUE;
! 451: }
! 452: else if(ch != 'M' || show(pos.y,pos.x)=='M') {
! 453: msg("%s misses", name);
! 454: }
! 455: }
! 456: }
! 457: else if(bounced && pos.y==hero.y && pos.x==hero.x) {
! 458: bounced = FALSE;
! 459: if (!save(VS_MAGIC + better)) {
! 460: msg("The %s hits you.", name);
! 461: chg_hpt(-roll(6, 6),FALSE,K_BOLT);
! 462: used = TRUE;
! 463: }
! 464: else
! 465: msg("The %s whizzes by you.", name);
! 466: }
! 467: mvwaddch(cw, pos.y, pos.x, dirch);
! 468: draw(cw);
! 469: }
! 470: pos.y += delta.y;
! 471: pos.x += delta.x;
! 472: }
! 473: for (x = 0; x < y; x++)
! 474: mvwaddch(cw, spotpos[x].y, spotpos[x].x,
! 475: show(spotpos[x].y, spotpos[x].x));
! 476: ws_know[wh] = TRUE;
! 477: }
! 478: when WS_ANTIM: {
! 479: reg int m1, m2, x1, y1;
! 480: struct linked_list *ll;
! 481: struct thing *lt;
! 482: int ch, radius;
! 483:
! 484: y1 = hero.y;
! 485: x1 = hero.x;
! 486: do {
! 487: y1 += delta.y;
! 488: x1 += delta.x;
! 489: ch = winat(y1, x1);
! 490: } while (ch == PASSAGE || ch == FLOOR);
! 491: if (curse)
! 492: radius = 2;
! 493: else if (bless)
! 494: radius = 0;
! 495: else
! 496: radius = 1;
! 497: for (m1 = x1 - radius; m1 <= x1 + radius; m1++) {
! 498: for (m2 = y1 - radius; m2 <= y1 + radius; m2++) {
! 499: if (!cordok(m2, m1))
! 500: continue;
! 501: ch = winat(m2, m1);
! 502: if (m1 == hero.x && m2 == hero.y)
! 503: continue;
! 504: if (ch == ' ')
! 505: continue;
! 506: ll = find_obj(m2,m1);
! 507: if (ll != NULL) {
! 508: detach(lvl_obj,ll);
! 509: discard(ll);
! 510: }
! 511: ll = find_mons(m2,m1);
! 512: if (ll != NULL) {
! 513: lt = THINGPTR(ll);
! 514: him->s_exp += lt->t_stats.s_exp;
! 515: unhold(lt->t_type);
! 516: /*
! 517: * throw away anything that the monster
! 518: * was carrying in its pack
! 519: */
! 520: free_list(lt->t_pack);
! 521: detach(mlist,ll);
! 522: discard(ll);
! 523: mvwaddch(mw,m2,m1,' ');
! 524: }
! 525: mvaddch(m2,m1,' ');
! 526: mvwaddch(cw,m2,m1,' ');
! 527: }
! 528: }
! 529: touchwin(cw);
! 530: touchwin(mw);
! 531: check_level();
! 532: }
! 533: otherwise:
! 534: msg("What a bizarre schtick!");
! 535: }
! 536: obj->o_charges--;
! 537: }
! 538:
! 539: /*
! 540: * drain:
! 541: * Do drain hit points from player stick
! 542: */
! 543: void
! 544: drain(int ymin, int ymax, int xmin, int xmax)
! 545: {
! 546: reg int i, j, cnt;
! 547: reg struct thing *ick;
! 548: reg struct linked_list *item;
! 549:
! 550: /*
! 551: * First count how many things we need to spread the hit points among
! 552: */
! 553: cnt = 0;
! 554: for (i = ymin; i <= ymax; i++)
! 555: for (j = xmin; j <= xmax; j++)
! 556: if (isalpha(mvwinch(mw, i, j)))
! 557: cnt++;
! 558: if (cnt == 0) {
! 559: msg("You have a tingling feeling.");
! 560: return;
! 561: }
! 562: cnt = him->s_hpt / cnt;
! 563: him->s_hpt /= 2;
! 564: /*
! 565: * Now zot all of the monsters
! 566: */
! 567: for (i = ymin; i <= ymax; i++) {
! 568: for (j = xmin; j <= xmax; j++) {
! 569: if(isalpha(mvwinch(mw, i, j))) {
! 570: item = find_mons(i, j);
! 571: if (item == NULL)
! 572: continue;
! 573: ick = THINGPTR(item);
! 574: if ((ick->t_stats.s_hpt -= cnt) < 1)
! 575: killed(item,cansee(i,j) && !(ick->t_flags & ISINVIS));
! 576: }
! 577: }
! 578: }
! 579: }
! 580:
! 581: /*
! 582: * charge_str:
! 583: * Return number of charges left in a stick
! 584: */
! 585: char *
! 586: charge_str(struct object *obj)
! 587: {
! 588: static char buf[20];
! 589:
! 590: buf[0] = '\0';
! 591: if (o_on(obj,ISKNOW) || o_on(obj,ISPOST))
! 592: sprintf(buf, " [%d]", obj->o_charges);
! 593: return buf;
! 594: }
CVSweb