date and time created 88/07/22 16:08:01 by bostic
[unix-history] / usr / src / games / rogue / hit.c
CommitLineData
b3afadef
KB
1/*
2 * hit.c
3 *
4 * This source herein may be modified and/or distributed by anybody who
5 * so desires, with the following restrictions:
6 * 1.) No portion of this notice shall be removed.
7 * 2.) Credit shall not be taken for the creation of this source.
8 * 3.) This code is not to be traded, sold, or used for personal
9 * gain or profit.
10 *
11 */
12
13#ifndef lint
14static char sccsid[] = "@(#)hit.c 5.1 (Berkeley) %G%";
15#endif /* not lint */
16
17#include "rogue.h"
18
19object *fight_monster = 0;
20char hit_message[80] = "";
21
22extern short halluc, blind, cur_level;
23extern short add_strength, ring_exp, r_rings;
24extern boolean being_held, interrupted, wizard, con_mon;
25
26mon_hit(monster)
27register object *monster;
28{
29 short damage, hit_chance;
30 char *mn;
31 float minus;
32
33 if (fight_monster && (monster != fight_monster)) {
34 fight_monster = 0;
35 }
36 monster->trow = NO_ROOM;
37 if (cur_level >= (AMULET_LEVEL * 2)) {
38 hit_chance = 100;
39 } else {
40 hit_chance = monster->m_hit_chance;
41 hit_chance -= (((2 * rogue.exp) + (2 * ring_exp)) - r_rings);
42 }
43 if (wizard) {
44 hit_chance /= 2;
45 }
46 if (!fight_monster) {
47 interrupted = 1;
48 }
49 mn = mon_name(monster);
50
51 if (!rand_percent(hit_chance)) {
52 if (!fight_monster) {
53 sprintf(hit_message + strlen(hit_message), "the %s misses", mn);
54 message(hit_message, 1);
55 hit_message[0] = 0;
56 }
57 return;
58 }
59 if (!fight_monster) {
60 sprintf(hit_message + strlen(hit_message), "the %s hit", mn);
61 message(hit_message, 1);
62 hit_message[0] = 0;
63 }
64 if (!(monster->m_flags & STATIONARY)) {
65 damage = get_damage(monster->m_damage, 1);
66 if (cur_level >= (AMULET_LEVEL * 2)) {
67 minus = (float) ((AMULET_LEVEL * 2) - cur_level);
68 } else {
69 minus = (float) get_armor_class(rogue.armor) * 3.00;
70 minus = minus/100.00 * (float) damage;
71 }
72 damage -= (short) minus;
73 } else {
74 damage = monster->stationary_damage++;
75 }
76 if (wizard) {
77 damage /= 3;
78 }
79 if (damage > 0) {
80 rogue_damage(damage, monster, 0);
81 }
82 if (monster->m_flags & SPECIAL_HIT) {
83 special_hit(monster);
84 }
85}
86
87rogue_hit(monster, force_hit)
88register object *monster;
89boolean force_hit;
90{
91 short damage, hit_chance;
92
93 if (monster) {
94 if (check_imitator(monster)) {
95 return;
96 }
97 hit_chance = force_hit ? 100 : get_hit_chance(rogue.weapon);
98
99 if (wizard) {
100 hit_chance *= 2;
101 }
102 if (!rand_percent(hit_chance)) {
103 if (!fight_monster) {
104 (void) strcpy(hit_message, "you miss ");
105 }
106 goto RET;
107 }
108 damage = get_weapon_damage(rogue.weapon);
109 if (wizard) {
110 damage *= 3;
111 }
112 if (con_mon) {
113 s_con_mon(monster);
114 }
115 if (mon_damage(monster, damage)) { /* still alive? */
116 if (!fight_monster) {
117 (void) strcpy(hit_message, "you hit ");
118 }
119 }
120RET: check_gold_seeker(monster);
121 wake_up(monster);
122 }
123}
124
125rogue_damage(d, monster, other)
126short d;
127object *monster;
128short other;
129{
130 if (d >= rogue.hp_current) {
131 rogue.hp_current = 0;
132 print_stats(STAT_HP);
133 killed_by(monster, other);
134 }
135 if (d > 0) {
136 rogue.hp_current -= d;
137 print_stats(STAT_HP);
138 }
139}
140
141get_damage(ds, r)
142char *ds;
143boolean r;
144{
145 register i = 0, j, n, d, total = 0;
146
147 while (ds[i]) {
148 n = get_number(ds+i);
149 while (ds[i++] != 'd') ;
150 d = get_number(ds+i);
151 while ((ds[i] != '/') && ds[i]) i++;
152
153 for (j = 0; j < n; j++) {
154 if (r) {
155 total += get_rand(1, d);
156 } else {
157 total += d;
158 }
159 }
160 if (ds[i] == '/') {
161 i++;
162 }
163 }
164 return(total);
165}
166
167get_w_damage(obj)
168object *obj;
169{
170 char new_damage[12];
171 register to_hit, damage;
172 register i = 0;
173
174 if ((!obj) || (obj->what_is != WEAPON)) {
175 return(-1);
176 }
177 to_hit = get_number(obj->damage) + obj->hit_enchant;
178 while (obj->damage[i++] != 'd') ;
179 damage = get_number(obj->damage + i) + obj->d_enchant;
180
181 sprintf(new_damage, "%dd%d", to_hit, damage);
182
183 return(get_damage(new_damage, 1));
184}
185
186get_number(s)
187register char *s;
188{
189 register i = 0;
190 register total = 0;
191
192 while ((s[i] >= '0') && (s[i] <= '9')) {
193 total = (10 * total) + (s[i] - '0');
194 i++;
195 }
196 return(total);
197}
198
199long
200lget_number(s)
201char *s;
202{
203 short i = 0;
204 long total = 0;
205
206 while ((s[i] >= '0') && (s[i] <= '9')) {
207 total = (10 * total) + (s[i] - '0');
208 i++;
209 }
210 return(total);
211}
212
213to_hit(obj)
214object *obj;
215{
216 if (!obj) {
217 return(1);
218 }
219 return(get_number(obj->damage) + obj->hit_enchant);
220}
221
222damage_for_strength()
223{
224 short strength;
225
226 strength = rogue.str_current + add_strength;
227
228 if (strength <= 6) {
229 return(strength-5);
230 }
231 if (strength <= 14) {
232 return(1);
233 }
234 if (strength <= 17) {
235 return(3);
236 }
237 if (strength <= 18) {
238 return(4);
239 }
240 if (strength <= 20) {
241 return(5);
242 }
243 if (strength <= 21) {
244 return(6);
245 }
246 if (strength <= 30) {
247 return(7);
248 }
249 return(8);
250}
251
252mon_damage(monster, damage)
253object *monster;
254short damage;
255{
256 char *mn;
257 short row, col;
258
259 monster->hp_to_kill -= damage;
260
261 if (monster->hp_to_kill <= 0) {
262 row = monster->row;
263 col = monster->col;
264 dungeon[row][col] &= ~MONSTER;
265 mvaddch(row, col, (int) get_dungeon_char(row, col));
266
267 fight_monster = 0;
268 cough_up(monster);
269 mn = mon_name(monster);
270 sprintf(hit_message+strlen(hit_message), "defeated the %s", mn);
271 message(hit_message, 1);
272 hit_message[0] = 0;
273 add_exp(monster->kill_exp, 1);
274 take_from_pack(monster, &level_monsters);
275
276 if (monster->m_flags & HOLDS) {
277 being_held = 0;
278 }
279 free_object(monster);
280 return(0);
281 }
282 return(1);
283}
284
285fight(to_the_death)
286boolean to_the_death;
287{
288 short ch, c, d;
289 short row, col;
290 boolean first_miss = 1;
291 short possible_damage;
292 object *monster;
293
294 while (!is_direction(ch = rgetchar(), &d)) {
295 sound_bell();
296 if (first_miss) {
297 message("direction?", 0);
298 first_miss = 0;
299 }
300 }
301 check_message();
302 if (ch == CANCEL) {
303 return;
304 }
305 row = rogue.row; col = rogue.col;
306 get_dir_rc(d, &row, &col, 0);
307
308 c = mvinch(row, col);
309 if (((c < 'A') || (c > 'Z')) ||
310 (!can_move(rogue.row, rogue.col, row, col))) {
311 message("I see no monster there", 0);
312 return;
313 }
314 if (!(fight_monster = object_at(&level_monsters, row, col))) {
315 return;
316 }
317 if (!(fight_monster->m_flags & STATIONARY)) {
318 possible_damage = ((get_damage(fight_monster->m_damage, 0) * 2) / 3);
319 } else {
320 possible_damage = fight_monster->stationary_damage - 1;
321 }
322 while (fight_monster) {
323 (void) one_move_rogue(ch, 0);
324 if (((!to_the_death) && (rogue.hp_current <= possible_damage)) ||
325 interrupted || (!(dungeon[row][col] & MONSTER))) {
326 fight_monster = 0;
327 } else {
328 monster = object_at(&level_monsters, row, col);
329 if (monster != fight_monster) {
330 fight_monster = 0;
331 }
332 }
333 }
334}
335
336get_dir_rc(dir, row, col, allow_off_screen)
337short dir;
338short *row, *col;
339short allow_off_screen;
340{
341 switch(dir) {
342 case LEFT:
343 if (allow_off_screen || (*col > 0)) {
344 (*col)--;
345 }
346 break;
347 case DOWN:
348 if (allow_off_screen || (*row < (DROWS-2))) {
349 (*row)++;
350 }
351 break;
352 case UPWARD:
353 if (allow_off_screen || (*row > MIN_ROW)) {
354 (*row)--;
355 }
356 break;
357 case RIGHT:
358 if (allow_off_screen || (*col < (DCOLS-1))) {
359 (*col)++;
360 }
361 break;
362 case UPLEFT:
363 if (allow_off_screen || ((*row > MIN_ROW) && (*col > 0))) {
364 (*row)--;
365 (*col)--;
366 }
367 break;
368 case UPRIGHT:
369 if (allow_off_screen || ((*row > MIN_ROW) && (*col < (DCOLS-1)))) {
370 (*row)--;
371 (*col)++;
372 }
373 break;
374 case DOWNRIGHT:
375 if (allow_off_screen || ((*row < (DROWS-2)) && (*col < (DCOLS-1)))) {
376 (*row)++;
377 (*col)++;
378 }
379 break;
380 case DOWNLEFT:
381 if (allow_off_screen || ((*row < (DROWS-2)) && (*col > 0))) {
382 (*row)++;
383 (*col)--;
384 }
385 break;
386 }
387}
388
389get_hit_chance(weapon)
390object *weapon;
391{
392 short hit_chance;
393
394 hit_chance = 40;
395 hit_chance += 3 * to_hit(weapon);
396 hit_chance += (((2 * rogue.exp) + (2 * ring_exp)) - r_rings);
397 return(hit_chance);
398}
399
400get_weapon_damage(weapon)
401object *weapon;
402{
403 short damage;
404
405 damage = get_w_damage(weapon);
406 damage += damage_for_strength();
407 damage += ((((rogue.exp + ring_exp) - r_rings) + 1) / 2);
408 return(damage);
409}
410
411s_con_mon(monster)
412object *monster;
413{
414 if (con_mon) {
415 monster->m_flags |= CONFUSED;
416 monster->moves_confused += get_rand(12, 22);
417 message("the monster appears confused", 0);
418 con_mon = 0;
419 }
420}