Annotation of early-roguelike/arogue7/misc.c, Revision 1.1.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