Annotation of early-roguelike/urogue/misc.c, Revision 1.1.1.1
1.1 rubenllo 1: /*
2: misc.c - all sorts of miscellaneous routines
3:
4: UltraRogue: The Ultimate Adventure in the Dungeons of Doom
5: Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
6: All rights reserved.
7:
8: Based on "Advanced Rogue"
9: Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
10: All rights reserved.
11:
12: Based on "Rogue: Exploring the Dungeons of Doom"
13: Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
14: All rights reserved.
15:
16: See the file LICENSE.TXT for full copyright and licensing information.
17: */
18:
19: #include <stdlib.h>
20: #include <string.h>
21: #include <ctype.h>
22: #include "rogue.h"
23:
24: /*
25: tr_name()
26: print the name of a trap
27: */
28:
29: char *
30: tr_name(char ch, char *trname)
31: {
32: const char *s = NULL;
33:
34: if (trname == NULL)
35: return(" Your found an error in UltraRogue #100.");
36:
37: switch(ch)
38: {
39: case TRAPDOOR:
40: s = "trapdoor.";
41: break;
42: case BEARTRAP:
43: s = "beartrap.";
44: break;
45: case SLEEPTRAP:
46: s = "sleeping gas trap.";
47: break;
48: case ARROWTRAP:
49: s = "arrow trap.";
50: break;
51: case TELTRAP:
52: s = "teleport trap.";
53: break;
54: case DARTTRAP:
55: s = "dart trap.";
56: break;
57: case POOL:
58: s = "shimmering pool.";
59: break;
60: case MAZETRAP:
61: s = "maze entrance.";
62: break;
63: case FIRETRAP:
64: s = "fire trap.";
65: break;
66: case POISONTRAP:
67: s = "poison pool trap.";
68: break;
69: case LAIR:
70: s = "monster lair.";
71: break;
72: case RUSTTRAP:
73: s = "rust trap.";
74: break;
75: default:
76: ;
77: }
78:
79: sprintf(trname, "You found a %s.", s);
80:
81: return(trname);
82: }
83:
84: /*
85: look()
86: A quick glance all around the player
87: */
88:
89: void
90: look(int wakeup)
91: {
92: int x, y;
93: char ch, och;
94: int oldx, oldy;
95: int inpass, horizontal, vertical, do_light = FALSE, do_blank = FALSE;
96: int passcount = 0;
97: struct room *rp;
98: int ey, ex;
99:
100: /* Are we moving vertically or horizontally? */
101:
102: if (runch == 'h' || runch == 'l')
103: horizontal = TRUE;
104: else
105: horizontal = FALSE;
106:
107: if (runch == 'j' || runch == 'k')
108: vertical = TRUE;
109: else
110: vertical = FALSE;
111:
112: getyx(cw, oldy, oldx); /* Save current position */
113:
114: /*
115: * Blank out the floor around our last position and check for moving
116: * out of a corridor in a maze.
117: */
118:
119: if (oldrp != NULL && (oldrp->r_flags & ISDARK) &&
120: !(oldrp->r_flags & HASFIRE) && off(player, ISBLIND))
121: do_blank = TRUE;
122:
123: for (x = player.t_oldpos.x - 1; x <= player.t_oldpos.x + 1; x++)
124: for (y = player.t_oldpos.y - 1; y <= player.t_oldpos.y + 1;
125: y++)
126: {
127: ch = show(y, x);
128:
129: if (do_blank && (y != hero.y || x != hero.x) && ch == FLOOR)
130: mvwaddch(cw, y, x, ' ');
131:
132: /* Moving out of a corridor? */
133:
134: if (levtype == MAZELEV &&
135: (ch != '|' && ch != '-') && /* Not a wall */
136: ((vertical && x != player.t_oldpos.x &&
137: y == player.t_oldpos.y) ||
138: (horizontal && y != player.t_oldpos.y &&
139: x == player.t_oldpos.x)))
140: do_light = TRUE; /* Just came to a turn */
141: }
142:
143: inpass = ((rp = roomin(hero)) == NULL); /* Are we in a passage? */
144:
145: /* Are we coming out of a wall into a corridor in a maze? */
146: och = show(player.t_oldpos.y, player.t_oldpos.x);
147: ch = show(hero.y, hero.x);
148:
149: if (levtype == MAZELEV && (och == '|' || och == '-' ||
150: och == SECRETDOOR) && (ch != '|' && ch != '-' && ch != SECRETDOOR))
151: {
152: do_light = off(player, ISBLIND); /* Light it up if not blind */
153: }
154:
155: /* Look around the player */
156:
157: ey = hero.y + 1;
158: ex = hero.x + 1;
159:
160: for (x = hero.x - 1; x <= ex; x++)
161: if (x >= 0 && x < COLS)
162: for (y = hero.y - 1; y <= ey; y++)
163: {
164: if (y <= 0 || y >= LINES - 2)
165: continue;
166:
167: if (isalpha(mvwinch(mw, y, x)))
168: {
169: struct linked_list *it;
170: struct thing *tp;
171:
172: if (wakeup)
173: it = wake_monster(y, x);
174: else
175: it = find_mons(y, x);
176:
177: if (it == NULL)
178: continue;
179:
180: tp = THINGPTR(it);
181: tp->t_oldch = CCHAR( mvinch(y, x) );
182:
183: if (isatrap(tp->t_oldch))
184: {
185: struct trap *trp = trap_at(y, x);
186:
187: tp->t_oldch = (trp->tr_flags & ISFOUND) ? tp->t_oldch
188: : trp->tr_show;
189: }
190:
191: if (tp->t_oldch == FLOOR &&
192: (rp->r_flags & ISDARK)
193: && !(rp->r_flags & HASFIRE) &&
194: off(player, ISBLIND))
195: tp->t_oldch = ' ';
196: }
197:
198: /* Secret doors show as walls */
199:
200: if ((ch = show(y, x)) == SECRETDOOR)
201: ch = secretdoor(y, x);
202:
203: /*
204: * Don't show room walls if he is in a
205: * passage and check for maze turns
206: */
207:
208: if (off(player, ISBLIND))
209: {
210: if (y == hero.y && x == hero.x || (inpass && (ch == '-' ||
211: ch == '|')))
212: continue;
213:
214: /* Are we at a crossroads in a maze? */
215:
216: if (levtype == MAZELEV && (ch != '|' && ch != '-') &&
217: /* Not a wall */
218: ((vertical && x != hero.x && y == hero.y) ||
219: (horizontal && y != hero.y && x == hero.x)))
220: do_light = TRUE;
221: /* Just came to a turn */
222: }
223: else if (y != hero.y || x != hero.x)
224: continue;
225:
226: wmove(cw, y, x);
227: waddch(cw, ch);
228:
229: if (door_stop && !firstmove && running)
230: {
231: switch (runch)
232: {
233: case 'h':
234: if (x == ex)
235: continue;
236: break;
237: case 'j':
238: if (y == hero.y - 1)
239: continue;
240: break;
241: case 'k':
242: if (y == ey)
243: continue;
244: break;
245: case 'l':
246: if (x == hero.x - 1)
247: continue;
248: break;
249: case 'y':
250: if ((x + y) - (hero.x + hero.y) >= 1)
251: continue;
252: break;
253: case 'u':
254: if ((y - x) - (hero.y - hero.x) >= 1)
255: continue;
256: break;
257: case 'n':
258: if ((x + y) - (hero.x + hero.y) <= -1)
259: continue;
260: break;
261: case 'b':
262: if ((y - x) - (hero.y - hero.x) <= -1)
263: continue;
264: break;
265: }
266:
267: switch (ch)
268: {
269: case DOOR:
270: if (x == hero.x || y == hero.y)
271: running = FALSE;
272: break;
273: case PASSAGE:
274: if (x == hero.x || y == hero.y)
275: passcount++;
276: break;
277: case FLOOR:
278:
279: /*
280: * Stop by new passages in a
281: * maze (floor next to us)
282: */
283: if ((levtype == MAZELEV) &&
284: ((horizontal && x == hero.x && y != hero.y) ||
285: (vertical && y == hero.y && x != hero.x)))
286: running = FALSE;
287:
288: case '|':
289: case '-':
290: case ' ':
291: break;
292:
293: default:
294: running = FALSE;
295: break;
296: }
297: }
298: }
299:
300: if (door_stop && !firstmove && passcount > 1)
301: running = FALSE;
302:
303: /*
304: * Do we have to light up the area (just stepped into a new
305: * corridor)?
306: */
307:
308: if (do_light && wakeup && /* wakeup will be true on a normal move */
309: !(rp->r_flags & ISDARK) && /* We have some light */
310: !ce(hero, player.t_oldpos)) /* Don't do anything if we didn't move */
311: light(&hero);
312:
313: mvwaddch(cw, hero.y, hero.x, PLAYER);
314: wmove(cw, oldy, oldx);
315:
316: if (wakeup)
317: {
318: player.t_oldpos = hero; /* Don't change if we didn't move */
319: oldrp = rp;
320: }
321: }
322:
323: /*
324: secret_door()
325: Figure out what a secret door looks like.
326: */
327:
328: char
329: secretdoor(int y, int x)
330: {
331: struct room *rp;
332: coord cp;
333:
334: cp.x = x;
335: cp.y = y;
336:
337: if ((rp = roomin(cp)) != NULL)
338: {
339: if (y == rp->r_pos.y || y == rp->r_pos.y + rp->r_max.y - 1)
340: return ('-');
341: else
342: return ('|');
343: }
344: return ('p');
345: }
346:
347: /*
348: find_obj()
349: find the unclaimed object at y, x
350: */
351:
352: struct linked_list *
353: find_obj(int y, int x)
354: {
355: struct linked_list *obj, *sobj;
356: struct object *op;
357:
358: sobj = lvl_obj;
359:
360: for (obj = sobj; obj != NULL; obj = next(obj))
361: {
362: op = OBJPTR(obj);
363:
364: if (op && op->o_pos.y == y && op->o_pos.x == x)
365: return(obj);
366: }
367:
368: return(NULL);
369: }
370:
371: /*
372: eat()
373: He wants to eat something, so let him try
374: */
375:
376: void
377: eat(void)
378: {
379: struct object *obj;
380: int amount;
381: float scale = (float) (LINES * COLS) / (25.0F * 80.0F);
382:
383: if ((obj = get_object(pack, "eat", FOOD, NULL)) == NULL)
384: return;
385:
386: switch (obj->o_which)
387: {
388: case FD_RATION:
389: amount = (int)(scale * (HUNGERTIME + rnd(400) - 200));
390:
391: if (rnd(100) > 70)
392: {
393: msg("Yuk, this food tastes awful.");
394: pstats.s_exp++;
395: check_level();
396: }
397: else
398: msg("Yum, that tasted good.");
399: break;
400:
401: case FD_FRUIT:
402: amount = (int)(scale * (200 + rnd(HUNGERTIME)));
403: msg("My, that was a yummy %s.", fruit);
404: break;
405:
406: case FD_CRAM:
407: amount = (int)(scale * (rnd(HUNGERTIME / 2) + 600));
408: msg("The cram tastes dry in your mouth.");
409: break;
410:
411: case FD_CAKES:
412: amount = (int)(scale * ((HUNGERTIME / 3) + rnd(600)));
413: msg("Yum, the honey cakes tasted good.");
414: break;
415:
416: case FD_LEMBA:
417: amount = (int)(scale * ((HUNGERTIME / 2) + rnd(900)));
418: quaff(&player, P_HEALING, ISNORMAL);
419: break;
420:
421: case FD_MIRUVOR:
422: amount = (int)(scale * ((HUNGERTIME / 3) + rnd(500)));
423: quaff(&player, P_HEALING, ISNORMAL);
424: quaff(&player, P_RESTORE, ISNORMAL);
425: break;
426:
427: default:
428: msg("What a strange thing to eat!");
429: amount = (int)(scale * HUNGERTIME);
430: }
431:
432: food_left += amount;
433:
434: if (obj->o_flags & ISBLESSED)
435: {
436: food_left += 2 * amount;
437: msg("You have a tingling feeling in your mouth.");
438: }
439: else if (food_left > scale * STOMACHSIZE)
440: {
441: food_left = (int)(scale * STOMACHSIZE);
442: msg("You feel satiated and too full to move.");
443: no_command = HOLDTIME;
444: }
445:
446: hungry_state = F_OK;
447: updpack();
448:
449: if (obj == cur_weapon)
450: cur_weapon = NULL;
451:
452: if (--obj->o_count <= 0) /* Remove this pack entry if last of food */
453: discard_pack(obj);
454: }
455:
456: /*
457: * Used to modify the player's strength it keeps track of the highest it has
458: * been, just in case
459: */
460:
461: void
462: chg_str(int amt, int both, int lost)
463: {
464: int ring_str; /* ring strengths */
465: struct stats *ptr; /* for speed */
466:
467: ptr = &pstats;
468:
469: ring_str = ring_value(R_ADDSTR) + (on(player, POWERSTR) ? 10 : 0) +
470: (on(player, SUPERHERO) ? 10 : 0);
471:
472: ptr->s_str -= ring_str;
473: ptr->s_str += amt;
474:
475: if (ptr->s_str < 3)
476: {
477: ptr->s_str = 3;
478: lost = FALSE;
479: }
480: else if (ptr->s_str > 25)
481: ptr->s_str = 25;
482:
483: if (both)
484: max_stats.s_str = ptr->s_str;
485:
486: if (lost)
487: lost_str -= amt;
488:
489: ptr->s_str += ring_str;
490:
491: if (ptr->s_str < 0)
492: ptr->s_str = 0;
493:
494: updpack();
495: }
496:
497: /*
498: * Used to modify the player's dexterity it keeps track of the highest it has
499: * been, just in case
500: */
501:
502: void
503: chg_dext(int amt, int both, int lost)
504: {
505: int ring_dext; /* ring strengths */
506: struct stats *ptr; /* for speed */
507:
508: ptr = &pstats;
509:
510: ring_dext = ring_value(R_ADDHIT) + (on(player, POWERDEXT) ? 10 : 0) +
511: (on(player, SUPERHERO) ? 5 : 0);
512:
513: ptr->s_dext -= ring_dext;
514: ptr->s_dext += amt;
515:
516: if (ptr->s_dext < 3)
517: {
518: ptr->s_dext = 3;
519: lost = FALSE;
520: }
521: else if (ptr->s_dext > 25)
522: ptr->s_dext = 25;
523:
524: if (both)
525: max_stats.s_dext = ptr->s_dext;
526:
527: if (lost)
528: lost_dext -= amt;
529:
530: ptr->s_dext += ring_dext;
531:
532: if (ptr->s_dext < 0)
533: ptr->s_dext = 0;
534: }
535:
536: /*
537: add_haste()
538: add a haste to the player
539: */
540:
541: void
542: add_haste(int blessed)
543: {
544: short hasttime;
545:
546: if (blessed)
547: hasttime = 10;
548: else
549: hasttime = 6;
550:
551: if (on(player, ISSLOW)) /* Is person slow? */
552: {
553: extinguish_fuse(FUSE_NOSLOW);
554: noslow(NULL);
555:
556: if (blessed)
557: hasttime = 4;
558: else
559: return;
560: }
561:
562: if (on(player, ISHASTE))
563: {
564: msg("You faint from exhaustion.");
565: no_command += rnd(hasttime);
566: lengthen_fuse(FUSE_NOHASTE, rnd(hasttime) + (roll(1, 4) * hasttime));
567: }
568: else
569: {
570: turn_on(player, ISHASTE);
571: light_fuse(FUSE_NOHASTE, 0, roll(hasttime, hasttime), AFTER);
572: }
573: }
574:
575: /*
576: aggravate()
577: aggravate all the monsters on this level
578: */
579:
580: void
581: aggravate(void)
582: {
583: struct linked_list *mi;
584: struct thing *tp;
585:
586: for (mi = mlist; mi != NULL; mi = next(mi))
587: {
588: tp = THINGPTR(mi);
589: chase_it(&tp->t_pos, &player);
590: }
591: }
592:
593: /*
594: vowelstr()
595: for printfs: if string starts with a vowel, return "n" for an "an"
596: */
597:
598: char *
599: vowelstr(char *str)
600: {
601: switch (*str)
602: {
603: case 'a':
604: case 'A':
605: case 'e':
606: case 'E':
607: case 'i':
608: case 'I':
609: case 'o':
610: case 'O':
611: case 'u':
612: case 'U':
613: return "n";
614: default:
615: return "";
616: }
617: }
618:
619: /*
620: is_object()
621: see if the object is one of the currently used items
622: */
623:
624: int
625: is_current(struct object *obj)
626: {
627: if (obj == NULL)
628: return FALSE;
629:
630: if (obj == cur_armor || obj == cur_weapon ||
631: obj == cur_ring[LEFT_1] || obj == cur_ring[LEFT_2] ||
632: obj == cur_ring[LEFT_3] || obj == cur_ring[LEFT_4] ||
633: obj == cur_ring[LEFT_5] ||
634: obj == cur_ring[RIGHT_1] || obj == cur_ring[RIGHT_2] ||
635: obj == cur_ring[RIGHT_3] || obj == cur_ring[RIGHT_4] ||
636: obj == cur_ring[RIGHT_5]) {
637: msg("That's already in use.");
638: return TRUE;
639: }
640:
641: return FALSE;
642: }
643:
644: /*
645: get_dir()
646: set up the direction co_ordinate for use in varios "prefix" commands
647: */
648:
649: int
650: get_dir(void)
651: {
652: char *prompt;
653: int gotit;
654:
655: prompt = "Which direction? ";
656: msg(prompt);
657:
658: do
659: {
660: gotit = TRUE;
661:
662: switch (readchar())
663: {
664: case 'h':
665: case 'H':
666: delta.y = 0;
667: delta.x = -1;
668: break;
669:
670: case 'j':
671: case 'J':
672: delta.y = 1;
673: delta.x = 0;
674: break;
675:
676: case 'k':
677: case 'K':
678: delta.y = -1;
679: delta.x = 0;
680: break;
681:
682: case 'l':
683: case 'L':
684: delta.y = 0;
685: delta.x = 1;
686: break;
687:
688: case 'y':
689: case 'Y':
690: delta.y = -1;
691: delta.x = -1;
692: break;
693:
694: case 'u':
695: case 'U':
696: delta.y = -1;
697: delta.x = 1;
698: break;
699:
700: case 'b':
701: case 'B':
702: delta.y = 1;
703: delta.x = -1;
704: break;
705:
706: case 'n':
707: case 'N':
708: delta.y = 1;
709: delta.x = 1;
710: break;
711:
712: case ESCAPE:
713: return FALSE;
714:
715: default:
716: mpos = 0;
717: msg(prompt);
718: gotit = FALSE;
719: }
720: }
721: while(!gotit);
722:
723: if (on(player, ISHUH) && rnd(100) > 80)
724: do
725: {
726: delta.y = rnd(3) - 1;
727: delta.x = rnd(3) - 1;
728: }
729: while (delta.y == 0 && delta.x == 0);
730:
731: mpos = 0;
732:
733: return(TRUE);
734: }
735:
736: /*
737: is_wearing()
738: is the hero wearing a particular ring
739: */
740:
741: int
742: is_wearing(int type)
743: {
744: #define ISRING(h, r) (cur_ring[h] != NULL && cur_ring[h]->o_which == r)
745:
746: return(
747: ISRING(LEFT_1, type) || ISRING(LEFT_2, type) ||
748: ISRING(LEFT_3, type) || ISRING(LEFT_4, type) ||
749: ISRING(LEFT_5, type) ||
750: ISRING(RIGHT_1, type) || ISRING(RIGHT_2, type) ||
751: ISRING(RIGHT_3, type) || ISRING(RIGHT_4, type) ||
752: ISRING(RIGHT_5, type) );
753: }
754:
755: /*
756: maze_view()
757: Returns true if the player can see the specified location
758: within the confines of a maze (within one column or row)
759: */
760:
761: int
762: maze_view(int y, int x)
763: {
764: int start, goal, delt, ycheck = 0, xcheck = 0, absy, absx;
765: int row;
766:
767: /* Get the absolute value of y and x differences */
768:
769: absy = hero.y - y;
770: absx = hero.x - x;
771:
772: if (absy < 0)
773: absy = -absy;
774:
775: if (absx < 0)
776: absx = -absx;
777:
778: /* Must be within one row or column */
779:
780: if (absy > 1 && absx > 1)
781: return(FALSE);
782:
783: if (absy <= 1) /* Go along row */
784: {
785: start = hero.x;
786: goal = x;
787: row = TRUE;
788: ycheck = hero.y;
789: }
790: else /* Go along column */
791: {
792: start = hero.y;
793: goal = y;
794: row = FALSE;
795: xcheck = hero.x;
796: }
797:
798: if (start <= goal)
799: delt = 1;
800: else
801: delt = -1;
802:
803: while (start != goal)
804: {
805: if (row)
806: xcheck = start;
807: else
808: ycheck = start;
809:
810: switch(CCHAR(winat(ycheck, xcheck)))
811: {
812: case '|':
813: case '-':
814: case WALL:
815: case DOOR:
816: case SECRETDOOR:
817: return(FALSE);
818:
819: default:
820: break;
821: }
822: start += delt;
823: }
824:
825: return(TRUE);
826: }
827:
828: /*
829: listen()
830: listen for monsters less than 5 units away
831: */
832:
833: void
834: listen(void)
835: {
836: struct linked_list *item;
837: struct thing *tp;
838: int thief_bonus = -50;
839: int mcount = 0;
840:
841: if (player.t_ctype == C_THIEF)
842: thief_bonus = 10;
843:
844: for (item = mlist; item != NULL; item = next(item))
845: {
846: tp = THINGPTR(item);
847:
848: if (DISTANCE(hero, tp->t_pos) < 81
849: && rnd(70) < (thief_bonus + 4 * pstats.s_dext +
850: 6 * pstats.s_lvl))
851: {
852: msg("You hear a%s %s nearby.",
853: vowelstr(monsters[tp->t_index].m_name),
854: monsters[tp->t_index].m_name);
855: mcount++;
856: }
857: }
858:
859: if (mcount == 0)
860: msg("You hear nothing.");
861: }
862:
863: /*
864: * nothing_message - print out "Nothing <adverb> happens."
865: */
866:
867: static const char *nothings[] =
868: {
869: "",
870: "unusual ",
871: "seems to ",
872: "at all ",
873: "really ",
874: "noticeable ",
875: "different ",
876: "strange ",
877: "wierd ",
878: "bizzare ",
879: "wonky ",
880: ""
881: };
882:
883: void
884: nothing_message(int flags)
885: {
886: int adverb = rnd(sizeof(nothings) / sizeof(char *));
887:
888: NOOP(flags);
889:
890: msg("Nothing %shappens.", nothings[adverb]);
891: }
892:
893: /*
894: feel_message()
895: print out "You feel <description>."
896: */
897:
898: void
899: feel_message(void)
900: {
901: char *charp;
902:
903: switch (rnd(25))
904: {
905: case 1: charp = "bad"; break;
906: case 2: charp = "hurt"; break;
907: case 3: charp = "sick"; break;
908: case 4: charp = "faint"; break;
909: case 5: charp = "yucky"; break;
910: case 6: charp = "wonky"; break;
911: case 7: charp = "wierd"; break;
912: case 8: charp = "queasy"; break;
913: case 9: charp = "wounded"; break;
914: case 11: charp = "unusual"; break;
915: case 12: charp = "no pain"; break;
916: case 13: charp = "strange"; break;
917: case 14: charp = "noticable"; break;
918: case 15: charp = "bizzare"; break;
919: case 16: charp = "distressed";break;
920: case 17: charp = "different"; break;
921: case 18: charp = "a touch of ague"; break;
922: case 19: charp = "a migrane coming on"; break;
923: case 20: charp = "Excedrin headache #666"; break;
924: case 21: charp = "a disturbance in the force"; break;
925: case 22: charp = "like someone dropped a house on you"; break;
926: case 23: charp = "as if every nerve in your body is on fire"; break;
927: case 24: charp = "like thousands of red-hot army ants are crawling under your skin";
928: break;
929:
930: default:
931: charp = "ill";
932: break;
933: }
934: msg("You feel %s.", charp);
935: }
936:
937: /*
938: const_bonus()
939: Hit point adjustment for changing levels
940: */
941:
942: int
943: const_bonus(void)
944: {
945: int ret_val = -2;
946:
947: if (pstats.s_const > 12)
948: ret_val = pstats.s_const - 12;
949: else if (pstats.s_const > 6)
950: ret_val = 0;
951: else if (pstats.s_const > 3)
952: ret_val = -1;
953:
954: return(ret_val);
955: }
956:
957: /*
958: int_wis_bonus()
959: Spell point adjustment for changing levels
960: */
961:
962: int
963: int_wis_bonus(void)
964: {
965: int ret_val = -2;
966: int casters_stat;
967:
968: switch (player.t_ctype)
969: {
970: case C_PALADIN:
971: case C_CLERIC:
972: casters_stat = pstats.s_wisdom;
973: break;
974: case C_RANGER:
975: case C_DRUID:
976: casters_stat = pstats.s_wisdom;
977: break;
978: case C_MAGICIAN:
979: casters_stat = pstats.s_intel;
980: break;
981: case C_ILLUSION:
982: casters_stat = pstats.s_intel;
983: break;
984:
985: default:
986: if (is_wearing(R_WIZARD))
987: casters_stat = pstats.s_intel;
988: else if (is_wearing(R_PIETY))
989: casters_stat = pstats.s_wisdom;
990: else
991: casters_stat = (rnd(2) ? pstats.s_wisdom :
992: pstats.s_intel);
993: }
994:
995: if (casters_stat > 12)
996: ret_val = casters_stat - 12;
997: else if (casters_stat > 6)
998: ret_val = 0;
999: else if (casters_stat > 3)
1000: ret_val = -1;
1001:
1002: return(ret_val);
1003: }
1004:
1005: void
1006: electrificate(void)
1007: {
1008: int affect_dist = 4 + player.t_stats.s_lvl / 4;
1009: struct linked_list *item, *nitem;
1010:
1011: for (item = mlist; item != NULL; item = nitem)
1012: {
1013: struct thing *tp = THINGPTR(item);
1014: char *mname = monsters[tp->t_index].m_name;
1015:
1016: nitem = next(item);
1017:
1018: if (DISTANCE(tp->t_pos, hero) < affect_dist)
1019: {
1020: int damage = roll(2, player.t_stats.s_lvl);
1021:
1022: debug("Charge does %d (%d)", damage, tp->t_stats.s_hpt - damage);
1023:
1024: if (on(*tp, NOBOLT))
1025: continue;
1026:
1027: if ((tp->t_stats.s_hpt -= damage) <= 0)
1028: {
1029: msg("The %s is killed by an electric shock.", mname);
1030: killed(&player, item, NOMESSAGE, POINTS);
1031: continue;
1032: }
1033:
1034: if (rnd(tp->t_stats.s_intel / 5) == 0)
1035: {
1036: turn_on(*tp, ISFLEE);
1037: msg("The %s is shocked by electricity.", mname);
1038: }
1039: else
1040: msg("The %s is zapped by your electricity.", mname);
1041:
1042: summon_help(tp, NOFORCE);
1043: turn_off(*tp, ISFRIENDLY);
1044: turn_off(*tp, ISCHARMED);
1045: turn_on(*tp, ISRUN);
1046: turn_off(*tp, ISDISGUISE);
1047: chase_it(&tp->t_pos, &player);
1048: fighting = after = running = FALSE;
1049: }
1050: }
1051: }
1052:
1053: /*
1054: feed_me - Print out interesting messages about food consumption
1055: */
1056:
1057: static char *f_hungry[] =
1058: {
1059: "want a cookie",
1060: "feel like a snack",
1061: "feel like some fruit",
1062: "start having the munchies",
1063: "are starting to get hungry"
1064: };
1065:
1066: static char *f_weak[] =
1067: {
1068: "are really hungry",
1069: "could eat a horse",
1070: "want some food - now",
1071: "are starting to feel weak",
1072: "feel a gnawing in your stomach",
1073: "are even willing to eat up cram",
1074: "feel lightheaded from not eating"
1075: };
1076:
1077: static char *f_faint[] =
1078: {
1079: "get dizzy from not eating",
1080: "are starving for nutrients",
1081: "feel too weak from lack of food",
1082: "see a mirage of an incredible banquet",
1083: "have incredible cramps in your stomach"
1084: };
1085:
1086: static char *f_plop[] =
1087: {
1088: "faint",
1089: "pass out",
1090: "keel over",
1091: "black out"
1092: };
1093:
1094: void
1095: feed_me(int hunger)
1096: {
1097: char *charp = NULL, *charp2 = NULL;
1098:
1099: switch (hunger)
1100: {
1101: case F_OK:
1102: default:
1103: debug("feed_me(%d) called.", hunger);
1104: break;
1105:
1106: case F_HUNGRY:
1107: charp = f_hungry[rnd(sizeof(f_hungry) /
1108: sizeof(char *))];
1109: break;
1110:
1111: case F_WEAK:
1112: charp = f_weak[rnd(sizeof(f_weak) / sizeof(char *))];
1113: break;
1114:
1115: case F_FAINT:
1116: charp = f_faint[rnd(sizeof(f_faint) / sizeof(char *))];
1117: charp2 = f_plop[rnd(sizeof(f_plop) / sizeof(char *))];
1118: break;
1119: }
1120:
1121: msg("You %s.", charp);
1122:
1123: if (hunger == F_FAINT)
1124: msg("You %s.", charp2);
1125: }
1126:
1127:
1128: /*
1129: get_monster_number()
1130: prompt player for a monster on list returns 0 if none selected
1131: */
1132:
1133: int
1134: get_monster_number(char *message)
1135: {
1136: int i;
1137: int pres_monst = 1;
1138: int ret_val = -1;
1139: char buf[2 * LINELEN];
1140: char monst_name[2 * LINELEN];
1141:
1142: while (ret_val == -1)
1143: {
1144: msg("Which monster do you wish to %s? (* for list)", message);
1145:
1146: if ((get_string(buf, cw)) != NORM)
1147: return(0);
1148:
1149: if ((i = atoi(buf)) != 0)
1150: ret_val = i;
1151: else if (buf[0] != '*')
1152: {
1153: for (i = 1; i < nummonst; i++)
1154: if ((strcmp(monsters[i].m_name, buf) == 0))
1155: ret_val = i;
1156: }
1157: /* The following hack should be redone by the windowing code */
1158: else
1159: while (pres_monst < nummonst) /* Print out the monsters */
1160: {
1161: int num_lines = LINES - 3;
1162:
1163: wclear(hw);
1164: touchwin(hw);
1165:
1166: wmove(hw, 2, 0);
1167:
1168: for (i = 0; i < num_lines && pres_monst < nummonst; i++)
1169: {
1170: sprintf(monst_name, "[%d] %s\n", pres_monst,
1171: monsters[pres_monst].m_name);
1172: waddstr(hw, monst_name);
1173: pres_monst++;
1174: }
1175:
1176: if (pres_monst < nummonst)
1177: {
1178: mvwaddstr(hw, LINES - 1, 0, morestr);
1179: wrefresh(hw);
1180: wait_for(' ');
1181: }
1182: else
1183: {
1184: mvwaddstr(hw, 0, 0, "Which monster");
1185: waddstr(hw, "? ");
1186: wrefresh(hw);
1187: }
1188: }
1189:
1190: get_monst:
1191: get_string(monst_name, hw);
1192: ret_val = atoi(monst_name);
1193:
1194: if ((ret_val < 1 || ret_val > nummonst - 1))
1195: {
1196: mvwaddstr(hw, 0, 0, "Please enter a number in the displayed range -- ");
1197: wrefresh(hw);
1198: goto get_monst;
1199: }
1200:
1201: /* Set up for redraw */
1202:
1203: clearok(cw, TRUE);
1204: touchwin(cw);
1205: }
1206:
1207: return(ret_val);
1208: }
CVSweb