]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - rogue/hit.c
mark non-returning functions (PR#6144 by Joseph Myers <jsm28@cam.ac.uk>)
[bsdgames-darwin.git] / rogue / hit.c
1 /* $NetBSD: hit.c,v 1.4 1997/10/12 11:45:05 lukem Exp $ */
2
3 /*
4 * Copyright (c) 1988, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Timothy C. Stoehr.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 */
38
39 #include <sys/cdefs.h>
40 #ifndef lint
41 #if 0
42 static char sccsid[] = "@(#)hit.c 8.1 (Berkeley) 5/31/93";
43 #else
44 __RCSID("$NetBSD: hit.c,v 1.4 1997/10/12 11:45:05 lukem Exp $");
45 #endif
46 #endif /* not lint */
47
48 /*
49 * hit.c
50 *
51 * This source herein may be modified and/or distributed by anybody who
52 * so desires, with the following restrictions:
53 * 1.) No portion of this notice shall be removed.
54 * 2.) Credit shall not be taken for the creation of this source.
55 * 3.) This code is not to be traded, sold, or used for personal
56 * gain or profit.
57 *
58 */
59
60 #include "rogue.h"
61
62 object *fight_monster = 0;
63 char hit_message[80] = "";
64
65 void
66 mon_hit(monster)
67 object *monster;
68 {
69 short damage, hit_chance;
70 char *mn;
71 float minus;
72
73 if (fight_monster && (monster != fight_monster)) {
74 fight_monster = 0;
75 }
76 monster->trow = NO_ROOM;
77 if (cur_level >= (AMULET_LEVEL * 2)) {
78 hit_chance = 100;
79 } else {
80 hit_chance = monster->m_hit_chance;
81 hit_chance -= (((2 * rogue.exp) + (2 * ring_exp)) - r_rings);
82 }
83 if (wizard) {
84 hit_chance /= 2;
85 }
86 if (!fight_monster) {
87 interrupted = 1;
88 }
89 mn = mon_name(monster);
90
91 if (!rand_percent(hit_chance)) {
92 if (!fight_monster) {
93 sprintf(hit_message + strlen(hit_message),
94 "the %s misses", mn);
95 message(hit_message, 1);
96 hit_message[0] = 0;
97 }
98 return;
99 }
100 if (!fight_monster) {
101 sprintf(hit_message + strlen(hit_message), "the %s hit", mn);
102 message(hit_message, 1);
103 hit_message[0] = 0;
104 }
105 if (!(monster->m_flags & STATIONARY)) {
106 damage = get_damage(monster->m_damage, 1);
107 if (cur_level >= (AMULET_LEVEL * 2)) {
108 minus = (float) ((AMULET_LEVEL * 2) - cur_level);
109 } else {
110 minus = (float) get_armor_class(rogue.armor) * 3.00;
111 minus = minus/100.00 * (float) damage;
112 }
113 damage -= (short) minus;
114 } else {
115 damage = monster->stationary_damage++;
116 }
117 if (wizard) {
118 damage /= 3;
119 }
120 if (damage > 0) {
121 rogue_damage(damage, monster, 0);
122 }
123 if (monster->m_flags & SPECIAL_HIT) {
124 special_hit(monster);
125 }
126 }
127
128 void
129 rogue_hit(monster, force_hit)
130 object *monster;
131 boolean force_hit;
132 {
133 short damage, hit_chance;
134
135 if (monster) {
136 if (check_imitator(monster)) {
137 return;
138 }
139 hit_chance = force_hit ? 100 : get_hit_chance(rogue.weapon);
140
141 if (wizard) {
142 hit_chance *= 2;
143 }
144 if (!rand_percent(hit_chance)) {
145 if (!fight_monster) {
146 (void) strcpy(hit_message, "you miss ");
147 }
148 goto RET;
149 }
150 damage = get_weapon_damage(rogue.weapon);
151 if (wizard) {
152 damage *= 3;
153 }
154 if (con_mon) {
155 s_con_mon(monster);
156 }
157 if (mon_damage(monster, damage)) { /* still alive? */
158 if (!fight_monster) {
159 (void) strcpy(hit_message, "you hit ");
160 }
161 }
162 RET: check_gold_seeker(monster);
163 wake_up(monster);
164 }
165 }
166
167 void
168 rogue_damage(d, monster, other)
169 short d;
170 object *monster;
171 short other;
172 {
173 if (d >= rogue.hp_current) {
174 rogue.hp_current = 0;
175 print_stats(STAT_HP);
176 killed_by(monster, other);
177 }
178 if (d > 0) {
179 rogue.hp_current -= d;
180 print_stats(STAT_HP);
181 }
182 }
183
184 int
185 get_damage(ds, r)
186 char *ds;
187 boolean r;
188 {
189 int i = 0, j, n, d, total = 0;
190
191 while (ds[i]) {
192 n = get_number(ds+i);
193 while (ds[i++] != 'd') ;
194 d = get_number(ds+i);
195 while ((ds[i] != '/') && ds[i]) i++;
196
197 for (j = 0; j < n; j++) {
198 if (r) {
199 total += get_rand(1, d);
200 } else {
201 total += d;
202 }
203 }
204 if (ds[i] == '/') {
205 i++;
206 }
207 }
208 return(total);
209 }
210
211 int
212 get_w_damage(obj)
213 object *obj;
214 {
215 char new_damage[12];
216 int to_hit, damage;
217 int i = 0;
218
219 if ((!obj) || (obj->what_is != WEAPON)) {
220 return(-1);
221 }
222 to_hit = get_number(obj->damage) + obj->hit_enchant;
223 while (obj->damage[i++] != 'd') ;
224 damage = get_number(obj->damage + i) + obj->d_enchant;
225
226 sprintf(new_damage, "%dd%d", to_hit, damage);
227
228 return(get_damage(new_damage, 1));
229 }
230
231 int
232 get_number(s)
233 char *s;
234 {
235 int i = 0;
236 int total = 0;
237
238 while ((s[i] >= '0') && (s[i] <= '9')) {
239 total = (10 * total) + (s[i] - '0');
240 i++;
241 }
242 return(total);
243 }
244
245 long
246 lget_number(s)
247 char *s;
248 {
249 short i = 0;
250 long total = 0;
251
252 while ((s[i] >= '0') && (s[i] <= '9')) {
253 total = (10 * total) + (s[i] - '0');
254 i++;
255 }
256 return(total);
257 }
258
259 int
260 to_hit(obj)
261 object *obj;
262 {
263 if (!obj) {
264 return(1);
265 }
266 return(get_number(obj->damage) + obj->hit_enchant);
267 }
268
269 int
270 damage_for_strength()
271 {
272 short strength;
273
274 strength = rogue.str_current + add_strength;
275
276 if (strength <= 6) {
277 return(strength-5);
278 }
279 if (strength <= 14) {
280 return(1);
281 }
282 if (strength <= 17) {
283 return(3);
284 }
285 if (strength <= 18) {
286 return(4);
287 }
288 if (strength <= 20) {
289 return(5);
290 }
291 if (strength <= 21) {
292 return(6);
293 }
294 if (strength <= 30) {
295 return(7);
296 }
297 return(8);
298 }
299
300 int
301 mon_damage(monster, damage)
302 object *monster;
303 short damage;
304 {
305 char *mn;
306 short row, col;
307
308 monster->hp_to_kill -= damage;
309
310 if (monster->hp_to_kill <= 0) {
311 row = monster->row;
312 col = monster->col;
313 dungeon[row][col] &= ~MONSTER;
314 mvaddch(row, col, (int) get_dungeon_char(row, col));
315
316 fight_monster = 0;
317 cough_up(monster);
318 mn = mon_name(monster);
319 sprintf(hit_message+strlen(hit_message), "defeated the %s", mn);
320 message(hit_message, 1);
321 hit_message[0] = 0;
322 add_exp(monster->kill_exp, 1);
323 take_from_pack(monster, &level_monsters);
324
325 if (monster->m_flags & HOLDS) {
326 being_held = 0;
327 }
328 free_object(monster);
329 return(0);
330 }
331 return(1);
332 }
333
334 void
335 fight(to_the_death)
336 boolean to_the_death;
337 {
338 short ch, c, d;
339 short row, col;
340 boolean first_miss = 1;
341 short possible_damage;
342 object *monster;
343
344 ch = 0;
345 while (!is_direction(ch = rgetchar(), &d)) {
346 sound_bell();
347 if (first_miss) {
348 message("direction?", 0);
349 first_miss = 0;
350 }
351 }
352 check_message();
353 if (ch == CANCEL) {
354 return;
355 }
356 row = rogue.row; col = rogue.col;
357 get_dir_rc(d, &row, &col, 0);
358
359 c = mvinch(row, col);
360 if (((c < 'A') || (c > 'Z')) ||
361 (!can_move(rogue.row, rogue.col, row, col))) {
362 message("I see no monster there", 0);
363 return;
364 }
365 if (!(fight_monster = object_at(&level_monsters, row, col))) {
366 return;
367 }
368 if (!(fight_monster->m_flags & STATIONARY)) {
369 possible_damage = ((get_damage(fight_monster->m_damage, 0) * 2) / 3);
370 } else {
371 possible_damage = fight_monster->stationary_damage - 1;
372 }
373 while (fight_monster) {
374 (void) one_move_rogue(ch, 0);
375 if (((!to_the_death) && (rogue.hp_current <= possible_damage)) ||
376 interrupted || (!(dungeon[row][col] & MONSTER))) {
377 fight_monster = 0;
378 } else {
379 monster = object_at(&level_monsters, row, col);
380 if (monster != fight_monster) {
381 fight_monster = 0;
382 }
383 }
384 }
385 }
386
387 void
388 get_dir_rc(dir, row, col, allow_off_screen)
389 short dir;
390 short *row, *col;
391 short allow_off_screen;
392 {
393 switch(dir) {
394 case LEFT:
395 if (allow_off_screen || (*col > 0)) {
396 (*col)--;
397 }
398 break;
399 case DOWN:
400 if (allow_off_screen || (*row < (DROWS-2))) {
401 (*row)++;
402 }
403 break;
404 case UPWARD:
405 if (allow_off_screen || (*row > MIN_ROW)) {
406 (*row)--;
407 }
408 break;
409 case RIGHT:
410 if (allow_off_screen || (*col < (DCOLS-1))) {
411 (*col)++;
412 }
413 break;
414 case UPLEFT:
415 if (allow_off_screen || ((*row > MIN_ROW) && (*col > 0))) {
416 (*row)--;
417 (*col)--;
418 }
419 break;
420 case UPRIGHT:
421 if (allow_off_screen || ((*row > MIN_ROW) && (*col < (DCOLS-1)))) {
422 (*row)--;
423 (*col)++;
424 }
425 break;
426 case DOWNRIGHT:
427 if (allow_off_screen || ((*row < (DROWS-2)) && (*col < (DCOLS-1)))) {
428 (*row)++;
429 (*col)++;
430 }
431 break;
432 case DOWNLEFT:
433 if (allow_off_screen || ((*row < (DROWS-2)) && (*col > 0))) {
434 (*row)++;
435 (*col)--;
436 }
437 break;
438 }
439 }
440
441 int
442 get_hit_chance(weapon)
443 object *weapon;
444 {
445 short hit_chance;
446
447 hit_chance = 40;
448 hit_chance += 3 * to_hit(weapon);
449 hit_chance += (((2 * rogue.exp) + (2 * ring_exp)) - r_rings);
450 return(hit_chance);
451 }
452
453 int
454 get_weapon_damage(weapon)
455 object *weapon;
456 {
457 short damage;
458
459 damage = get_w_damage(weapon);
460 damage += damage_for_strength();
461 damage += ((((rogue.exp + ring_exp) - r_rings) + 1) / 2);
462 return(damage);
463 }
464
465 void
466 s_con_mon(monster)
467 object *monster;
468 {
469 if (con_mon) {
470 monster->m_flags |= CONFUSED;
471 monster->moves_confused += get_rand(12, 22);
472 message("the monster appears confused", 0);
473 con_mon = 0;
474 }
475 }