Maybe better compatibility...
[rogue-pphs.git] / monsters.c
1 /*
2 * File with various monster functions in it
3 *
4 * @(#)monsters.c 3.18 (Berkeley) 6/15/81
5 *
6 * Rogue: Exploring the Cavern of Cuties
7 * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
8 * All rights reserved.
9 *
10 * See the file LICENSE.TXT for full copyright and licensing information.
11 */
12
13 #include "curses.h"
14 #include "rogue.h"
15 #include <string.h>
16 #include <ctype.h>
17
18 /*
19 * List of monsters in rough order of vorpalness
20 */
21 char lvl_mons[27] = "KJBSHEAOZGLCRQNYTWFIXUMVDP";
22 char wand_mons[27] = "KJBSH AOZG CRQ Y W IXU V ";
23
24 /*
25 * randmonster:
26 * Pick a monster to show up. The lower the level,
27 * the meaner the monster.
28 */
29
30 randmonster(wander)
31 bool wander;
32 {
33 register int d;
34 register char *mons;
35
36 mons = wander ? wand_mons : lvl_mons;
37 do
38 {
39 d = level + (rnd(10) - 5);
40 if (d < 1)
41 d = rnd(5) + 1;
42 if (d > 26)
43 d = rnd(5) + 22;
44 } while (mons[--d] == ' ');
45 return mons[d];
46 }
47
48 /*
49 * new_monster:
50 * Pick a new monster and add it to the list
51 */
52
53 new_monster(item, type, cp)
54 struct linked_list *item;
55 char type;
56 register coord *cp;
57 {
58 register struct thing *tp;
59 register struct monster *mp;
60
61 attach(mlist, item);
62 tp = (struct thing *) ldata(item);
63 tp->t_type = type;
64 tp->t_pos = *cp;
65 tp->t_oldch = mvwinch(cw, cp->y, cp->x);
66 mvwaddch(mw, cp->y, cp->x, tp->t_type);
67 mp = &monsters[tp->t_type-'A'];
68 tp->t_stats.s_hpt = roll(mp->m_stats.s_lvl, 8);
69 tp->t_stats.s_lvl = mp->m_stats.s_lvl;
70 tp->t_stats.s_arm = mp->m_stats.s_arm;
71 strcpy(tp->t_stats.s_dmg,mp->m_stats.s_dmg);
72 tp->t_stats.s_exp = mp->m_stats.s_exp;
73 tp->t_stats.s_str.st_str = 10;
74 tp->t_stats.s_ont = rnd(1 << NUM_FEATURES);
75 tp->t_flags = mp->m_flags;
76 tp->t_turn = TRUE;
77 tp->t_pack = NULL;
78 if (ISWEARING(R_AGGR))
79 runto(cp, &hero);
80 if (type == 'M')
81 {
82 char mch;
83
84 if (tp->t_pack != NULL)
85 mch = ((struct object *) ldata(tp->t_pack))->o_type;
86 else
87 switch (rnd(level > 25 ? 9 : 8))
88 {
89 case 0: mch = GOLD;
90 when 1: mch = POTION;
91 when 2: mch = SCROLL;
92 when 3: mch = STAIRS;
93 when 4: mch = WEAPON;
94 when 5: mch = ARMOR;
95 when 6: mch = RING;
96 when 7: mch = STICK;
97 when 8: mch = AMULET;
98 }
99 tp->t_disguise = mch;
100 }
101 }
102
103 /*
104 * wanderer:
105 * A wandering monster has awakened and is headed for the player
106 */
107
108 wanderer()
109 {
110 register int i, ch;
111 register struct room *rp, *hr = roomin(&hero);
112 register struct linked_list *item;
113 register struct thing *tp;
114 coord cp;
115
116 item = new_item(sizeof *tp);
117 do
118 {
119 i = rnd_room();
120 if ((rp = &rooms[i]) == hr)
121 continue;
122 rnd_pos(rp, &cp);
123 if ((ch = mvwinch(stdscr, cp.y, cp.x)) == ERR)
124 {
125 debug("Routine wanderer: mvwinch failed to %d,%d", cp.y, cp.x);
126 if (wizard)
127 wait_for(cw,'\n');
128 return;
129 }
130 } until(hr != rp && step_ok(ch));
131 new_monster(item, randmonster(TRUE), &cp);
132 tp = (struct thing *) ldata(item);
133 tp->t_flags |= ISRUN;
134 tp->t_pos = cp;
135 tp->t_dest = &hero;
136 if (wizard)
137 msg("Started a wandering %s", monsters[tp->t_type-'A'].m_name);
138 }
139
140 /*
141 * what to do when the hero steps next to a monster
142 */
143 struct linked_list *
144 wake_monster(y, x)
145 int y, x;
146 {
147 register struct thing *tp;
148 register struct linked_list *it;
149 register struct room *rp;
150 register char ch;
151
152 if ((it = find_mons(y, x)) == NULL)
153 fatal("Can't find monster in wake");
154 tp = (struct thing *) ldata(it);
155 ch = tp->t_type;
156 /*
157 * Every time he sees mean monster, it might start chasing him
158 */
159 if (rnd(100) > 33 && on(*tp, ISMEAN) && off(*tp, ISHELD)
160 && !ISWEARING(R_STEALTH))
161 {
162 tp->t_dest = &hero;
163 tp->t_flags |= ISRUN;
164 }
165 if (ch == 'U' && off(player, ISBLIND))
166 {
167 rp = roomin(&hero);
168 if ((rp != NULL && !(rp->r_flags&ISDARK))
169 || DISTANCE(y, x, hero.y, hero.x) < 3)
170 {
171 if (off(*tp, ISFOUND) && !save(VS_MAGIC))
172 {
173 msg("The umber hulk's gaze has confused you.");
174 if (on(player, ISHUH))
175 lengthen(unconfuse, rnd(20)+HUHDURATION);
176 else
177 fuse(unconfuse, 0, rnd(20)+HUHDURATION, AFTER);
178 player.t_flags |= ISHUH;
179 }
180 tp->t_flags |= ISFOUND;
181 }
182 }
183 /*
184 * Hide invisible monsters
185 */
186 if (on(*tp, ISINVIS) && off(player, CANSEE))
187 ch = mvwinch(stdscr, y, x);
188 /*
189 * Let greedy ones guard gold
190 */
191 if (on(*tp, ISGREED) && off(*tp, ISRUN))
192 {
193 rp = roomin(&hero);
194
195 if (rp != NULL && rp->r_goldval)
196 {
197 tp->t_dest = &rp->r_gold;
198 tp->t_flags |= ISRUN;
199 }
200 }
201
202 return it;
203 }
204
205 genocide()
206 {
207 register struct linked_list *ip;
208 register struct thing *mp;
209 register char c;
210 register int i;
211 register struct linked_list *nip;
212
213 addmsg("Which monster");
214 if (!terse)
215 addmsg(" do you wish to wipe out");
216 msg("? ");
217 while (!isalpha(c = readchar(cw)))
218 if (c == ESCAPE)
219 return;
220 else
221 {
222 mpos = 0;
223 msg("Please specify a letter between 'A' and 'Z'");
224 }
225 if (islower(c))
226 c = toupper(c);
227 for (ip = mlist; ip; ip = nip)
228 {
229 mp = (struct thing *) ldata(ip);
230 nip = next(ip);
231 if (mp->t_type == c)
232 remove_monster(&mp->t_pos, ip);
233 }
234 for (i = 0; i < 26; i++)
235 if (lvl_mons[i] == c)
236 {
237 lvl_mons[i] = ' ';
238 wand_mons[i] = ' ';
239 break;
240 }
241 }