Annotation of early-roguelike/arogue7/misc.c, Revision 1.1
1.1 ! rubenllo 1: /*
! 2: * misc.c - routines dealing specifically with miscellaneous magic
! 3: *
! 4: * Advanced Rogue
! 5: * Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
! 6: * All rights reserved.
! 7: *
! 8: * Based on "Rogue: Exploring the Dungeons of Doom"
! 9: * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
! 10: * All rights reserved.
! 11: *
! 12: * See the file LICENSE.TXT for full copyright and licensing information.
! 13: */
! 14:
! 15: #include "curses.h"
! 16: #include <stdlib.h>
! 17: #include <ctype.h>
! 18: #include <string.h>
! 19: #include "rogue.h"
! 20: #ifdef PC7300
! 21: #include "menu.h"
! 22: #endif
! 23:
! 24: /*
! 25: * routines dealing specifically with miscellaneous magic
! 26: */
! 27:
! 28: /*
! 29: * changeclass:
! 30: * Change the player's class to the specified one.
! 31: */
! 32:
! 33: void
! 34: changeclass(int newclass)
! 35: {
! 36: if (newclass == player.t_ctype) {
! 37: msg("You feel more skillful.");
! 38: raise_level();
! 39: }
! 40: else {
! 41: /*
! 42: * reset his class and then use check_level to reset hit
! 43: * points and the right level for his exp pts
! 44: * drop exp pts by 10%
! 45: */
! 46: long save;
! 47:
! 48: msg("You feel like a whole new person!");
! 49:
! 50: /*
! 51: * if he becomes a thief he has to have leather armor
! 52: */
! 53: if ((newclass == C_THIEF || newclass == C_ASSASIN) &&
! 54: cur_armor != NULL &&
! 55: cur_armor->o_which != LEATHER &&
! 56: cur_armor->o_which != STUDDED_LEATHER )
! 57: cur_armor->o_which = STUDDED_LEATHER;
! 58: /*
! 59: * if he becomes a monk he can't wear armor
! 60: */
! 61: if (newclass == C_MONK && cur_armor != NULL) {
! 62: cur_armor->o_ac = armors[cur_armor->o_which].a_class -
! 63: cur_armor->o_ac;
! 64: cur_armor->o_type = MM;
! 65: cur_armor->o_which = MM_PROTECT;
! 66: cur_armor->o_flags &= ~(ISPROT | ISKNOW | ISMETAL);
! 67: cur_misc[WEAR_CLOAK] = cur_armor;
! 68: cur_armor = NULL;
! 69: }
! 70: /*
! 71: * if he used to be a spell caster of some sort, kill the fuse
! 72: */
! 73: if (player.t_ctype == C_MAGICIAN || player.t_ctype == C_RANGER)
! 74: extinguish(spell_recovery);
! 75: if (player.t_ctype == C_DRUID || player.t_ctype == C_RANGER)
! 76: extinguish(chant_recovery);
! 77: if ((player.t_ctype == C_CLERIC || player.t_ctype == C_PALADIN) &&
! 78: !cur_relic[HEIL_ANKH])
! 79: extinguish(prayer_recovery);
! 80: /*
! 81: * if he becomes a spell caster of some kind, give him a fuse
! 82: */
! 83: if (newclass == C_MAGICIAN || newclass == C_RANGER)
! 84: fuse(spell_recovery, NULL, SPELLTIME, AFTER);
! 85: if (newclass == C_DRUID || newclass == C_RANGER)
! 86: fuse(chant_recovery, NULL, SPELLTIME, AFTER);
! 87: if ((newclass==C_CLERIC || newclass==C_PALADIN) && !cur_misc[HEIL_ANKH])
! 88: fuse(prayer_recovery, NULL, SPELLTIME, AFTER);
! 89: /*
! 90: * if he's changing from a fighter then may have to change
! 91: * his sword since only fighter can use two-handed
! 92: * and bastard swords
! 93: */
! 94: if ((player.t_ctype == C_FIGHTER ||
! 95: player.t_ctype == C_RANGER ||
! 96: player.t_ctype == C_PALADIN) &&
! 97: cur_weapon != NULL &&
! 98: cur_weapon->o_type == WEAPON &&
! 99: (cur_weapon->o_which== BASWORD ||
! 100: cur_weapon->o_which== TWOSWORD ) &&
! 101: !(newclass == C_FIGHTER ||
! 102: newclass == C_RANGER ||
! 103: newclass == C_PALADIN) &&
! 104: !(newclass == C_ASSASIN &&
! 105: cur_weapon->o_which == BASWORD))
! 106: cur_weapon->o_which = SWORD;
! 107:
! 108: /*
! 109: * if he was a thief then take out the trap_look() daemon
! 110: */
! 111: if (player.t_ctype == C_THIEF ||
! 112: player.t_ctype == C_MONK ||
! 113: player.t_ctype == C_ASSASIN)
! 114: kill_daemon(trap_look);
! 115:
! 116: /*
! 117: * if he becomes a thief then add the trap_look() daemon
! 118: */
! 119: if (newclass == C_THIEF || newclass == C_ASSASIN || newclass == C_MONK)
! 120: start_daemon(trap_look, NULL, AFTER);
! 121: char_type = player.t_ctype = newclass;
! 122: save = pstats.s_hpt;
! 123: max_stats.s_hpt = pstats.s_hpt = 0;
! 124: max_stats.s_lvl = pstats.s_lvl = 0;
! 125: max_stats.s_lvladj = pstats.s_lvladj = 0;
! 126: max_stats.s_exp = pstats.s_exp -= pstats.s_exp/10;
! 127: check_level();
! 128: if (pstats.s_hpt > save) /* don't add to current hits */
! 129: pstats.s_hpt = save;
! 130: }
! 131: }
! 132:
! 133: /*
! 134: * Use the relic that our monster is wielding.
! 135: */
! 136: void
! 137: m_use_relic(struct thing *monster)
! 138: {
! 139: register struct object *obj;
! 140:
! 141: /* Make sure we really have it */
! 142: if (monster->t_using) obj = OBJPTR(monster->t_using);
! 143: else {
! 144: debug("Relic not set!");
! 145: monster->t_action = A_NIL;
! 146: return;
! 147: }
! 148:
! 149: /* Now let's see what we're using */
! 150: if (obj->o_type == RELIC) switch (obj->o_which) {
! 151: case MING_STAFF: {
! 152: static struct object missile = {
! 153: MISSILE, {0,0}, "", 0, "", "0d4 " , NULL, 0, WS_MISSILE, 100, 1
! 154: };
! 155:
! 156: debug("Firing Ming's staff");
! 157: sprintf(missile.o_hurldmg, "%dd4", monster->t_stats.s_lvl);
! 158: do_motion(&missile,
! 159: monster->t_newpos.y, monster->t_newpos.x, monster);
! 160: hit_monster(unc(missile.o_pos), &missile, monster);
! 161: monster->t_artifact = monster->t_artifact * 4 / 5;
! 162: }
! 163: when EMORI_CLOAK:
! 164: debug("stunning with Emori's cloak");
! 165: do_zap(monster, obj, &monster->t_newpos, WS_PARALYZE, 0);
! 166: obj->o_charges = 0;
! 167:
! 168: when ASMO_ROD: {
! 169: char *name;
! 170:
! 171: switch (rnd(3)) { /* Select a function */
! 172: case 0: name = "lightning bolt";
! 173: when 1: name = "flame";
! 174: otherwise: name = "ice";
! 175: }
! 176: shoot_bolt( monster,
! 177: monster->t_pos,
! 178: monster->t_newpos,
! 179: FALSE,
! 180: monster->t_index,
! 181: name,
! 182: roll(monster->t_stats.s_lvl,6));
! 183: monster->t_artifact /= 2;
! 184: }
! 185: when BRIAN_MANDOLIN:
! 186: /* Make sure the defendant is still around */
! 187: if (DISTANCE(monster->t_pos.y, monster->t_pos.x,
! 188: hero.y, hero.x) < 25) {
! 189: if (!save(VS_MAGIC, &player, -4) &&
! 190: !ISWEARING(R_ALERT)) {
! 191: msg("Some beautiful music enthralls you.");
! 192: player.t_no_move += movement(&player) * FREEZETIME;
! 193: player.t_action = A_FREEZE;
! 194: monster->t_artifact = monster->t_artifact * 2 / 3;
! 195: }
! 196: else {
! 197: msg("You wince at a sour note.");
! 198: monster->t_artifact /= 3;
! 199: }
! 200: }
! 201: when GERYON_HORN:
! 202: /* Make sure the defendant is still around */
! 203: if (DISTANCE(monster->t_pos.y, monster->t_pos.x,
! 204: hero.y, hero.x) < 25) {
! 205: if (!ISWEARING(R_HEROISM) &&
! 206: !save(VS_MAGIC, &player, -4)) {
! 207: turn_on(player, ISFLEE);
! 208: player.t_dest = &monster->t_pos;
! 209: msg("A shrill blast terrifies you.");
! 210: monster->t_artifact = monster->t_artifact * 3 / 4;
! 211: }
! 212: else {
! 213: msg("A shrill blast sends chills up your spine.");
! 214: monster->t_artifact /= 3;
! 215: }
! 216: }
! 217:
! 218: otherwise:
! 219: /* Unknown RELIC! */
! 220: debug("Unknown wielded relic %d", obj->o_which);
! 221: }
! 222: else debug("Declared relic is %d", obj->o_type);
! 223:
! 224: turn_off(*monster, CANSURPRISE);
! 225: /* Reset the monsters actions */
! 226: monster->t_action = A_NIL;
! 227: monster->t_using = NULL;
! 228: }
! 229:
! 230: /*
! 231: * add something to the contents of something else
! 232: * bag: the holder of the items
! 233: * item: the item to put inside
! 234: */
! 235: void
! 236: put_contents(struct object *bag, struct linked_list *item)
! 237: {
! 238: register struct linked_list *titem;
! 239: register struct object *tobj;
! 240:
! 241: bag->o_ac++;
! 242: tobj = OBJPTR(item);
! 243: for (titem = bag->contents; titem != NULL; titem = next(titem)) {
! 244: if ((OBJPTR(titem))->o_which == tobj->o_which)
! 245: break;
! 246: }
! 247: if (titem == NULL) { /* if not a duplicate put at beginning */
! 248: attach(bag->contents, item);
! 249: }
! 250: else {
! 251: item->l_prev = titem;
! 252: item->l_next = titem->l_next;
! 253: if (next(titem) != NULL)
! 254: (titem->l_next)->l_prev = item;
! 255: titem->l_next = item;
! 256: }
! 257: }
! 258:
! 259: /*
! 260: * remove something from something else
! 261: * bag: the holder of the items
! 262: */
! 263: void
! 264: take_contents(struct object *bag, struct linked_list *item)
! 265: {
! 266:
! 267: if (bag->o_ac <= 0) {
! 268: msg("Nothing to take out");
! 269: return;
! 270: }
! 271: bag->o_ac--;
! 272: detach(bag->contents, item);
! 273: if (!add_pack(item, FALSE, NULL))
! 274: put_contents(bag, item);
! 275: }
! 276:
! 277:
! 278: void
! 279: do_bag(struct linked_list *item)
! 280: {
! 281:
! 282: register struct linked_list *titem = NULL;
! 283: register struct object *obj, *tobj;
! 284: bool doit = TRUE;
! 285:
! 286: obj = OBJPTR(item);
! 287: while (doit) {
! 288: msg("What do you want to do? (* for a list): ");
! 289: mpos = 0;
! 290: switch (readchar()) {
! 291: case EOF:
! 292: case ESCAPE:
! 293: msg ("");
! 294: doit = FALSE;
! 295: when '1':
! 296: inventory(obj->contents, ALL);
! 297:
! 298: when '2':
! 299: if (obj->o_ac >= MAXCONTENTS) {
! 300: msg("the %s is full", m_magic[obj->o_which].mi_name);
! 301: break;
! 302: }
! 303: switch (obj->o_which) {
! 304: case MM_BEAKER:
! 305: titem = get_item(pack, "put in", POTION, FALSE, FALSE);
! 306: when MM_BOOK:
! 307: titem = get_item(pack, "put in", SCROLL, FALSE, FALSE);
! 308: }
! 309: if (titem == NULL)
! 310: break;
! 311: detach(pack, titem);
! 312: inpack--;
! 313: put_contents(obj, titem);
! 314:
! 315: when '3':
! 316: titem = get_item(obj->contents,"take out",ALL,FALSE,FALSE);
! 317: if (titem == NULL)
! 318: break;
! 319: take_contents(obj, titem);
! 320:
! 321: when '4':
! 322: switch (obj->o_which) {
! 323: case MM_BEAKER:
! 324: titem = get_item(obj->contents,"quaff",ALL,FALSE,FALSE);
! 325: if (titem == NULL)
! 326: break;
! 327: tobj = OBJPTR(titem);
! 328: obj->o_ac--;
! 329: detach(obj->contents, titem);
! 330: quaff(tobj->o_which,
! 331: tobj->o_kind,
! 332: tobj->o_flags,
! 333: TRUE);
! 334: if (p_know[tobj->o_which] && p_guess[tobj->o_which])
! 335: {
! 336: free(p_guess[tobj->o_which]);
! 337: p_guess[tobj->o_which] = NULL;
! 338: }
! 339: else if (!p_know[tobj->o_which] &&
! 340: askme &&
! 341: (tobj->o_flags & ISKNOW) == 0 &&
! 342: (tobj->o_flags & ISPOST) == 0 &&
! 343: p_guess[tobj->o_which] == NULL) {
! 344: nameitem(titem, FALSE);
! 345: }
! 346: o_discard(titem);
! 347: when MM_BOOK:
! 348: if (on(player, ISBLIND)) {
! 349: msg("You can't see to read anything");
! 350: break;
! 351: }
! 352: titem = get_item(obj->contents,"read",ALL,FALSE,FALSE);
! 353: if (titem == NULL)
! 354: break;
! 355: tobj = OBJPTR(titem);
! 356: obj->o_ac--;
! 357: detach(obj->contents, titem);
! 358: read_scroll(tobj->o_which,
! 359: tobj->o_flags & (ISCURSED|ISBLESSED),
! 360: TRUE);
! 361: if (s_know[tobj->o_which] && s_guess[tobj->o_which])
! 362: {
! 363: free(s_guess[tobj->o_which]);
! 364: s_guess[tobj->o_which] = NULL;
! 365: }
! 366: else if (!s_know[tobj->o_which] &&
! 367: askme &&
! 368: (tobj->o_flags & ISKNOW) == 0 &&
! 369: (tobj->o_flags & ISPOST) == 0 &&
! 370: s_guess[tobj->o_which] == NULL) {
! 371: nameitem(titem, FALSE);
! 372: }
! 373: o_discard(titem);
! 374: }
! 375: doit = FALSE;
! 376:
! 377: otherwise:
! 378: wclear(hw);
! 379: touchwin(hw);
! 380: mvwaddstr(hw,0,0,"The following operations are available:");
! 381: mvwaddstr(hw,2,0,"[1]\tInventory\n");
! 382: wprintw(hw,"[2]\tPut something in the %s\n",
! 383: m_magic[obj->o_which].mi_name);
! 384: wprintw(hw,"[3]\tTake something out of the %s\n",
! 385: m_magic[obj->o_which].mi_name);
! 386: switch(obj->o_which) {
! 387: case MM_BEAKER: waddstr(hw,"[4]\tQuaff a potion\n");
! 388: when MM_BOOK: waddstr(hw,"[4]\tRead a scroll\n");
! 389: }
! 390: waddstr(hw,"[ESC]\tLeave this menu\n");
! 391: mvwaddstr(hw, lines-1, 0, spacemsg);
! 392: draw(hw);
! 393: wait_for (' ');
! 394: clearok(cw, TRUE);
! 395: touchwin(cw);
! 396: }
! 397: }
! 398: }
! 399:
! 400: /* who: Kind of monster to panic (all if who is NULL) */
! 401: void
! 402: do_panic(int who)
! 403: {
! 404: register int x,y;
! 405: register struct linked_list *mon, *item;
! 406: register struct thing *th;
! 407:
! 408: for (x = hero.x-2; x <= hero.x+2; x++) {
! 409: for (y = hero.y-2; y <= hero.y+2; y++) {
! 410: if (y < 1 || x < 0 || y > lines - 3 || x > cols - 1)
! 411: continue;
! 412: if (isalpha(mvwinch(mw, y, x))) {
! 413: if ((mon = find_mons(y, x)) != NULL) {
! 414: th = THINGPTR(mon);
! 415:
! 416: /* Is this the right kind of monster to panic? */
! 417: if (who && th->t_index != who) continue;
! 418:
! 419: if (who ||
! 420: (!on(*th, ISUNDEAD) && !save(VS_MAGIC, th, 0) && off(*th, WASTURNED))) {
! 421: msg("%s %s.", prname(monster_name(th), TRUE),
! 422: terse ? "panics" : "turns to run in panic");
! 423:
! 424: turn_on(*th, ISFLEE);
! 425: turn_on(*th, WASTURNED);
! 426: turn_off(*th, CANSURPRISE);
! 427:
! 428: /* Disrupt what it was doing */
! 429: dsrpt_monster(th, TRUE, TRUE);
! 430:
! 431: /* If monster was suffocating, stop it */
! 432: if (on(*th, DIDSUFFOCATE)) {
! 433: turn_off(*th, DIDSUFFOCATE);
! 434: extinguish(suffocate);
! 435: }
! 436:
! 437: /* If monster held us, stop it */
! 438: if (on(*th, DIDHOLD) && (--hold_count == 0))
! 439: turn_off(player, ISHELD);
! 440: turn_off(*th, DIDHOLD);
! 441:
! 442: /*
! 443: * if he has something he might drop it
! 444: */
! 445: if ((item = th->t_pack) != NULL &&
! 446: (OBJPTR(item))->o_type != RELIC &&
! 447: rnd(100) < 50) {
! 448: detach(th->t_pack, item);
! 449: fall(item, FALSE);
! 450: }
! 451:
! 452: /* It is okay to turn tail */
! 453: th->t_oldpos = th->t_pos;
! 454: }
! 455: runto(th, &hero);
! 456: }
! 457: }
! 458: }
! 459: }
! 460: }
! 461:
! 462: /*
! 463: * print miscellaneous magic bonuses
! 464: */
! 465: char *
! 466: misc_name(struct object *obj)
! 467: {
! 468: static char buf[LINELEN];
! 469: char buf1[LINELEN];
! 470:
! 471: buf[0] = '\0';
! 472: buf1[0] = '\0';
! 473: if (!(obj->o_flags & ISKNOW))
! 474: return (m_magic[obj->o_which].mi_name);
! 475: switch (obj->o_which) {
! 476: case MM_BRACERS:
! 477: case MM_PROTECT:
! 478: strcat(buf, num(obj->o_ac, 0));
! 479: strcat(buf, " ");
! 480: }
! 481: switch (obj->o_which) {
! 482: case MM_G_OGRE:
! 483: case MM_G_DEXTERITY:
! 484: case MM_JEWEL:
! 485: case MM_STRANGLE:
! 486: case MM_R_POWERLESS:
! 487: case MM_DANCE:
! 488: if (obj->o_flags & ISCURSED)
! 489: strcat(buf, "cursed ");
! 490: }
! 491: strcat(buf, m_magic[obj->o_which].mi_name);
! 492: switch (obj->o_which) {
! 493: case MM_JUG:
! 494: if (obj->o_ac == JUG_EMPTY)
! 495: strcat(buf1, " [empty]");
! 496: else if (p_know[obj->o_ac])
! 497: sprintf(buf1, " [containing a potion of %s (%s)]",
! 498: p_magic[obj->o_ac].mi_name,
! 499: p_colors[obj->o_ac]);
! 500: else sprintf(buf1, " [containing a%s %s liquid]",
! 501: vowelstr(p_colors[obj->o_ac]),
! 502: p_colors[obj->o_ac]);
! 503: when MM_BEAKER:
! 504: case MM_BOOK: {
! 505: sprintf(buf1, " [containing %d]", obj->o_ac);
! 506: }
! 507: when MM_OPEN:
! 508: case MM_HUNGER:
! 509: sprintf(buf1, " [%d ring%s]", obj->o_charges,
! 510: obj->o_charges == 1 ? "" : "s");
! 511: when MM_DRUMS:
! 512: sprintf(buf1, " [%d beat%s]", obj->o_charges,
! 513: obj->o_charges == 1 ? "" : "s");
! 514: when MM_DISAPPEAR:
! 515: case MM_CHOKE:
! 516: sprintf(buf1, " [%d pinch%s]", obj->o_charges,
! 517: obj->o_charges == 1 ? "" : "es");
! 518: when MM_KEOGHTOM:
! 519: sprintf(buf1, " [%d application%s]", obj->o_charges,
! 520: obj->o_charges == 1 ? "" : "s");
! 521: when MM_SKILLS:
! 522: sprintf(buf1, " [%s]", char_class[obj->o_ac].name);
! 523: }
! 524: strcat (buf, buf1);
! 525: return buf;
! 526: }
! 527:
! 528: void
! 529: use_emori(void)
! 530: {
! 531: char selection; /* Cloak function */
! 532: int state = 0; /* Menu state */
! 533:
! 534: msg("What do you want to do? (* for a list): ");
! 535: do {
! 536: selection = tolower(readchar());
! 537: switch (selection) {
! 538: case '*':
! 539: if (state != 1) {
! 540: wclear(hw);
! 541: touchwin(hw);
! 542: mvwaddstr(hw, 2, 0, "[1] Fly\n[2] Stop flying\n");
! 543: waddstr(hw, "[3] Turn invisible\n[4] Turn Visible\n");
! 544: mvwaddstr(hw, 0, 0, "What do you want to do? ");
! 545: draw(hw);
! 546: state = 1; /* Now in prompt window */
! 547: }
! 548: break;
! 549:
! 550: case ESCAPE:
! 551: if (state == 1) {
! 552: clearok(cw, TRUE); /* Set up for redraw */
! 553: touchwin(cw);
! 554: }
! 555: msg("");
! 556:
! 557: after = FALSE;
! 558: return;
! 559:
! 560: when '1':
! 561: case '2':
! 562: case '3':
! 563: case '4':
! 564: if (state == 1) { /* In prompt window */
! 565: clearok(cw, TRUE); /* Set up for redraw */
! 566: touchwin(cw);
! 567: }
! 568:
! 569: msg("");
! 570:
! 571: state = 2; /* Finished */
! 572: break;
! 573:
! 574: default:
! 575: if (state == 1) { /* In the prompt window */
! 576: mvwaddstr(hw, 0, 0,
! 577: "Please enter a selection between 1 and 4: ");
! 578: draw(hw);
! 579: }
! 580: else { /* Normal window */
! 581: mpos = 0;
! 582: msg("Please enter a selection between 1 and 4: ");
! 583: }
! 584: }
! 585: } while (state != 2);
! 586:
! 587: /* We now must have a selection between 1 and 4 */
! 588: switch (selection) {
! 589: case '1': /* Fly */
! 590: if (on(player, ISFLY)) {
! 591: extinguish(land); /* Extinguish in case of potion */
! 592: msg("%slready flying.", terse ? "A" : "You are a");
! 593: }
! 594: else {
! 595: msg("You feel lighter than air!");
! 596: turn_on(player, ISFLY);
! 597: }
! 598: when '2': /* Stop flying */
! 599: if (off(player, ISFLY))
! 600: msg("%sot flying.", terse ? "N" : "You are n");
! 601: else {
! 602: if (find_slot(land))
! 603: msg("%sot flying by the cloak.",
! 604: terse ? "N" : "You are n");
! 605: else land();
! 606: }
! 607: when '3': /* Turn invisible */
! 608: if (off(player, ISINVIS)) {
! 609: turn_on(player, ISINVIS);
! 610: msg("You have a tingling feeling all over your body");
! 611: PLAYER = IPLAYER;
! 612: light(&hero);
! 613: }
! 614: else {
! 615: extinguish(appear); /* Extinguish in case of potion */
! 616: extinguish(dust_appear);/* dust of disappearance */
! 617: msg("%slready invisible.", terse ? "A" : "You are a");
! 618: }
! 619: when '4': /* Turn visible */
! 620: if (off(player, ISINVIS))
! 621: msg("%sot invisible.", terse ? "N" : "You are n");
! 622: else {
! 623: if (find_slot(appear) || find_slot(dust_appear))
! 624: msg("%sot invisible by the cloak.",
! 625: terse ? "N" : "You are n");
! 626: else appear();
! 627: }
! 628: }
! 629: }
! 630:
! 631: #ifdef PC7300
! 632: static menu_t Display; /* The menu structure */
! 633: static mitem_t Dispitems[MAXQUILL+1]; /* Info for each line */
! 634: static char Displines[MAXQUILL+1][LINELEN+1]; /* The lines themselves */
! 635: #endif
! 636: /*
! 637: * try to write a scroll with the quill of Nagrom
! 638: */
! 639: void
! 640: use_quill(struct object *obj)
! 641: {
! 642: struct linked_list *item;
! 643: register int i,
! 644: scroll_ability;
! 645: int which_scroll,
! 646: curlen,
! 647: maxlen,
! 648: dummy;
! 649: bool nohw = FALSE;
! 650:
! 651: i = which_scroll = 0;
! 652: scroll_ability = obj->o_charges;
! 653:
! 654: /* Prompt for scrolls */
! 655: msg("Which scroll are you writing? (* for list): ");
! 656:
! 657: which_scroll = (int) (readchar() - 'a');
! 658: if (which_scroll == (int) ESCAPE - (int) 'a') {
! 659: mpos = 0;
! 660: msg("");
! 661: after = FALSE;
! 662: return;
! 663: }
! 664: if (which_scroll >= 0 && which_scroll < MAXQUILL) nohw = TRUE;
! 665:
! 666: else if (slow_invent) {
! 667: register char c;
! 668:
! 669: nohw = TRUE;
! 670: do {
! 671: for (i=0; i<MAXQUILL; i++) {
! 672: msg("");
! 673: mvwaddch(msgw, 0, 0, '[');
! 674: waddch(msgw, (char) ((int) 'a' + i));
! 675: waddstr(msgw, "] A scroll of ");
! 676: waddstr(msgw, s_magic[quill_scrolls[i].s_which].mi_name);
! 677: waddstr(msgw, morestr);
! 678: clearok(msgw, FALSE);
! 679: draw(msgw);
! 680: do {
! 681: c = readchar();
! 682: } while (c != ' ' && c != ESCAPE);
! 683: if (c == ESCAPE)
! 684: break;
! 685: }
! 686: msg("");
! 687: mvwaddstr(msgw, 0, 0, "Which scroll are you writing? ");
! 688: clearok(msgw, FALSE);
! 689: draw(msgw);
! 690:
! 691: which_scroll = (int) (readchar() - 'a');
! 692: } while (which_scroll != (int) (ESCAPE - 'a') &&
! 693: (which_scroll < 0 || which_scroll >= MAXQUILL));
! 694:
! 695: if (which_scroll == (int) (ESCAPE - 'a')) {
! 696: mpos = 0;
! 697: msg("");
! 698: after = FALSE;
! 699: return;
! 700: }
! 701: }
! 702: else {
! 703: /* Now display the possible scrolls */
! 704: wclear(hw);
! 705: touchwin(hw);
! 706: mvwaddstr(hw, 2, 0, " Cost Scroll");
! 707: mvwaddstr(hw, 3, 0,
! 708: "-----------------------------------------------");
! 709: maxlen = 47; /* Maximum width of header */
! 710:
! 711: for (i=0; i<MAXQUILL; i++) {
! 712: wmove(hw, i+4, 0);
! 713: sprintf(prbuf, "[%c] %3d A scroll of %s",
! 714: (char) ((int) 'a' + i),
! 715: quill_scrolls[i].s_cost,
! 716: s_magic[quill_scrolls[i].s_which].mi_name);
! 717: #ifdef PC7300
! 718: /* Put it into the PC menu display */
! 719: strcpy(Displines[i], prbuf);
! 720: Dispitems[i].mi_name = Displines[i];
! 721: Dispitems[i].mi_flags = 0;
! 722: Dispitems[i].mi_val = i;
! 723: #endif
! 724: waddstr(hw, prbuf);
! 725:
! 726: /* Get the length of the line */
! 727: getyx(hw, dummy, curlen);
! 728: if (maxlen < curlen) maxlen = curlen;
! 729: }
! 730:
! 731: sprintf(prbuf, "[Current scroll power = %d]", scroll_ability);
! 732: mvwaddstr(hw, 0, 0, prbuf);
! 733: waddstr(hw, " Which scroll are you writing? ");
! 734: getyx(hw, dummy, curlen);
! 735: if (maxlen < curlen) maxlen = curlen;
! 736:
! 737: #ifdef PC7300
! 738: /* Place an end marker for the items */
! 739: Dispitems[MAXQUILL].mi_name = 0;
! 740:
! 741: /* Design prompts */
! 742: sprintf(prbuf, "Current scroll power is %d", scroll_ability);
! 743:
! 744: /* Set up the main menu structure */
! 745: Display.m_label = prbuf;
! 746: Display.m_title = " Cost Scroll";
! 747: Display.m_prompt = "Select a scroll or press Cancl to continue.";
! 748: Display.m_curptr = '\0';
! 749: Display.m_markptr = '\0';
! 750: Display.m_flags = M_ASISTITLE;
! 751: Display.m_selcnt = 1;
! 752: Display.m_items = Dispitems;
! 753: Display.m_curi = 0;
! 754:
! 755: /*
! 756: * Try to display the menu. If we don't have a local terminal,
! 757: * the call will fail and we will just continue with the
! 758: * normal mode.
! 759: */
! 760: if (menu(&Display) >= 0) {
! 761: if (Display.m_selcnt == 0) {
! 762: /* Menu was cancelled */
! 763: after = FALSE;
! 764: return FALSE; /* all done if abort */
! 765: }
! 766: else which_scroll = (int) Display.m_curi->mi_val;
! 767: goto got_scroll;
! 768: }
! 769: #endif
! 770: /* Should we overlay? */
! 771: if (menu_overlay && MAXQUILL + 3 < lines / 2) {
! 772: over_win(cw, hw, MAXQUILL + 5, maxlen + 3, 0, curlen, '\0');
! 773: }
! 774: else draw(hw);
! 775: }
! 776:
! 777: if (!nohw) {
! 778: which_scroll = (int) (readchar() - 'a');
! 779: while (which_scroll < 0 || which_scroll >= MAXQUILL) {
! 780: if (which_scroll == (int) ESCAPE - (int) 'a') {
! 781: after = FALSE;
! 782:
! 783: /* Restore the screen */
! 784: touchwin(cw);
! 785: if (MAXQUILL + 3 < lines / 2) clearok(cw, FALSE);
! 786: else {
! 787: msg("");
! 788: clearok(cw, TRUE);
! 789: }
! 790: return;
! 791: }
! 792: wmove(hw, 0, 0);
! 793: wclrtoeol(hw);
! 794: waddstr(hw, "Please enter one of the listed scrolls. ");
! 795: getyx(hw, dummy, curlen);
! 796: if (maxlen < curlen) maxlen = curlen;
! 797:
! 798: /* Should we overlay? */
! 799: if (menu_overlay && MAXQUILL + 3 < lines / 2) {
! 800: over_win(cw, hw, MAXQUILL + 5, maxlen + 3,
! 801: 0, curlen, '\0');
! 802: }
! 803: else draw(hw);
! 804:
! 805: which_scroll = (int) (readchar() - 'a');
! 806: }
! 807: }
! 808:
! 809: /* Now restore the screen if we have to */
! 810: if (!nohw) {
! 811: touchwin(cw);
! 812: if (MAXQUILL + 3 < lines / 2) clearok(cw, FALSE);
! 813: else {
! 814: msg("");
! 815: clearok(cw, TRUE);
! 816: }
! 817: }
! 818: else msg("");
! 819:
! 820:
! 821: #ifdef PC7300
! 822: got_scroll:
! 823: #endif
! 824: /* We've waited our required time. */
! 825: player.t_using = NULL;
! 826: player.t_action = A_NIL;
! 827:
! 828: if (quill_scrolls[which_scroll].s_cost > scroll_ability) {
! 829: msg("Your attempt fails.");
! 830: return;
! 831: }
! 832:
! 833: obj->o_charges -= quill_scrolls[which_scroll].s_cost;
! 834: item = spec_item(SCROLL, quill_scrolls[which_scroll].s_which, 0, 0);
! 835: if (add_pack(item, FALSE, NULL) == FALSE) {
! 836: (OBJPTR(item))->o_pos = hero;
! 837: fall(item, TRUE);
! 838: }
! 839: }
! 840:
! 841: void
! 842: use_mm(int which)
! 843: {
! 844: register struct object *obj = NULL;
! 845: register struct linked_list *item = NULL;
! 846: bool cursed, blessed, is_mm;
! 847:
! 848: cursed = FALSE;
! 849: is_mm = FALSE;
! 850:
! 851: if (which < 0) { /* A real miscellaneous magic item */
! 852: /* This is miscellaneous magic. It takes 3 movement periods to use */
! 853: if (player.t_action != C_USE) {
! 854: int units; /* Number of movement units for the item */
! 855:
! 856: item = get_item(pack, "use", USEABLE, FALSE, FALSE);
! 857:
! 858: /*
! 859: * Make certain that it is a micellaneous magic item
! 860: */
! 861: if (item == NULL)
! 862: return;
! 863:
! 864: units = usage_time(item);
! 865: if (units < 0) return;
! 866:
! 867: player.t_using = item; /* Remember what it is */
! 868: player.t_action = C_USE; /* We are quaffing */
! 869: player.t_no_move = units * movement(&player);
! 870: return;
! 871: }
! 872:
! 873: /* We have waited our time, let's use the item */
! 874: item = player.t_using;
! 875: player.t_using = NULL;
! 876: player.t_action = A_NIL;
! 877:
! 878: is_mm = TRUE;
! 879:
! 880: obj = OBJPTR(item);
! 881: cursed = (obj->o_flags & ISCURSED) != 0;
! 882: blessed = (obj->o_flags & ISBLESSED) != 0;
! 883: which = obj->o_which;
! 884: }
! 885:
! 886: if (obj->o_type == POTION) { /* An potion */
! 887: is_mm = FALSE;
! 888: inpack--;
! 889: detach (pack, item);
! 890: switch (obj->o_which) {
! 891: case P_POISON:
! 892: if (cur_weapon) {
! 893: if (cur_weapon->o_type == RELIC) {
! 894: msg("The poison burns off %s",
! 895: inv_name(cur_weapon,FALSE));
! 896: }
! 897: else {
! 898: cur_weapon->o_flags |= ISPOISON;
! 899: msg("Your weapon has %s gooey stuff on it",
! 900: p_colors[cur_weapon->o_which]);
! 901: }
! 902: }
! 903: else
! 904: msg("The poison pours on the floor and disappears!");
! 905: }
! 906: o_discard(item);
! 907: }
! 908: else if (obj->o_type == RELIC) { /* An artifact */
! 909: is_mm = FALSE;
! 910: switch (obj->o_which) {
! 911: case EMORI_CLOAK:
! 912: use_emori();
! 913: when QUILL_NAGROM:
! 914: use_quill(obj);
! 915: when BRIAN_MANDOLIN:
! 916: /* Put monsters around us to sleep */
! 917: read_scroll(S_HOLD, 0, FALSE);
! 918: when GERYON_HORN:
! 919: /* Chase close monsters away */
! 920: msg("The horn blasts a shrill tone.");
! 921: do_panic(0);
! 922: when HEIL_ANKH:
! 923: case YENDOR_AMULET:
! 924: case STONEBONES_AMULET:
! 925: /* Nothing happens by this mode */
! 926: msg("Nothing happens.");
! 927: when EYE_VECNA:
! 928: msg("The pain subsides...");
! 929: when SURTUR_RING:
! 930: /* Panic fire giants */
! 931: do_panic(findmindex("fire giant"));
! 932: }
! 933: }
! 934: else switch (which) { /* Miscellaneous Magic */
! 935: /*
! 936: * the jug of alchemy manufactures potions when you drink
! 937: * the potion it will make another after a while
! 938: */
! 939: case MM_JUG:
! 940: if (obj->o_ac == JUG_EMPTY) {
! 941: msg("The jug is empty");
! 942: break;
! 943: }
! 944: quaff (obj->o_ac, 0, 0, FALSE);
! 945: obj->o_ac = JUG_EMPTY;
! 946: fuse (alchemy, obj, ALCHEMYTIME, AFTER);
! 947: if (!(obj->o_flags & ISKNOW))
! 948: whatis(item);
! 949:
! 950: /*
! 951: * the beaker of plentiful potions is used to hold potions
! 952: * the book of infinite spells is used to hold scrolls
! 953: */
! 954: when MM_BEAKER:
! 955: case MM_BOOK:
! 956: do_bag(item);
! 957:
! 958: /*
! 959: * the chime of opening opens up secret doors
! 960: */
! 961: when MM_OPEN:
! 962: {
! 963: register struct linked_list *exit;
! 964: register struct room *rp;
! 965: register coord *cp;
! 966:
! 967: if (obj->o_charges <= 0) {
! 968: msg("The chime is cracked!");
! 969: break;
! 970: }
! 971: obj->o_charges--;
! 972: msg("chime... chime... hime... ime... me... e...");
! 973: if ((rp = roomin(&hero)) == NULL) {
! 974: search(FALSE, TRUE); /* Non-failing search for door */
! 975: break;
! 976: }
! 977: for (exit = rp->r_exit; exit != NULL; exit = next(exit)) {
! 978: cp = DOORPTR(exit);
! 979: if (winat(cp->y, cp->x) == SECRETDOOR) {
! 980: mvaddch (cp->y, cp->x, DOOR);
! 981: if (cansee (cp->y, cp->x))
! 982: mvwaddch(cw, cp->y, cp->x, DOOR);
! 983: }
! 984: }
! 985: }
! 986:
! 987: /*
! 988: * the chime of hunger just makes the hero hungry
! 989: */
! 990: when MM_HUNGER:
! 991: if (obj->o_charges <= 0) {
! 992: msg("The chime is cracked!");
! 993: break;
! 994: }
! 995: obj->o_charges--;
! 996: if (food_left >= MORETIME + 5) {
! 997: food_left = MORETIME + 5;
! 998: msg(terse? "Getting hungry" : "You are starting to get hungry");
! 999: hungry_state = F_HUNGRY;
! 1000: }
! 1001: aggravate(TRUE, TRUE);
! 1002:
! 1003: /*
! 1004: * the drums of panic make all creatures within two squares run
! 1005: * from the hero in panic unless they save or they are mindless
! 1006: * undead
! 1007: */
! 1008: when MM_DRUMS:
! 1009: if (obj->o_charges <= 0) {
! 1010: msg("The drum is broken!");
! 1011: break;
! 1012: }
! 1013: obj->o_charges--;
! 1014: do_panic(0);
! 1015: /*
! 1016: * dust of disappearance makes the player invisible for a while
! 1017: */
! 1018: when MM_DISAPPEAR:
! 1019: m_know[MM_DISAPPEAR] = TRUE;
! 1020: if (obj->o_charges <= 0) {
! 1021: msg("No more dust!");
! 1022: break;
! 1023: }
! 1024: obj->o_charges--;
! 1025: msg("aaAAACHOOOooo. Cough. Cough. Sneeze. Sneeze.");
! 1026: if (!find_slot(dust_appear)) {
! 1027: turn_on(player, ISINVIS);
! 1028: fuse(dust_appear, NULL, DUSTTIME, AFTER);
! 1029: PLAYER = IPLAYER;
! 1030: light(&hero);
! 1031: }
! 1032: else lengthen(dust_appear, DUSTTIME);
! 1033:
! 1034: /*
! 1035: * dust of choking and sneezing can kill the hero if he misses
! 1036: * the save
! 1037: */
! 1038: when MM_CHOKE:
! 1039: m_know[MM_CHOKE] = TRUE;
! 1040: if (obj->o_charges <= 0) {
! 1041: msg("No more dust!");
! 1042: break;
! 1043: }
! 1044: obj->o_charges--;
! 1045: msg("aaAAACHOOOooo. Cough. Cough. Sneeze. Sneeze.");
! 1046: if (!cur_relic[SURTUR_RING] && !save(VS_POISON, &player, 0)) {
! 1047: msg ("You choke to death!!! --More--");
! 1048: pstats.s_hpt = -1; /* in case he hangs up the phone */
! 1049: wait_for(' ');
! 1050: death(D_CHOKE);
! 1051: }
! 1052: else {
! 1053: msg("You begin to cough and choke uncontrollably");
! 1054: if (find_slot(unchoke))
! 1055: lengthen(unchoke, DUSTTIME);
! 1056: else
! 1057: fuse(unchoke, NULL, DUSTTIME, AFTER);
! 1058: turn_on(player, ISHUH);
! 1059: turn_on(player, ISBLIND);
! 1060: light(&hero);
! 1061: }
! 1062:
! 1063: when MM_KEOGHTOM:
! 1064: /*
! 1065: * this is a very powerful healing ointment
! 1066: * but it takes a while to put on...
! 1067: */
! 1068: obj->o_charges--;
! 1069: if (on(player, HASDISEASE)) {
! 1070: extinguish(cure_disease);
! 1071: cure_disease();
! 1072: msg(terse ? "You feel yourself improving."
! 1073: : "You begin to feel yourself improving again.");
! 1074: }
! 1075: if (on(player, HASINFEST)) {
! 1076: turn_off(player, HASINFEST);
! 1077: infest_dam = 0;
! 1078: msg(terse ? "You feel yourself improving."
! 1079: : "You begin to feel yourself improving again.");
! 1080: }
! 1081: if (on(player, DOROT)) {
! 1082: msg("You feel your skin returning to normal.");
! 1083: turn_off(player, DOROT);
! 1084: }
! 1085: pstats.s_hpt += roll(pstats.s_lvl, 6);
! 1086: if (pstats.s_hpt > max_stats.s_hpt)
! 1087: pstats.s_hpt = max_stats.s_hpt;
! 1088: sight();
! 1089: msg("You begin to feel much better.");
! 1090:
! 1091: /*
! 1092: * The book has a character class associated with it.
! 1093: * if your class matches that of the book, it will raise your
! 1094: * level by one. If your class does not match the one of the book,
! 1095: * it change your class to that of book.
! 1096: * Note that it takes a while to read.
! 1097: */
! 1098: when MM_SKILLS:
! 1099: detach (pack, item);
! 1100: inpack--;
! 1101: changeclass(obj->o_ac);
! 1102:
! 1103: otherwise:
! 1104: msg("What a strange magic item you have!");
! 1105: }
! 1106: status(FALSE);
! 1107: if (is_mm && m_know[which] && m_guess[which]) {
! 1108: free(m_guess[which]);
! 1109: m_guess[which] = NULL;
! 1110: }
! 1111: else if (is_mm &&
! 1112: !m_know[which] &&
! 1113: askme &&
! 1114: (obj->o_flags & ISKNOW) == 0 &&
! 1115: m_guess[which] == NULL) {
! 1116: nameitem(item, FALSE);
! 1117: }
! 1118: if (item != NULL && which == MM_SKILLS)
! 1119: o_discard(item);
! 1120: updpack(TRUE, &player);
! 1121: }
! 1122:
! 1123: /*
! 1124: * usage_time:
! 1125: * Return how long it takes to use an item. For now we only give time
! 1126: * for MM, RELIC, SCROLL, and POTION items.
! 1127: */
! 1128:
! 1129: int
! 1130: usage_time(struct linked_list *item)
! 1131: {
! 1132: register struct object *obj;
! 1133: register int units = -1;
! 1134:
! 1135: obj = OBJPTR(item);
! 1136: switch (obj->o_type) {
! 1137: case SCROLL: units = 4;
! 1138: when POTION: units = 3;
! 1139: when RELIC: /* An artifact */
! 1140: switch (obj->o_which) {
! 1141: case QUILL_NAGROM: units = 2;
! 1142: when EMORI_CLOAK: units = 2;
! 1143: when BRIAN_MANDOLIN:units = 4;
! 1144: when GERYON_HORN: units = 3;
! 1145: when HEIL_ANKH:
! 1146: case YENDOR_AMULET:
! 1147: case STONEBONES_AMULET:
! 1148: units = 2;
! 1149: when EYE_VECNA:
! 1150: /* Do some effects right away! */
! 1151: units = 6;
! 1152:
! 1153: /* The eye will do nothing other than give a headache */
! 1154: pstats.s_hpt -= 35;
! 1155: msg("You feel a sudden shooting pain in your eye!");
! 1156: if (pstats.s_hpt < 0) {
! 1157: msg ("The pain is too much for you! -- More --");
! 1158: wait_for(' ');
! 1159: death(D_RELIC);
! 1160: }
! 1161: when SURTUR_RING:
! 1162: units = 3;
! 1163: msg("Your nose tickles a bit.");
! 1164: }
! 1165: when MM:
! 1166: switch (obj->o_which) { /* Miscellaneous Magic */
! 1167: case MM_JUG:
! 1168: if (obj->o_ac == JUG_EMPTY) {
! 1169: msg("The jug is empty");
! 1170: return (-1);
! 1171: }
! 1172: units = 3;
! 1173: when MM_BEAKER:
! 1174: case MM_BOOK:
! 1175: /* This is a strange case because it can go forever */
! 1176: units = 1;
! 1177: when MM_OPEN:
! 1178: case MM_HUNGER:
! 1179: /* Chimes */
! 1180: units = 3;
! 1181: when MM_DRUMS:
! 1182: units = 3;
! 1183: when MM_DISAPPEAR:
! 1184: case MM_CHOKE:
! 1185: /* Dust */
! 1186: units = 3;
! 1187: when MM_KEOGHTOM:
! 1188: /* Ointment */
! 1189: if (obj->o_charges <= 0) {
! 1190: msg("The jar is empty!");
! 1191: return (-1);
! 1192: }
! 1193: units = 5;
! 1194: when MM_SKILLS:
! 1195: /* A whole book! */
! 1196: units = 15;
! 1197: otherwise:
! 1198: /* What is it? */
! 1199: units = -1;
! 1200: }
! 1201: otherwise: units = -1;
! 1202: }
! 1203:
! 1204: return (units);
! 1205: }
CVSweb