comparison xrogue/misc.c @ 133:e6179860cb76

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