comparison arogue7/misc.c @ 125:adfa37e67084

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