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