1 /* $NetBSD: spec_hit.c,v 1.7 2008/01/14 00:23:53 dholland Exp $ */
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
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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
35 #include <sys/cdefs.h>
38 static char sccsid
[] = "@(#)spec_hit.c 8.1 (Berkeley) 5/31/93";
40 __RCSID("$NetBSD: spec_hit.c,v 1.7 2008/01/14 00:23:53 dholland Exp $");
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
58 static void disappear(object
*);
59 static void drain_life(void);
60 static void drop_level(void);
61 static void freeze(object
*);
62 static int get_dir(short, short, short, short);
63 static boolean
gold_at(short, short);
64 static void steal_gold(object
*);
65 static void steal_item(object
*);
66 static void sting(object
*);
67 static boolean
try_to_cough(short, short, object
*);
73 special_hit(object
*monster
)
75 if ((monster
->m_flags
& CONFUSED
) && rand_percent(66)) {
78 if (monster
->m_flags
& RUSTS
) {
81 if ((monster
->m_flags
& HOLDS
) && !levitate
) {
84 if (monster
->m_flags
& FREEZES
) {
87 if (monster
->m_flags
& STINGS
) {
90 if (monster
->m_flags
& DRAINS_LIFE
) {
93 if (monster
->m_flags
& DROPS_LEVEL
) {
96 if (monster
->m_flags
& STEALS_GOLD
) {
98 } else if (monster
->m_flags
& STEALS_ITEM
) {
104 rust(object
*monster
)
106 if ((!rogue
.armor
) || (get_armor_class(rogue
.armor
) <= 1) ||
107 (rogue
.armor
->which_kind
== LEATHER
)) {
110 if ((rogue
.armor
->is_protected
) || maintain_armor
) {
111 if (monster
&& (!(monster
->m_flags
& RUST_VANISHED
))) {
112 messagef(0, "the rust vanishes instantly");
113 monster
->m_flags
|= RUST_VANISHED
;
116 rogue
.armor
->d_enchant
--;
117 messagef(0, "your armor weakens");
118 print_stats(STAT_ARMOR
);
123 freeze(object
*monster
)
125 short freeze_percent
= 99;
128 if (rand_percent(12)) {
131 freeze_percent
-= (rogue
.str_current
+(rogue
.str_current
/ 2));
132 freeze_percent
-= ((rogue
.exp
+ ring_exp
) * 4);
133 freeze_percent
-= (get_armor_class(rogue
.armor
) * 5);
134 freeze_percent
-= (rogue
.hp_max
/ 3);
136 if (freeze_percent
> 10) {
137 monster
->m_flags
|= FREEZING_ROGUE
;
138 messagef(1, "you are frozen");
141 for (i
= 0; i
< n
; i
++) {
144 if (rand_percent(freeze_percent
)) {
145 for (i
= 0; i
< 50; i
++) {
148 killed_by(NULL
, HYPOTHERMIA
);
150 messagef(1, you_can_move_again
);
151 monster
->m_flags
&= (~FREEZING_ROGUE
);
156 steal_gold(object
*monster
)
160 if ((rogue
.gold
<= 0) || rand_percent(10)) {
164 amount
= get_rand((cur_level
* 10), (cur_level
* 30));
166 if (amount
> rogue
.gold
) {
169 rogue
.gold
-= amount
;
170 messagef(0, "your purse feels lighter");
171 print_stats(STAT_GOLD
);
176 steal_item(object
*monster
)
181 boolean has_something
= 0;
183 if (rand_percent(15)) {
186 obj
= rogue
.pack
.next_object
;
192 if (!(obj
->in_use_flags
& BEING_USED
)) {
196 obj
= obj
->next_object
;
198 if (!has_something
) {
201 n
= get_rand(0, MAX_PACK_COUNT
);
202 obj
= rogue
.pack
.next_object
;
204 for (i
= 0; i
<= n
; i
++) {
205 obj
= obj
->next_object
;
206 while ((!obj
) || (obj
->in_use_flags
& BEING_USED
)) {
208 obj
= rogue
.pack
.next_object
;
210 obj
= obj
->next_object
;
214 if (obj
->what_is
!= WEAPON
) {
218 get_desc(obj
, desc
, sizeof(desc
));
219 messagef(0, "she stole %s", desc
);
221 obj
->quantity
= ((obj
->what_is
!= WEAPON
) ? t
: 1);
223 vanish(obj
, 0, &rogue
.pack
);
229 disappear(object
*monster
)
236 dungeon
[row
][col
] &= ~MONSTER
;
237 if (rogue_can_see(row
, col
)) {
238 mvaddch(row
, col
, get_dungeon_char(row
, col
));
240 take_from_pack(monster
, &level_monsters
);
241 free_object(monster
);
246 cough_up(object
*monster
)
249 short row
, col
, i
, n
;
251 if (cur_level
< max_level
) {
255 if (monster
->m_flags
& STEALS_GOLD
) {
256 obj
= alloc_object();
258 obj
->quantity
= get_rand((cur_level
* 15), (cur_level
* 30));
260 if (!rand_percent((int)monster
->drop_percent
)) {
268 for (n
= 0; n
<= 5; n
++) {
269 for (i
= -n
; i
<= n
; i
++) {
270 if (try_to_cough(row
+n
, col
+i
, obj
)) {
273 if (try_to_cough(row
-n
, col
+i
, obj
)) {
277 for (i
= -n
; i
<= n
; i
++) {
278 if (try_to_cough(row
+i
, col
-n
, obj
)) {
281 if (try_to_cough(row
+i
, col
+n
, obj
)) {
290 try_to_cough(short row
, short col
, object
*obj
)
292 if ((row
< MIN_ROW
) ||
293 (row
> (DROWS
-2)) || (col
< 0) || (col
>(DCOLS
-1))) {
296 if ((!(dungeon
[row
][col
] & (OBJECT
| STAIRS
| TRAP
))) &&
297 (dungeon
[row
][col
] & (TUNNEL
| FLOOR
| DOOR
))) {
298 place_at(obj
, row
, col
);
299 if (((row
!= rogue
.row
) || (col
!= rogue
.col
)) &&
300 (!(dungeon
[row
][col
] & MONSTER
))) {
301 mvaddch(row
, col
, get_dungeon_char(row
, col
));
309 seek_gold(object
*monster
)
313 if ((rn
= get_room_number(monster
->row
, monster
->col
)) < 0) {
316 for (i
= rooms
[rn
].top_row
+1; i
< rooms
[rn
].bottom_row
; i
++) {
317 for (j
= rooms
[rn
].left_col
+1; j
< rooms
[rn
].right_col
; j
++) {
318 if ((gold_at(i
, j
)) && !(dungeon
[i
][j
] & MONSTER
)) {
319 monster
->m_flags
|= CAN_FLIT
;
320 s
= mon_can_go(monster
, i
, j
);
321 monster
->m_flags
&= (~CAN_FLIT
);
323 move_mon_to(monster
, i
, j
);
324 monster
->m_flags
|= ASLEEP
;
325 monster
->m_flags
&= (~(WAKENS
| SEEKS_GOLD
));
328 monster
->m_flags
&= (~SEEKS_GOLD
);
329 monster
->m_flags
|= CAN_FLIT
;
330 mv_1_monster(monster
, i
, j
);
331 monster
->m_flags
&= (~CAN_FLIT
);
332 monster
->m_flags
|= SEEKS_GOLD
;
341 gold_at(short row
, short col
)
343 if (dungeon
[row
][col
] & OBJECT
) {
346 if ((obj
= object_at(&level_objects
, row
, col
)) &&
347 (obj
->what_is
== GOLD
)) {
355 check_gold_seeker(object
*monster
)
357 monster
->m_flags
&= (~SEEKS_GOLD
);
361 check_imitator(object
*monster
)
363 if (monster
->m_flags
& IMITATES
) {
366 mvaddch(monster
->row
, monster
->col
,
367 get_dungeon_char(monster
->row
, monster
->col
));
369 messagef(1, "wait, that's a %s!", mon_name(monster
));
377 imitating(short row
, short col
)
379 if (dungeon
[row
][col
] & MONSTER
) {
382 if ((monster
= object_at(&level_monsters
, row
, col
)) != NULL
) {
383 if (monster
->m_flags
& IMITATES
) {
392 sting(object
*monster
)
394 short sting_chance
= 35;
396 if ((rogue
.str_current
<= 3) || sustain_strength
) {
399 sting_chance
+= (6 * (6 - get_armor_class(rogue
.armor
)));
401 if ((rogue
.exp
+ ring_exp
) > 8) {
402 sting_chance
-= (6 * ((rogue
.exp
+ ring_exp
) - 8));
404 if (rand_percent(sting_chance
)) {
405 messagef(0, "the %s's bite has weakened you",
408 print_stats(STAT_STRENGTH
);
417 if (rand_percent(80) || (rogue
.exp
<= 5)) {
420 rogue
.exp_points
= level_points
[rogue
.exp
-2] - get_rand(9, 29);
423 if ((rogue
.hp_current
-= hp
) <= 0) {
424 rogue
.hp_current
= 1;
426 if ((rogue
.hp_max
-= hp
) <= 0) {
437 if (rand_percent(60) || (rogue
.hp_max
<= 30) || (rogue
.hp_current
< 10)) {
440 n
= get_rand(1, 3); /* 1 Hp, 2 Str, 3 both */
442 if ((n
!= 2) || (!sustain_strength
)) {
443 messagef(0, "you feel weaker");
451 if ((rogue
.str_current
> 3) && (!sustain_strength
)) {
458 print_stats((STAT_STRENGTH
| STAT_HP
));
462 m_confuse(object
*monster
)
464 if (!rogue_can_see(monster
->row
, monster
->col
)) {
467 if (rand_percent(45)) {
468 monster
->m_flags
&= (~CONFUSES
); /* will not confuse the rogue */
471 if (rand_percent(55)) {
472 monster
->m_flags
&= (~CONFUSES
);
473 messagef(1, "the gaze of the %s has confused you",
482 flame_broil(object
*monster
)
486 if ((!mon_sees(monster
, rogue
.row
, rogue
.col
)) || coin_toss()) {
489 row
= rogue
.row
- monster
->row
;
490 col
= rogue
.col
- monster
->col
;
497 if (((row
!= 0) && (col
!= 0) && (row
!= col
)) ||
498 ((row
> 7) || (col
> 7))) {
501 dir
= get_dir(monster
->row
, monster
->col
, row
, col
);
502 bounce(FIRE
, dir
, monster
->row
, monster
->col
, 0);
508 get_dir(short srow
, short scol
, short drow
, short dcol
)
524 if ((srow
> drow
) && (scol
> dcol
)) {
527 if ((srow
< drow
) && (scol
< dcol
)) {
530 if ((srow
< drow
) && (scol
> dcol
)) {
533 /*if ((srow > drow) && (scol < dcol)) {*/