comparison arogue7/monsters.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 * monsters.c - File with various monster functions in it
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 /*
16 * File with various monster functions in it
17 *
18 */
19
20 #include "curses.h"
21 #include "rogue.h"
22 #include <ctype.h>
23
24
25 /*
26 * Check_residue takes care of any effect of the monster
27 */
28 check_residue(tp)
29 register struct thing *tp;
30 {
31 /*
32 * Take care of special abilities
33 */
34 if (on(*tp, DIDHOLD) && (--hold_count == 0)) {
35 turn_off(player, ISHELD);
36 turn_off(*tp, DIDHOLD);
37 }
38
39 /* If frightened of this monster, stop */
40 if (on(player, ISFLEE) &&
41 player.t_dest == &tp->t_pos) turn_off(player, ISFLEE);
42
43 /* If monster was suffocating player, stop it */
44 if (on(*tp, DIDSUFFOCATE)) {
45 extinguish(suffocate);
46 turn_off(*tp, DIDSUFFOCATE);
47 }
48
49 /* If something with fire, may darken */
50 if (on(*tp, HASFIRE)) {
51 register struct room *rp=roomin(&tp->t_pos);
52 register struct linked_list *fire_item;
53
54 if (rp) {
55 for (fire_item = rp->r_fires; fire_item != NULL;
56 fire_item = next(fire_item)) {
57 if (THINGPTR(fire_item) == tp) {
58 detach(rp->r_fires, fire_item);
59 destroy_item(fire_item);
60 if (rp->r_fires == NULL) {
61 rp->r_flags &= ~HASFIRE;
62 if (cansee(tp->t_pos.y, tp->t_pos.x)) light(&hero);
63 }
64 break;
65 }
66 }
67 }
68 }
69 }
70
71 /*
72 * Creat_mons creates the specified monster -- any if 0
73 */
74
75 bool
76 creat_mons(person, monster, report)
77 struct thing *person; /* Where to create next to */
78 short monster;
79 bool report;
80 {
81 struct linked_list *nitem;
82 register struct thing *tp;
83 struct room *rp;
84 coord *mp;
85
86 if (levtype == POSTLEV)
87 return(FALSE);
88 if ((mp = fallpos(&(person->t_pos), FALSE, 2)) != NULL) {
89 nitem = new_item(sizeof (struct thing));
90 new_monster(nitem,
91 monster == 0 ? randmonster(FALSE, FALSE)
92 : monster,
93 mp,
94 TRUE);
95 tp = THINGPTR(nitem);
96 runto(tp, &hero);
97 carry_obj(tp, monsters[tp->t_index].m_carry/2); /* only half chance */
98
99 /* since it just got here, it is disoriented */
100 tp->t_no_move = 2 * movement(tp);
101
102 if (on(*tp, HASFIRE)) {
103 rp = roomin(&tp->t_pos);
104 if (rp) {
105 register struct linked_list *fire_item;
106
107 /* Put the new fellow in the room list */
108 fire_item = creat_item();
109 ldata(fire_item) = (char *) tp;
110 attach(rp->r_fires, fire_item);
111
112 rp->r_flags |= HASFIRE;
113 }
114 }
115
116 /*
117 * If we can see this monster, set oldch to ' ' to make light()
118 * think the creature used to be invisible (ie. not seen here)
119 */
120 if (cansee(tp->t_pos.y, tp->t_pos.x)) tp->t_oldch = ' ';
121 return(TRUE);
122 }
123 if (report) msg("You hear a faint cry of anguish in the distance.");
124 return(FALSE);
125 }
126
127 /*
128 * Genmonsters:
129 * Generate at least 'least' monsters for this single room level.
130 * 'Treas' indicates whether this is a "treasure" level.
131 */
132
133 void
134 genmonsters(least, treas)
135 register int least;
136 bool treas;
137 {
138 reg int i;
139 reg struct room *rp = &rooms[0];
140 reg struct linked_list *item;
141 reg struct thing *mp;
142 coord tp;
143
144 for (i = 0; i < level + least; i++) {
145 if (!treas && rnd(100) < 50) /* put in some little buggers */
146 continue;
147 /*
148 * Put the monster in
149 */
150 item = new_item(sizeof *mp);
151 mp = THINGPTR(item);
152 do {
153 rnd_pos(rp, &tp);
154 } until(mvwinch(stdscr, tp.y, tp.x) == FLOOR);
155
156 new_monster(item, randmonster(FALSE, FALSE), &tp, FALSE);
157 /*
158 * See if we want to give it a treasure to carry around.
159 */
160 carry_obj(mp, monsters[mp->t_index].m_carry);
161
162 /* Calculate a movement rate */
163 mp->t_no_move = movement(mp);
164
165 /* Is it going to give us some light? */
166 if (on(*mp, HASFIRE)) {
167 register struct linked_list *fire_item;
168
169 fire_item = creat_item();
170 ldata(fire_item) = (char *) mp;
171 attach(rp->r_fires, fire_item);
172 rp->r_flags |= HASFIRE;
173 }
174 }
175 }
176
177 /*
178 * id_monst returns the index of the monster given its letter
179 */
180
181 short
182 id_monst(monster)
183 register char monster;
184 {
185 register short result;
186
187 result = NLEVMONS*vlevel;
188 if (result > NUMMONST) result = NUMMONST;
189
190 for(; result>0; result--)
191 if (monsters[result].m_appear == monster) return(result);
192 for (result=(NLEVMONS*vlevel)+1; result <= NUMMONST; result++)
193 if (monsters[result].m_appear == monster) return(result);
194 return(0);
195 }
196
197
198 /*
199 * new_monster:
200 * Pick a new monster and add it to the list
201 */
202
203 new_monster(item, type, cp, max_monster)
204 struct linked_list *item;
205 short type;
206 coord *cp;
207 bool max_monster;
208 {
209 register struct thing *tp;
210 register struct monster *mp;
211 register char *ip, *hitp;
212 register int i, min_intel, max_intel;
213 register int num_dice, num_sides=8, num_extra=0;
214 char *strchr();
215
216 attach(mlist, item);
217 tp = THINGPTR(item);
218 tp->t_pack = NULL;
219 tp->t_index = type;
220 tp->t_wasshot = FALSE;
221 tp->t_type = monsters[type].m_appear;
222 tp->t_ctype = C_MONSTER;
223 tp->t_action = A_NIL;
224 tp->t_doorgoal = 0;
225 tp->t_quiet = 0;
226 tp->t_dest = NULL;
227 tp->t_name = NULL;
228 tp->t_pos = tp->t_oldpos = *cp;
229 tp->t_oldch = CCHAR( mvwinch(cw, cp->y, cp->x) );
230 mvwaddch(mw, cp->y, cp->x, tp->t_type);
231 mp = &monsters[tp->t_index];
232
233 /* Figure out monster's hit points */
234 hitp = mp->m_stats.s_hpt;
235 num_dice = atoi(hitp);
236 if ((hitp = strchr(hitp, 'd')) != NULL) {
237 num_sides = atoi(++hitp);
238 if ((hitp = strchr(hitp, '+')) != NULL)
239 num_extra = atoi(++hitp);
240 }
241
242 tp->t_stats.s_lvladj = 0;
243 tp->t_stats.s_lvl = mp->m_stats.s_lvl;
244 tp->t_stats.s_arm = mp->m_stats.s_arm;
245 strncpy(tp->t_stats.s_dmg, mp->m_stats.s_dmg, sizeof(tp->t_stats.s_dmg));
246 tp->t_stats.s_str = mp->m_stats.s_str;
247 tp->t_stats.s_dext = mp->m_stats.s_dex;
248 tp->t_movement = mp->m_stats.s_move;
249 if (vlevel > HARDER) { /* the deeper, the meaner we get */
250 tp->t_stats.s_lvl += (vlevel - HARDER);
251 num_dice += (vlevel - HARDER)/2;
252 tp->t_stats.s_arm -= (vlevel - HARDER) / 4;
253 }
254 if (max_monster)
255 tp->t_stats.s_hpt = num_dice * num_sides + num_extra;
256 else
257 tp->t_stats.s_hpt = roll(num_dice, num_sides) + num_extra;
258 tp->t_stats.s_exp = mp->m_stats.s_exp + mp->m_add_exp*tp->t_stats.s_hpt;
259
260 /*
261 * just initailize others values to something reasonable for now
262 * maybe someday will *really* put these in monster table
263 */
264 tp->t_stats.s_wisdom = 8 + rnd(4);
265 tp->t_stats.s_const = 8 + rnd(4);
266 tp->t_stats.s_charisma = 8 + rnd(4);
267
268 /* Set the initial flags */
269 for (i=0; i<16; i++) tp->t_flags[i] = 0;
270 for (i=0; i<MAXFLAGS; i++)
271 turn_on(*tp, mp->m_flags[i]);
272
273 /*
274 * these are the base chances that a creatures will do something
275 * assuming it can. These are(or can be) modified at runtime
276 * based on what the creature experiences
277 */
278 tp->t_breathe = 75; /* base chance of breathing */
279 tp->t_artifact = 90; /* base chance of using artifact */
280 tp->t_summon = 40; /* base chance of summoning */
281 tp->t_cast = 75; /* base chance of casting a spell */
282 tp->t_wand = on(*tp, ISUNIQUE) ? 35 : 50; /* base chance of using wands */
283
284 /* suprising monsters don't always surprise you */
285 if (!max_monster && on(*tp, CANSURPRISE) &&
286 off(*tp, ISUNIQUE) && rnd(100) < 20)
287 turn_off(*tp, CANSURPRISE);
288
289 /* If this monster is unique, gen it */
290 if (on(*tp, ISUNIQUE)) mp->m_normal = FALSE;
291
292 /*
293 * If it is the quartermaster, then compute his level and exp pts
294 * based on the level. This will make it fair when thieves try to
295 * steal and give them reasonable experience if they succeed.
296 * Then fill his pack with his wares.
297 */
298 if (on(*tp, CANSELL)) {
299 tp->t_stats.s_exp = vlevel * 100;
300 tp->t_stats.s_lvl = vlevel/2 + 1;
301 make_sell_pack(tp);
302 }
303
304 /* Normally scared monsters have a chance to not be scared */
305 if (on(*tp, ISFLEE) && (rnd(4) == 0)) turn_off(*tp, ISFLEE);
306
307 /* Figure intelligence */
308 min_intel = atoi(mp->m_intel);
309 if ((ip = (char *) strchr(mp->m_intel, '-')) == NULL)
310 tp->t_stats.s_intel = min_intel;
311 else {
312 max_intel = atoi(++ip);
313 if (max_monster)
314 tp->t_stats.s_intel = max_intel;
315 else
316 tp->t_stats.s_intel = min_intel + rnd(max_intel - min_intel);
317 }
318 if (vlevel > HARDER)
319 tp->t_stats.s_intel += ((vlevel - HARDER)/2);
320 tp->maxstats = tp->t_stats;
321
322 /* If the monster can shoot, it may have a weapon */
323 if (on(*tp, CANSHOOT) && ((rnd(100) < (22 + vlevel)) || max_monster)) {
324 struct linked_list *item1;
325 register struct object *cur, *cur1;
326
327 item = new_item(sizeof *cur);
328 item1 = new_item(sizeof *cur1);
329 cur = OBJPTR(item);
330 cur1 = OBJPTR(item1);
331 cur->o_hplus = (rnd(4) < 3) ? 0
332 : (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
333 cur->o_dplus = (rnd(4) < 3) ? 0
334 : (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
335 cur1->o_hplus = (rnd(4) < 3) ? 0
336 : (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
337 cur1->o_dplus = (rnd(4) < 3) ? 0
338 : (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
339
340 strncpy(cur->o_damage, "0d0", sizeof(cur->o_damage));
341 strncpy(cur->o_hurldmg, "0d0", sizeof(cur->o_hurldmg));
342 strncpy(cur1->o_damage, "0d0", sizeof(cur1->o_damage));
343 strncpy(cur1->o_hurldmg, "0d0", sizeof(cur1->o_hurldmg));
344
345 cur->o_ac = cur1->o_ac = 11;
346 cur->o_count = cur1->o_count = 1;
347 cur->o_group = cur1->o_group = 0;
348 cur->contents = cur1->contents = NULL;
349 if ((cur->o_hplus <= 0) && (cur->o_dplus <= 0)) cur->o_flags = ISCURSED;
350 if ((cur1->o_hplus <= 0) && (cur1->o_dplus <= 0))
351 cur1->o_flags = ISCURSED;
352 cur->o_flags = cur1->o_flags = 0;
353 cur->o_type = cur1->o_type = WEAPON;
354 cur->o_mark[0] = cur1->o_mark[0] = '\0';
355
356 /* The monster may use a crossbow, sling, or an arrow */
357 i = rnd(100);
358 if (i < 10) {
359 cur->o_which = CROSSBOW;
360 cur1->o_which = BOLT;
361 init_weapon(cur, CROSSBOW);
362 init_weapon(cur1, BOLT);
363 }
364 else if (i < 70) {
365 cur->o_which = BOW;
366 cur1->o_which = ARROW;
367 init_weapon(cur, BOW);
368 init_weapon(cur1, ARROW);