comparison xrogue/monsters.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 f54901b9c39b
comparison
equal deleted inserted replaced
124:d10fc4a065ac 133:e6179860cb76
1 /*
2 monsters.c - File with various monster functions in it
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 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 <curses.h>
20 #include <ctype.h>
21 #include <string.h>
22 #include "rogue.h"
23
24 /*
25 * Check_residue takes care of any effect of the monster
26 */
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 < (max(50, level) + least); i++) {
145 if (!treas && rnd(100) < 65) /* put in some little buggers */
146 continue;
147
148 /*
149 * Put the monster in
150 */
151 item = new_item(sizeof *mp);
152 mp = THINGPTR(item);
153 do {
154 rnd_pos(rp, &tp);
155 } until(mvwinch(stdscr, tp.y, tp.x) == FLOOR);
156
157 new_monster(item, randmonster(FALSE, FALSE), &tp, FALSE);
158 /*
159 * See if we want to give it a treasure to carry around.
160 */
161 carry_obj(mp, monsters[mp->t_index].m_carry);
162
163 /* Calculate a movement rate */
164 mp->t_no_move = movement(mp);
165
166 /* Is it going to give us some light? */
167 if (on(*mp, HASFIRE)) {
168 register struct linked_list *fire_item;
169
170 fire_item = creat_item();
171 ldata(fire_item) = (char *) mp;
172 attach(rp->r_fires, fire_item);
173 rp->r_flags |= HASFIRE;
174 }
175 }
176 }
177
178 /*
179 * id_monst returns the index of the monster given its letter
180 */
181
182 short
183 id_monst(monster)
184 register char monster;
185 {
186 register short result;
187
188 if (levtype == OUTSIDE) {
189 result = NLEVMONS*vlevel + (NUMMONST-NUMDINOS-1);
190 if (result > NUMMONST) result = NUMMONST;
191 }
192 else {
193 result = NLEVMONS*vlevel;
194 if (result > NUMMONST-NUMDINOS) result = NUMMONST-NUMDINOS;
195 }
196
197 if (levtype == OUTSIDE) {
198 for(; result>(NUMMONST-NUMDINOS-1); result--)
199 if (monsters[result].m_appear == monster) return(result);
200 for (result=(NLEVMONS*vlevel)+1; result <= NUMMONST-NUMDINOS; result++)
201 if (monsters[result].m_appear == monster) return(result);
202 }
203 else {
204 for(; result>0; result--)
205 if (monsters[result].m_appear == monster) return(result);
206 for (result=(NLEVMONS*vlevel)+1; result <= NUMMONST; result++)
207 if (monsters[result].m_appear == monster) return(result);
208 }
209 return(0);
210 }
211
212
213 /*
214 * new_monster:
215 * Pick a new monster and add it to the list
216 */
217
218 new_monster(item, type, cp, max_monster)
219 struct linked_list *item;
220 short type;
221 coord *cp;
222 bool max_monster;
223 {
224 register struct thing *tp;
225 register struct monster *mp;
226 register char *ip, *hitp;
227 register int i, min_intel, max_intel;
228 register int num_dice, num_sides=8, num_extra=0;
229
230 attach(mlist, item);
231 tp = THINGPTR(item);
232 tp->t_pack = NULL;
233 tp->t_index = type;
234 tp->t_wasshot = FALSE;
235 tp->t_type = monsters[type].m_appear;
236 tp->t_ctype = C_MONSTER;
237 tp->t_action = A_NIL;
238 tp->t_doorgoal.x = tp->t_doorgoal.y = -1;
239 tp->t_quiet = 0;
240 tp->t_dest = NULL;
241 tp->t_name = NULL;
242 tp->t_pos = tp->t_oldpos = *cp;
243 tp->t_oldch = mvwinch(cw, cp->y, cp->x);
244 mvwaddch(mw, cp->y, cp->x, tp->t_type);
245 mp = &monsters[tp->t_index];
246
247 /* Figure out monster's hit points */
248 hitp = mp->m_stats.ms_hpt;
249 num_dice = atoi(hitp);
250 if ((hitp = strchr(hitp, 'd')) != NULL) {
251 num_sides = atoi(++hitp);
252 if ((hitp = strchr(hitp, '+')) != NULL)
253 num_extra = atoi(++hitp);
254 }
255
256 tp->t_stats.s_lvladj = 0;
257 tp->t_stats.s_lvl = mp->m_stats.ms_lvl;
258 tp->t_stats.s_arm = mp->m_stats.ms_arm;
259 strcpy(tp->t_stats.s_dmg,mp->m_stats.ms_dmg);
260 tp->t_stats.s_str = mp->m_stats.ms_str;
261 tp->t_stats.s_dext = mp->m_stats.ms_dex;
262 tp->t_movement = mp->m_stats.ms_move;
263 if (vlevel > HARDER) { /* the deeper, the meaner we get */
264 tp->t_stats.s_lvl += (vlevel - HARDER);
265 num_dice += (vlevel - HARDER)/2;
266 tp->t_stats.s_arm -= (vlevel - HARDER) / 4;
267 }
268 if (max_monster)
269 tp->t_stats.s_hpt = num_dice * num_sides + num_extra;
270 else
271 tp->t_stats.s_hpt = roll(num_dice, num_sides) + num_extra;
272 tp->t_stats.s_exp = mp->m_stats.ms_exp + mp->m_add_exp*tp->t_stats.s_hpt;
273
274 /*
275 * just initailize others values to something reasonable for now
276 * maybe someday will *really* put these in monster table
277 */
278 tp->t_stats.s_wisdom = 8 + rnd(7);
279 tp->t_stats.s_const = 8 + rnd(7);
280 tp->t_stats.s_charisma = 8 + rnd(7);
281
282 /* Set the initial flags */
283 for (i=0; i<16; i++) tp->t_flags[i] = 0;
284 for (i=0; i<MAXFLAGS; i++)
285 turn_on(*tp, mp->m_flags[i]);
286
287 /*
288 * these are the base chances that a creatures will do something
289 * assuming it can. These are(or can be) modified at runtime
290 * based on what the creature experiences
291 */
292 tp->t_breathe = 70; /* base chance of breathing */
293 tp->t_artifact = 90; /* base chance of using artifact */
294 tp->t_summon = 50; /* base chance of summoning */
295 tp->t_cast = 70; /* base chance of casting a spell */
296 tp->t_wand = on(*tp, ISUNIQUE) ? 35 : 50; /* base chance of using wands */
297
298 /* suprising monsters don't always surprise you */
299 if (!max_monster && on(*tp, CANSURPRISE) &&
300 off(*tp, ISUNIQUE) && rnd(100) < 25)
301 turn_off(*tp, CANSURPRISE);
302
303 /* If this monster is unique, gen it */
304 if (on(*tp, ISUNIQUE)) mp->m_normal = FALSE;
305
306 /*
307 * If it is the quartermaster, then compute his level and exp pts
308 * based on the level. This will make it fair when thieves try to
309 * steal and give them reasonable experience if they succeed.
310 * Then fill his pack with his wares.
311 */
312 if (on(*tp, CANSELL)) {
313 tp->t_stats.s_exp = vlevel * 100;
314 tp->t_stats.s_lvl = vlevel/2 + 1;
315 make_sell_pack(tp);
316 }
317
318 /* Normally scared monsters have a chance to not be scared */
319 if (on(*tp, ISFLEE) && (rnd(4) == 0)) turn_off(*tp, ISFLEE);
320
321 /* Figure intelligence */
322 min_intel = atoi(mp->m_intel);
323 if ((ip = (char *) strchr(mp->m_intel, '-')) == NULL)
324 tp->t_stats.s_intel = min_intel;
325 else {
326 max_intel = atoi(++ip);
327 if (max_monster)
328 tp->t_stats.s_intel = max_intel;
329 else
330 tp->t_stats.s_intel = min_intel + rnd(max_intel - min_intel);
331 }
332 if (vlevel > HARDER)
333 tp->t_stats.s_intel += ((vlevel - HARDER)/2);
334 tp->maxstats = tp->t_stats;
335
336 /* If the monster can shoot, it may have a weapon */
337 if (on(*tp, CANSHOOT) && ((rnd(100) < (20 + vlevel)) || max_monster)) {
338 struct linked_list *item1;
339 register struct object *cur, *cur1;
340
341 item = new_item(sizeof *cur);
342 item1 = new_item(sizeof *cur1);
343 cur = OBJPTR(item);
344 cur1 = OBJPTR(item1);
345 cur->o_hplus = (rnd(4) < 3) ? 0
346 : (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
347 cur->o_dplus = (rnd(4) < 3) ? 0
348 : (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
349 cur1->o_hplus = (rnd(4) < 3) ? 0
350 : (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
351 cur1->o_dplus = (rnd(4) < 3) ? 0
352 : (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
353 strcpy(cur->o_damage,"0d0");
354 strcpy(cur->o_hurldmg,"0d0");
355 strcpy(cur1->o_damage,"0d0");
356 strcpy(cur1->o_hurldmg,"0d0");
357 cur->o_ac = cur1->o_ac = 11;
358 cur->o_count = cur1->o_count = 1;
359 cur->o_group = cur1->o_group = 0;
360 cur->contents = cur1->contents = NULL;