Sync usage with man page.
[netbsd-mini2440.git] / games / rogue / hit.c
blobe4d3d50f9375862403d99788eaacd9c3c235fb31
1 /* $NetBSD: hit.c,v 1.9 2008/01/14 00:23:51 dholland Exp $ */
3 /*
4 * Copyright (c) 1988, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * Timothy C. Stoehr.
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. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
35 #include <sys/cdefs.h>
36 #ifndef lint
37 #if 0
38 static char sccsid[] = "@(#)hit.c 8.1 (Berkeley) 5/31/93";
39 #else
40 __RCSID("$NetBSD: hit.c,v 1.9 2008/01/14 00:23:51 dholland Exp $");
41 #endif
42 #endif /* not lint */
45 * hit.c
47 * This source herein may be modified and/or distributed by anybody who
48 * so desires, with the following restrictions:
49 * 1.) No portion of this notice shall be removed.
50 * 2.) Credit shall not be taken for the creation of this source.
51 * 3.) This code is not to be traded, sold, or used for personal
52 * gain or profit.
56 #include "rogue.h"
58 static int damage_for_strength(void);
59 static int get_w_damage(const object *);
60 static int to_hit(const object *);
62 static object *fight_monster = NULL;
63 char hit_message[HIT_MESSAGE_SIZE] = "";
65 void
66 mon_hit(object *monster)
68 short damage, hit_chance;
69 const char *mn;
70 float minus;
72 if (fight_monster && (monster != fight_monster)) {
73 fight_monster = 0;
75 monster->trow = NO_ROOM;
76 if (cur_level >= (AMULET_LEVEL * 2)) {
77 hit_chance = 100;
78 } else {
79 hit_chance = monster->m_hit_chance;
80 hit_chance -= (((2 * rogue.exp) + (2 * ring_exp)) - r_rings);
82 if (wizard) {
83 hit_chance /= 2;
85 if (!fight_monster) {
86 interrupted = 1;
88 mn = mon_name(monster);
90 if (!rand_percent(hit_chance)) {
91 if (!fight_monster) {
92 messagef(1, "%sthe %s misses", hit_message, mn);
93 hit_message[0] = 0;
95 return;
97 if (!fight_monster) {
98 messagef(1, "%sthe %s hit", hit_message, mn);
99 hit_message[0] = 0;
101 if (!(monster->m_flags & STATIONARY)) {
102 damage = get_damage(monster->m_damage, 1);
103 if (cur_level >= (AMULET_LEVEL * 2)) {
104 minus = (float)((AMULET_LEVEL * 2) - cur_level);
105 } else {
106 minus = (float)get_armor_class(rogue.armor) * 3.00;
107 minus = minus/100.00 * (float)damage;
109 damage -= (short)minus;
110 } else {
111 damage = monster->stationary_damage++;
113 if (wizard) {
114 damage /= 3;
116 if (damage > 0) {
117 rogue_damage(damage, monster, 0);
119 if (monster->m_flags & SPECIAL_HIT) {
120 special_hit(monster);
124 void
125 rogue_hit(object *monster, boolean force_hit)
127 short damage, hit_chance;
129 if (monster) {
130 if (check_imitator(monster)) {
131 return;
133 hit_chance = force_hit ? 100 : get_hit_chance(rogue.weapon);
135 if (wizard) {
136 hit_chance *= 2;
138 if (!rand_percent(hit_chance)) {
139 if (!fight_monster) {
140 (void)strlcpy(hit_message, "you miss ",
141 sizeof(hit_message));
143 goto RET;
145 damage = get_weapon_damage(rogue.weapon);
146 if (wizard) {
147 damage *= 3;
149 if (con_mon) {
150 s_con_mon(monster);
152 if (mon_damage(monster, damage)) { /* still alive? */
153 if (!fight_monster) {
154 (void)strlcpy(hit_message, "you hit ",
155 sizeof(hit_message));
158 RET: check_gold_seeker(monster);
159 wake_up(monster);
163 void
164 rogue_damage(short d, object *monster, short other)
166 if (d >= rogue.hp_current) {
167 rogue.hp_current = 0;
168 print_stats(STAT_HP);
169 killed_by(monster, other);
171 if (d > 0) {
172 rogue.hp_current -= d;
173 print_stats(STAT_HP);
178 get_damage(const char *ds, boolean r)
180 int i = 0, j, n, d, total = 0;
182 while (ds[i]) {
183 n = get_number(ds+i);
184 while ((ds[i] != 'd') && ds[i]) {
185 i++;
187 if (ds[i] == 'd') {
188 i++;
191 d = get_number(ds+i);
192 while ((ds[i] != '/') && ds[i]) {
193 i++;
195 if (ds[i] == '/') {
196 i++;
199 for (j = 0; j < n; j++) {
200 if (r) {
201 total += get_rand(1, d);
202 } else {
203 total += d;
207 return(total);
210 static int
211 get_w_damage(const object *obj)
213 char new_damage[32];
214 int tmp_to_hit, tmp_damage;
215 int i = 0;
217 if ((!obj) || (obj->what_is != WEAPON)) {
218 return(-1);
220 tmp_to_hit = get_number(obj->damage) + obj->hit_enchant;
221 while ((obj->damage[i] != 'd') && obj->damage[i]) {
222 i++;
224 if (obj->damage[i] == 'd') {
225 i++;
227 tmp_damage = get_number(obj->damage + i) + obj->d_enchant;
229 snprintf(new_damage, sizeof(new_damage), "%dd%d",
230 tmp_to_hit, tmp_damage);
232 return(get_damage(new_damage, 1));
236 get_number(const char *s)
238 int i = 0;
239 int total = 0;
241 while ((s[i] >= '0') && (s[i] <= '9')) {
242 total = (10 * total) + (s[i] - '0');
243 i++;
245 return(total);
248 long
249 lget_number(const char *s)
251 short i = 0;
252 long total = 0;
254 while ((s[i] >= '0') && (s[i] <= '9')) {
255 total = (10 * total) + (s[i] - '0');
256 i++;
258 return(total);
261 static int
262 to_hit(const object *obj)
264 if (!obj) {
265 return(1);
267 return(get_number(obj->damage) + obj->hit_enchant);
270 static int
271 damage_for_strength(void)
273 short strength;
275 strength = rogue.str_current + add_strength;
277 if (strength <= 6) {
278 return(strength-5);
280 if (strength <= 14) {
281 return(1);
283 if (strength <= 17) {
284 return(3);
286 if (strength <= 18) {
287 return(4);
289 if (strength <= 20) {
290 return(5);
292 if (strength <= 21) {
293 return(6);
295 if (strength <= 30) {
296 return(7);
298 return(8);
302 mon_damage(object *monster, short damage)
304 const char *mn;
305 short row, col;
307 monster->hp_to_kill -= damage;
309 if (monster->hp_to_kill <= 0) {
310 row = monster->row;
311 col = monster->col;
312 dungeon[row][col] &= ~MONSTER;
313 mvaddch(row, col, get_dungeon_char(row, col));
315 fight_monster = 0;
316 cough_up(monster);
317 mn = mon_name(monster);
318 messagef(1, "%sdefeated the %s", hit_message, mn);
319 hit_message[0] = 0;
320 add_exp(monster->kill_exp, 1);
321 take_from_pack(monster, &level_monsters);
323 if (monster->m_flags & HOLDS) {
324 being_held = 0;
326 free_object(monster);
327 return(0);
329 return(1);
332 void
333 fight(boolean to_the_death)
335 short ch, c, d;
336 short row, col;
337 boolean first_miss = 1;
338 short possible_damage;
339 object *monster;
341 ch = 0;
342 while (!is_direction(ch = rgetchar(), &d)) {
343 sound_bell();
344 if (first_miss) {
345 messagef(0, "direction?");
346 first_miss = 0;
349 check_message();
350 if (ch == CANCEL) {
351 return;
353 row = rogue.row; col = rogue.col;
354 get_dir_rc(d, &row, &col, 0);
356 c = mvinch(row, col);
357 if (((c < 'A') || (c > 'Z')) ||
358 (!can_move(rogue.row, rogue.col, row, col))) {
359 messagef(0, "I see no monster there");
360 return;
362 if (!(fight_monster = object_at(&level_monsters, row, col))) {
363 return;
365 if (!(fight_monster->m_flags & STATIONARY)) {
366 possible_damage = ((get_damage(fight_monster->m_damage, 0) * 2) / 3);
367 } else {
368 possible_damage = fight_monster->stationary_damage - 1;
370 while (fight_monster) {
371 (void)one_move_rogue(ch, 0);
372 if (((!to_the_death) && (rogue.hp_current <= possible_damage)) ||
373 interrupted || (!(dungeon[row][col] & MONSTER))) {
374 fight_monster = 0;
375 } else {
376 monster = object_at(&level_monsters, row, col);
377 if (monster != fight_monster) {
378 fight_monster = 0;
384 void
385 get_dir_rc(short dir, short *row, short *col, short allow_off_screen)
387 switch(dir) {
388 case LEFT:
389 if (allow_off_screen || (*col > 0)) {
390 (*col)--;
392 break;
393 case DOWN:
394 if (allow_off_screen || (*row < (DROWS-2))) {
395 (*row)++;
397 break;
398 case UPWARD:
399 if (allow_off_screen || (*row > MIN_ROW)) {
400 (*row)--;
402 break;
403 case RIGHT:
404 if (allow_off_screen || (*col < (DCOLS-1))) {
405 (*col)++;
407 break;
408 case UPLEFT:
409 if (allow_off_screen || ((*row > MIN_ROW) && (*col > 0))) {
410 (*row)--;
411 (*col)--;
413 break;
414 case UPRIGHT:
415 if (allow_off_screen || ((*row > MIN_ROW) && (*col < (DCOLS-1)))) {
416 (*row)--;
417 (*col)++;
419 break;
420 case DOWNRIGHT:
421 if (allow_off_screen || ((*row < (DROWS-2)) && (*col < (DCOLS-1)))) {
422 (*row)++;
423 (*col)++;
425 break;
426 case DOWNLEFT:
427 if (allow_off_screen || ((*row < (DROWS-2)) && (*col > 0))) {
428 (*row)++;
429 (*col)--;
431 break;
436 get_hit_chance(const object *weapon)
438 short hit_chance;
440 hit_chance = 40;
441 hit_chance += 3 * to_hit(weapon);
442 hit_chance += (((2 * rogue.exp) + (2 * ring_exp)) - r_rings);
443 return(hit_chance);
447 get_weapon_damage(const object *weapon)
449 short damage;
451 damage = get_w_damage(weapon);
452 damage += damage_for_strength();
453 damage += ((((rogue.exp + ring_exp) - r_rings) + 1) / 2);
454 return(damage);
457 void
458 s_con_mon(object *monster)
460 if (con_mon) {
461 monster->m_flags |= CONFUSED;
462 monster->moves_confused += get_rand(12, 22);
463 messagef(0, "the monster appears confused");
464 con_mon = 0;