comparison rogue3/fight.c @ 0:527e2150eaf0

Import Rogue 3.6 from the Roguelike Restoration Project (r1490)
author edwarj4
date Tue, 13 Oct 2009 13:33:34 +0000
parents
children e7aab31362af
comparison
equal deleted inserted replaced
-1:000000000000 0:527e2150eaf0
1 /*
2 * All the fighting gets done here
3 *
4 * @(#)fight.c 3.28 (Berkeley) 6/15/81
5 *
6 * Rogue: Exploring the Dungeons of Doom
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 <ctype.h>
15 #include <string.h>
16 #include <stdlib.h>
17 #include "rogue.h"
18
19 int e_levels[] = {
20 10,20,40,80,160,320,640,1280,2560,5120,10240,20480,
21 40920, 81920, 163840, 327680, 655360, 1310720, 2621440, 0 };
22
23 /*
24 * fight:
25 * The player attacks the monster.
26 */
27
28 int
29 fight(coord *mp, int mn, struct object *weap, int thrown)
30 {
31 struct thing *tp;
32 struct linked_list *item;
33 int did_hit = TRUE;
34
35 /*
36 * Find the monster we want to fight
37 */
38 if ((item = find_mons(mp->y, mp->x)) == NULL)
39 {
40 debug("Fight what @ %d,%d", mp->y, mp->x);
41 return(0);
42 }
43 tp = (struct thing *) ldata(item);
44 /*
45 * Since we are fighting, things are not quiet so no healing takes
46 * place.
47 */
48 quiet = 0;
49 runto(mp, &hero);
50 /*
51 * Let him know it was really a mimic (if it was one).
52 */
53 if (tp->t_type == 'M' && tp->t_disguise != 'M' && off(player, ISBLIND))
54 {
55 msg("Wait! That's a mimic!");
56 tp->t_disguise = 'M';
57 did_hit = thrown;
58 }
59 if (did_hit)
60 {
61 char *mname;
62
63 did_hit = FALSE;
64 if (on(player, ISBLIND))
65 mname = "it";
66 else
67 mname = monsters[mn-'A'].m_name;
68 if (roll_em(&pstats, &tp->t_stats, weap, thrown))
69 {
70 did_hit = TRUE;
71 if (thrown)
72 thunk(weap, mname);
73 else
74 hit(NULL, mname);
75 if (on(player, CANHUH))
76 {
77 msg("Your hands stop glowing red");
78 msg("The %s appears confused.", mname);
79 tp->t_flags |= ISHUH;
80 player.t_flags &= ~CANHUH;
81 }
82 if (tp->t_stats.s_hpt <= 0)
83 killed(item, TRUE);
84 }
85 else
86 if (thrown)
87 bounce(weap, mname);
88 else
89 miss(NULL, mname);
90 }
91 count = 0;
92 return did_hit;
93 }
94
95 /*
96 * attack:
97 * The monster attacks the player
98 */
99
100 int
101 attack(struct thing *mp)
102 {
103 char *mname;
104
105 /*
106 * Since this is an attack, stop running and any healing that was
107 * going on at the time.
108 */
109 running = FALSE;
110 quiet = 0;
111 if (mp->t_type == 'M' && off(player, ISBLIND))
112 mp->t_disguise = 'M';
113 if (on(player, ISBLIND))
114 mname = "it";
115 else
116 mname = monsters[mp->t_type-'A'].m_name;
117 if (roll_em(&mp->t_stats, &pstats, NULL, FALSE))
118 {
119 if (mp->t_type != 'E')
120 hit(mname, NULL);
121 if (pstats.s_hpt <= 0)
122 death(mp->t_type); /* Bye bye life ... */
123 if (off(*mp, ISCANC))
124 switch (mp->t_type)
125 {
126 case 'R':
127 /*
128 * If a rust monster hits, you lose armor
129 */
130 if (cur_armor != NULL && cur_armor->o_ac < 9)
131 {
132 if (!terse)
133 msg("Your armor appears to be weaker now. Oh my!");
134 else
135 msg("Your armor weakens");
136 cur_armor->o_ac++;
137 }
138 when 'E':
139 /*
140 * The gaze of the floating eye hypnotizes you
141 */
142 if (on(player, ISBLIND))
143 break;
144 if (!no_command)
145 {
146 addmsg("You are transfixed");
147 if (!terse)
148 addmsg(" by the gaze of the floating eye.");
149 endmsg();
150 }
151 no_command += rnd(2)+2;
152 if (no_command > 100 && food_left <= 0)
153 death('E');
154 when 'A':
155 /*
156 * Ants have poisonous bites
157 */
158 if (!save(VS_POISON))
159 if (!ISWEARING(R_SUSTSTR))
160 {
161 chg_str(-1);
162 if (!terse)
163 msg("You feel a sting in your arm and now feel weaker");
164 else
165 msg("A sting has weakened you");
166 }
167 else
168 if (!terse)
169 msg("A sting momentarily weakens you");
170 else
171 msg("Sting has no effect");
172 when 'W':
173 /*
174 * Wraiths might drain energy levels
175 */
176 if (rnd(100) < 15)
177 {
178 int fewer;
179
180 if (pstats.s_exp == 0)
181 death('W'); /* All levels gone */
182 msg("You suddenly feel weaker.");
183 if (--pstats.s_lvl == 0)
184 {
185 pstats.s_exp = 0;
186 pstats.s_lvl = 1;
187 }
188 else
189 pstats.s_exp = e_levels[pstats.s_lvl-1]+1;
190 fewer = roll(1, 10);
191 pstats.s_hpt -= fewer;
192 max_hp -= fewer;
193 if (pstats.s_hpt < 1)
194 pstats.s_hpt = 1;
195 if (max_hp < 1)
196 death('W');
197 }
198 when 'F':
199 /*
200 * Violet fungi stops the poor guy from moving
201 */
202 player.t_flags |= ISHELD;
203 sprintf(monsters['F'-'A'].m_stats.s_dmg,"%dd1",++fung_hit);
204 when 'L':
205 {
206 /*
207 * Leperachaun steals some gold
208 */
209 int lastpurse;
210
211 lastpurse = purse;
212 purse -= GOLDCALC;
213 if (!save(VS_MAGIC))
214 purse -= GOLDCALC + GOLDCALC + GOLDCALC + GOLDCALC;
215 if (purse < 0)
216 purse = 0;
217 if (purse != lastpurse)
218 msg("Your purse feels lighter");
219 remove_monster(&mp->t_pos, find_mons(mp->t_pos.y, mp->t_pos.x));
220 mp = NULL;
221 }
222 when 'N':
223 {
224 struct linked_list *list, *steal;
225 struct object *obj;
226 int nobj;
227
228 /*
229 * Nymph's steal a magic item, look through the pack
230 * and pick out one we like.
231 */
232 steal = NULL;
233 for (nobj = 0, list = pack; list != NULL; list = next(list))
234 {
235 obj = (struct object *) ldata(list);
236 if (obj != cur_armor &&
237 obj != cur_weapon &&
238 obj != cur_ring[LEFT] &&
239 obj != cur_ring[RIGHT] && /* Nymph bug fix */
240 is_magic(obj) &&
241 rnd(++nobj) == 0)
242 steal = list;
243 }
244 if (steal != NULL)
245 {
246 struct object *sobj;
247
248 sobj = (struct object *) ldata(steal);
249 remove_monster(&mp->t_pos, find_mons(mp->t_pos.y, mp->t_pos.x));
250 mp = NULL;
251 if (sobj->o_count > 1 && sobj->o_group == 0)
252 {
253 int oc;
254
255 oc = sobj->o_count;
256 sobj->o_count = 1;
257 msg("She stole %s!", inv_name(sobj, TRUE));
258 sobj->o_count = oc - 1;
259 }
260 else
261 {
262 msg("She stole %s!", inv_name(sobj, TRUE));
263 detach(pack, steal);
264 discard(steal);
265 }
266 inpack--;
267 }
268 }
269 otherwise:
270 break;
271 }
272 }
273 else if (mp->t_type != 'E')
274 {
275 if (mp->t_type == 'F')
276 {
277 pstats.s_hpt -= fung_hit;
278 if (pstats.s_hpt <= 0)
279 death(mp->t_type); /* Bye bye life ... */
280 }
281 miss(mname, NULL);
282 }
283 /*
284 * Check to see if this is a regenerating monster and let it heal if
285 * it is.
286 */
287 if ((mp != NULL) && (on(*mp, ISREGEN) && rnd(100) < 33))
288 mp->t_stats.s_hpt++;
289 if (fight_flush)
290 {
291 flush_type(); /* flush typeahead */
292 }
293 count = 0;
294 status();
295
296 if (mp == NULL)
297 return(-1);
298 else
299 return(0);
300 }
301
302 /*
303 * swing:
304 * returns true if the swing hits
305 */
306
307 int
308 swing(int at_lvl, int op_arm, int wplus)
309 {
310 int res = rnd(20)+1;
311 int need = (21-at_lvl)-op_arm;
312
313 return (res+wplus >= need);
314 }
315
316 /*
317 * check_level:
318 * Check to see if the guy has gone up a level.
319 */
320
321 void
322 check_level()
323 {
324 int i, add;
325
326 for (i = 0; e_levels[i] != 0; i++)
327 if (e_levels[i] > pstats.s_exp)
328 break;
329 i++;
330 if (i > pstats.s_lvl)
331 {
332 add = roll(i-pstats.s_lvl,10);
333 max_hp += add;
334 if ((pstats.s_hpt += add) > max_hp)
335 pstats.s_hpt = max_hp;
336 msg("Welcome to level %d", i);
337 }
338 pstats.s_lvl = i;
339 }
340
341 /*
342 * roll_em:
343 * Roll several attacks
344 */
345
346 int
347 roll_em(struct stats *att, struct stats *def, struct object *weap, int hurl)
348 {
349 char *cp;
350 int ndice, nsides, def_arm;
351 int did_hit = FALSE;
352 int prop_hplus, prop_dplus;
353
354 prop_hplus = prop_dplus = 0;
355 if (weap == NULL)
356 cp = att->s_dmg;
357 else if (hurl)
358 if ((weap->o_flags&ISMISL) && cur_weapon != NULL &&
359 cur_weapon->o_which == weap->o_launch)
360 {
361 cp = weap->o_hurldmg;
362 prop_hplus = cur_weapon->o_hplus;
363 prop_dplus = cur_weapon->o_dplus;
364 }
365 else
366 cp = (weap->o_flags&ISMISL ? weap->o_damage : weap->o_hurldmg);
367 else
368 {
369 cp = weap->o_damage;
370 /*
371 * Drain a staff of striking
372 */
373 if (weap->o_type == STICK && weap->o_which == WS_HIT
374 && weap->o_charges == 0)
375 {
376 strcpy(weap->o_damage,"0d0");
377 weap->o_hplus = weap->o_dplus = 0;
378 }
379 }
380 for (;;)
381 {
382 int damage;
383 int hplus = prop_hplus + (weap == NULL ? 0 : weap->o_hplus);