comparison rogue5/fight.c @ 33:f502bf60e6e4

Import Rogue 5.4 from the Roguelike Restoration Project (r1490)
author elwin
date Mon, 24 May 2010 20:10:59 +0000
parents
children e7aab31362af
comparison
equal deleted inserted replaced
32:2dcd75e6a736 33:f502bf60e6e4
1 /*
2 * All the fighting gets done here
3 *
4 * @(#)fight.c 4.67 (Berkeley) 09/06/83
5 *
6 * Rogue: Exploring the Dungeons of Doom
7 * Copyright (C) 1980-1983, 1985, 1999 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 <stdlib.h>
14 #include <curses.h>
15 #include <string.h>
16 #include <ctype.h>
17 #include "rogue.h"
18
19 #define EQSTR(a, b) (strcmp(a, b) == 0)
20
21 static const char *h_names[] = { /* strings for hitting */
22 " scored an excellent hit on ",
23 " hit ",
24 " have injured ",
25 " swing and hit ",
26 " scored an excellent hit on ",
27 " hit ",
28 " has injured ",
29 " swings and hits "
30 };
31
32 static const char *m_names[] = { /* strings for missing */
33 " miss",
34 " swing and miss",
35 " barely miss",
36 " don't hit",
37 " misses",
38 " swings and misses",
39 " barely misses",
40 " doesn't hit",
41 };
42
43 /*
44 * adjustments to hit probabilities due to strength
45 */
46 static int str_plus[] = {
47 -7, -6, -5, -4, -3, -2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
48 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3,
49 };
50
51 /*
52 * adjustments to damage done due to strength
53 */
54 static int add_dam[] = {
55 -7, -6, -5, -4, -3, -2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3,
56 3, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6
57 };
58
59 /*
60 * fight:
61 * The player attacks the monster.
62 */
63 int
64 fight(const coord *mp, const THING *weap, int thrown)
65 {
66 THING *tp;
67 int did_hit = TRUE;
68 const char *mname;
69 int ch;
70
71 /*
72 * Find the monster we want to fight
73 */
74 if ((tp = moat(mp->y, mp->x)) == NULL)
75 {
76 #ifdef MASTER
77 debug("Fight what @ %d,%d", mp->y, mp->x);
78 #endif
79 return FALSE;
80 }
81 /*
82 * Since we are fighting, things are not quiet so no healing takes
83 * place.
84 */
85 count = 0;
86 quiet = 0;
87 runto(mp);
88 /*
89 * Let him know it was really a xeroc (if it was one).
90 */
91 ch = '\0';
92 if (tp->t_type == 'X' && tp->t_disguise != 'X' && !on(player, ISBLIND))
93 {
94 tp->t_disguise = 'X';
95 if (on(player, ISHALU)) {
96 ch = rnd(26) + 'A';
97 mvaddch(tp->t_pos.y, tp->t_pos.x, ch);
98 }
99 msg(choose_str("heavy! That's a nasty critter!",
100 "wait! That's a xeroc!"));
101 if (!thrown)
102 return FALSE;
103 }
104 mname = set_mname(tp);
105 did_hit = FALSE;
106 has_hit = (terse && !to_death);
107 if (roll_em(&player, tp, weap, thrown))
108 {
109 did_hit = FALSE;
110 if (thrown)
111 thunk(weap, mname, terse);
112 else
113 hit(NULL, mname, terse);
114 if (on(player, CANHUH))
115 {
116 did_hit = TRUE;
117 tp->t_flags |= ISHUH;
118 player.t_flags &= ~CANHUH;
119 endmsg();
120 has_hit = FALSE;
121 msg("your hands stop glowing %s", pick_color("red"));
122 }
123 if (tp->t_stats.s_hpt <= 0)
124 killed(tp, TRUE);
125 else if (did_hit && !on(player, ISBLIND))
126 msg("%s appears confused", mname);
127 did_hit = TRUE;
128 }
129 else
130 if (thrown)
131 bounce(weap, mname, terse);
132 else
133 miss(NULL, mname, terse);
134 return did_hit;
135 }
136
137 /*
138 * attack:
139 * The monster attacks the player
140 */
141 int
142 attack(THING *mp)
143 {
144 const char *mname;
145 int oldhp;
146
147 /*
148 * Since this is an attack, stop running and any healing that was
149 * going on at the time.
150 */
151 running = FALSE;
152 count = 0;
153 quiet = 0;
154 if (to_death && !on(*mp, ISTARGET))
155 {
156 to_death = FALSE;
157 kamikaze = FALSE;
158 }
159 if (mp->t_type == 'X' && mp->t_disguise != 'X' && !on(player, ISBLIND))
160 {
161 mp->t_disguise = 'X';
162 if (on(player, ISHALU))
163 mvaddch(mp->t_pos.y, mp->t_pos.x, rnd(26) + 'A');
164 }
165 mname = set_mname(mp);
166 oldhp = pstats.s_hpt;
167 if (roll_em(mp, &player, NULL, FALSE))
168 {
169 if (mp->t_type != 'I')
170 {
171 if (has_hit)
172 addmsg(". ");
173 hit(mname, NULL, FALSE);
174 }
175 else
176 if (has_hit)
177 endmsg();
178 has_hit = FALSE;
179 if (pstats.s_hpt <= 0)
180 death(mp->t_type); /* Bye bye life ... */
181 else if (!kamikaze)
182 {
183 oldhp -= pstats.s_hpt;
184 if (oldhp > max_hit)
185 max_hit = oldhp;
186 if (pstats.s_hpt <= max_hit)
187 to_death = FALSE;
188 }
189 if (!on(*mp, ISCANC))
190 switch (mp->t_type)
191 {
192 case 'A':
193 /*
194 * If an aquator hits, you can lose armor class.
195 */
196 rust_armor(cur_armor);
197 when 'I':
198 /*
199 * The ice monster freezes you
200 */
201 player.t_flags &= ~ISRUN;
202 if (!no_command)
203 {
204 addmsg("you are frozen");
205 if (!terse)
206 addmsg(" by the %s", mname);
207 endmsg();
208 }
209 no_command += rnd(2) + 2;
210 if (no_command > BORE_LEVEL)
211 death('h');
212 when 'R':
213 /*
214 * Rattlesnakes have poisonous bites
215 */
216 if (!save(VS_POISON))
217 {
218 if (!ISWEARING(R_SUSTSTR))
219 {
220 chg_str(-1);
221 if (!terse)
222 msg("you feel a bite in your leg and now feel weaker");
223 else
224 msg("a bite has weakened you");
225 }
226 else if (!to_death)
227 {
228 if (!terse)
229 msg("a bite momentarily weakens you");
230 else
231 msg("bite has no effect");
232 }
233 }
234 when 'W':
235 case 'V':
236 /*
237 * Wraiths might drain energy levels, and Vampires
238 * can steal max_hp
239 */
240 if (rnd(100) < (mp->t_type == 'W' ? 15 : 30))
241 {
242 int fewer;
243
244 if (mp->t_type == 'W')
245 {
246 if (pstats.s_exp == 0)
247 death('W'); /* All levels gone */
248 if (--pstats.s_lvl == 0)
249 {
250 pstats.s_exp = 0;
251 pstats.s_lvl = 1;
252 }
253 else
254 pstats.s_exp = e_levels[pstats.s_lvl-1]+1;
255 fewer = roll(1, 10);
256 }
257 else
258 fewer = roll(1, 3);
259 pstats.s_hpt -= fewer;
260 max_hp -= fewer;
261 if (pstats.s_hpt <= 0)
262 pstats.s_hpt = 1;
263 if (max_hp <= 0)
264 death(mp->t_type);
265 msg("you suddenly feel weaker");
266 }
267 when 'F':
268 /*
269 * Venus Flytrap stops the poor guy from moving
270 */
271 player.t_flags |= ISHELD;
272 sprintf(monsters['F'-'A'].m_stats.s_dmg,"%dx1", ++vf_hit);
273 if (--pstats.s_hpt <= 0)
274 death('F');
275 when 'L':
276 {
277 /*
278 * Leperachaun steals some gold
279 */
280 int lastpurse;
281
282 lastpurse = purse;
283 purse -= GOLDCALC;
284 if (!save(VS_MAGIC))
285 purse -= GOLDCALC + GOLDCALC + GOLDCALC + GOLDCALC;
286 if (purse < 0)
287 purse = 0;
288 remove_mon(&mp->t_pos, mp, FALSE);
289 mp=NULL;
290 if (purse != lastpurse)
291 msg("your purse feels lighter");
292 }
293 when 'N':
294 {
295 THING *obj, *steal;
296 int nobj;
297
298 /*
299 * Nymph's steal a magic item, look through the pack
300 * and pick out one we like.
301 */
302 steal = NULL;
303 for (nobj = 0, obj = pack; obj != NULL; obj = next(obj))
304 if (obj != cur_armor && obj != cur_weapon
305 && obj != cur_ring[LEFT] && obj != cur_ring[RIGHT]
306 && is_magic(obj) && rnd(++nobj) == 0)
307 steal = obj;
308 if (steal != NULL)
309 {
310 remove_mon(&mp->t_pos, moat(mp->t_pos.y, mp->t_pos.x), FALSE);
311 mp=NULL;
312 steal = leave_pack(steal, TRUE, FALSE);
313 msg("she stole %s!", inv_name(steal, TRUE));
314 discard(steal);
315 }
316 }
317 otherwise:
318 break;
319 }
320 }
321 else if (mp->t_type != 'I')
322 {
323 if (has_hit)
324 {
325 addmsg(". ");
326 has_hit = FALSE;
327 }
328 if (mp->t_type == 'F')
329 {
330 pstats.s_hpt -= vf_hit;
331 if (pstats.s_hpt <= 0)
332 death(mp->t_type); /* Bye bye life ... */
333 }
334 miss(mname, NULL, FALSE);
335 }
336 if (fight_flush && !to_death)
337 flush_type();
338 count = 0;
339 status();
340 if (mp == NULL)
341 return(-1);
342 else
343 return(0);
344 }
345
346 /*
347 * set_mname:
348 * return the monster name for the given monster
349 */
350 const char *
351 set_mname(const THING *tp)
352 {
353 int ch;
354 const char *mname;
355 static char tbuf[MAXSTR] = { 't', 'h', 'e', ' ' };
356
357 if (!see_monst(tp) && !on(player, SEEMONST))
358 return (terse ? "it" : "something");
359 else if (on(player, ISHALU))
360 {
361 move(tp->t_pos.y, tp->t_pos.x);
362 ch = toascii(CCHAR(inch()));
363 if (!isupper(ch))
364 ch = rnd(26);
365 else
366 ch -= 'A';
367 mname = monsters[ch].m_name;
368 }
369 else
370 mname = monsters[tp->t_type - 'A'].m_name;
371 strcpy(&tbuf[4], mname);
372 return tbuf;
373 }
374
375 /*
376 * swing:
377 * Returns true if the swing hits
378 */
379 int
380 swing(int at_lvl, int op_arm, int wplus)
381 {
382 int res = rnd(20);
383 int need = (20 - at_lvl) - op_arm;