libc/sysvipc: Mark two functions as printf-like and fix resulting errors.
[dragonfly.git] / games / rogue / zap.c
blob585b1dd3c2581d3dba84924039f33d8a06f5b103
1 /*-
2 * Copyright (c) 1988, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Timothy C. Stoehr.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
32 * @(#)zap.c 8.1 (Berkeley) 5/31/93
33 * $FreeBSD: src/games/rogue/zap.c,v 1.3 1999/11/30 03:49:29 billf Exp $
37 * zap.c
39 * This source herein may be modified and/or distributed by anybody who
40 * so desires, with the following restrictions:
41 * 1.) No portion of this notice shall be removed.
42 * 2.) Credit shall not be taken for the creation of this source.
43 * 3.) This code is not to be traded, sold, or used for personal
44 * gain or profit.
48 #include "rogue.h"
50 static object *get_zapped_monster(short, short *, short *);
51 static void tele_away(object *);
52 static void wdrain_life(object *);
53 static void zap_monster(object *, unsigned short);
55 boolean wizard = 0;
57 void
58 zapp(void)
60 short wch;
61 boolean first_miss = 1;
62 object *wand;
63 short dir, d, row, col;
64 object *monster;
66 while (!is_direction(dir = rgetchar(), &d)) {
67 sound_bell();
68 if (first_miss) {
69 message("direction? ", 0);
70 first_miss = 0;
73 check_message();
74 if (dir == CANCEL) {
75 return;
77 if ((wch = pack_letter("zap with what?", WAND)) == CANCEL) {
78 return;
80 check_message();
82 if (!(wand = get_letter_object(wch))) {
83 message("no such item.", 0);
84 return;
86 if (wand->what_is != WAND) {
87 message("you can't zap with that", 0);
88 return;
90 if (wand->class <= 0) {
91 message("nothing happens", 0);
92 } else {
93 wand->class--;
94 row = rogue.row; col = rogue.col;
95 if ((wand->which_kind == COLD) || (wand->which_kind == FIRE)) {
96 bounce((short)wand->which_kind, d, row, col, 0);
97 } else {
98 monster = get_zapped_monster(d, &row, &col);
99 if (wand->which_kind == DRAIN_LIFE) {
100 wdrain_life(monster);
101 } else if (monster) {
102 wake_up(monster);
103 s_con_mon(monster);
104 zap_monster(monster, wand->which_kind);
105 relight();
109 reg_move();
112 static object *
113 get_zapped_monster(short dir, short *row, short *col)
115 short orow, ocol;
117 for (;;) {
118 orow = *row; ocol = *col;
119 get_dir_rc(dir, row, col, 0);
120 if (((*row == orow) && (*col == ocol)) ||
121 (dungeon[*row][*col] & (HORWALL | VERTWALL)) ||
122 (dungeon[*row][*col] == NOTHING)) {
123 return(0);
125 if (dungeon[*row][*col] & MONSTER) {
126 if (!imitating(*row, *col)) {
127 return(object_at(&level_monsters, *row, *col));
133 static void
134 zap_monster(object *monster, unsigned short kind)
136 short row, col;
137 object *nm;
138 short tc;
140 row = monster->row;
141 col = monster->col;
143 switch(kind) {
144 case SLOW_MONSTER:
145 if (monster->m_flags & HASTED) {
146 monster->m_flags &= (~HASTED);
147 } else {
148 monster->slowed_toggle = 0;
149 monster->m_flags |= SLOWED;
151 break;
152 case HASTE_MONSTER:
153 if (monster->m_flags & SLOWED) {
154 monster->m_flags &= (~SLOWED);
155 } else {
156 monster->m_flags |= HASTED;
158 break;
159 case TELE_AWAY:
160 tele_away(monster);
161 break;
162 case INVISIBILITY:
163 monster->m_flags |= INVISIBLE;
164 break;
165 case POLYMORPH:
166 if (monster->m_flags & HOLDS) {
167 being_held = 0;
169 nm = monster->next_monster;
170 tc = monster->trail_char;
171 gr_monster(monster, get_rand(0, MONSTERS-1));
172 monster->row = row;
173 monster->col = col;
174 monster->next_monster = nm;
175 monster->trail_char = tc;
176 if (!(monster->m_flags & IMITATES)) {
177 wake_up(monster);
179 break;
180 case MAGIC_MISSILE:
181 rogue_hit(monster, 1);
182 break;
183 case CANCELLATION:
184 if (monster->m_flags & HOLDS) {
185 being_held = 0;
187 if (monster->m_flags & STEALS_ITEM) {
188 monster->drop_percent = 0;
190 monster->m_flags &= (~(FLIES | FLITS | SPECIAL_HIT | INVISIBLE |
191 FLAMES | IMITATES | CONFUSES | SEEKS_GOLD | HOLDS));
192 break;
193 case DO_NOTHING:
194 message("nothing happens", 0);
195 break;
199 static void
200 tele_away(object *monster)
202 short row, col;
204 if (monster->m_flags & HOLDS) {
205 being_held = 0;
207 gr_row_col(&row, &col, (FLOOR | TUNNEL | STAIRS | OBJECT));
208 mvaddch(monster->row, monster->col, monster->trail_char);
209 dungeon[monster->row][monster->col] &= ~MONSTER;
210 monster->row = row; monster->col = col;
211 dungeon[row][col] |= MONSTER;
212 monster->trail_char = mvinch(row, col);
213 if (detect_monster || rogue_can_see(row, col)) {
214 mvaddch(row, col, gmc(monster));
218 void
219 wizardize(void)
221 char buf[100];
223 if (wizard) {
224 wizard = 0;
225 message("not wizard anymore", 0);
226 } else {
227 if (get_input_line("wizard's password:", "", buf, "", 0, 0)) {
228 xxx(1);
229 xxxx(buf, strlen(buf));
230 if (!strncmp(buf, "\247\104\126\272\115\243\027", 7)) {
231 wizard = 1;
232 score_only = 1;
233 message("Welcome, mighty wizard!", 0);
234 } else {
235 message("sorry", 0);
241 static void
242 wdrain_life(object *monster)
244 short hp;
245 object *lmon, *nm;
247 hp = rogue.hp_current / 3;
248 rogue.hp_current = (rogue.hp_current + 1) / 2;
250 if (cur_room >= 0) {
251 lmon = level_monsters.next_monster;
252 while (lmon) {
253 nm = lmon->next_monster;
254 if (get_room_number(lmon->row, lmon->col) == cur_room) {
255 wake_up(lmon);
256 mon_damage(lmon, hp);
258 lmon = nm;
260 } else {
261 if (monster) {
262 wake_up(monster);
263 mon_damage(monster, hp);
266 print_stats(STAT_HP);
267 relight();
270 void
271 bounce(short ball, short dir, short row, short col, short r)
273 short orow, ocol;
274 char buf[DCOLS];
275 const char *s;
276 short i, ch, new_dir = -1, damage;
277 static short btime;
279 if (++r == 1) {
280 btime = get_rand(3, 6);
281 } else if (r > btime) {
282 return;
285 if (ball == FIRE) {
286 s = "fire";
287 } else {
288 s = "ice";
290 if (r > 1) {
291 sprintf(buf, "the %s bounces", s);
292 message(buf, 0);
294 orow = row;
295 ocol = col;
296 do {
297 ch = mvinch(orow, ocol);
298 standout();
299 mvaddch(orow, ocol, ch);
300 get_dir_rc(dir, &orow, &ocol, 1);
301 } while (!( (ocol <= 0) ||
302 (ocol >= DCOLS-1) ||
303 (dungeon[orow][ocol] == NOTHING) ||
304 (dungeon[orow][ocol] & MONSTER) ||
305 (dungeon[orow][ocol] & (HORWALL | VERTWALL)) ||
306 ((orow == rogue.row) && (ocol == rogue.col))));
307 standend();
308 refresh();
309 do {
310 orow = row;
311 ocol = col;
312 ch = mvinch(row, col);
313 mvaddch(row, col, ch);
314 get_dir_rc(dir, &row, &col, 1);
315 } while (!( (col <= 0) ||
316 (col >= DCOLS-1) ||
317 (dungeon[row][col] == NOTHING) ||
318 (dungeon[row][col] & MONSTER) ||
319 (dungeon[row][col] & (HORWALL | VERTWALL)) ||
320 ((row == rogue.row) && (col == rogue.col))));
322 if (dungeon[row][col] & MONSTER) {
323 object *monster;
325 monster = object_at(&level_monsters, row, col);
327 wake_up(monster);
328 if (rand_percent(33)) {
329 sprintf(buf, "the %s misses the %s", s, mon_name(monster));
330 message(buf, 0);
331 goto ND;
333 if (ball == FIRE) {
334 if (!(monster->m_flags & RUSTS)) {
335 if (monster->m_flags & FREEZES) {
336 damage = monster->hp_to_kill;
337 } else if (monster->m_flags & FLAMES) {
338 damage = (monster->hp_to_kill / 10) + 1;
339 } else {
340 damage = get_rand((rogue.hp_current / 3), rogue.hp_max);
342 } else {
343 damage = (monster->hp_to_kill / 2) + 1;
345 sprintf(buf, "the %s hits the %s", s, mon_name(monster));
346 message(buf, 0);
347 mon_damage(monster, damage);
348 } else {
349 damage = -1;
350 if (!(monster->m_flags & FREEZES)) {
351 if (rand_percent(33)) {
352 message("the monster is frozen", 0);
353 monster->m_flags |= (ASLEEP | NAPPING);
354 monster->nap_length = get_rand(3, 6);
355 } else {
356 damage = rogue.hp_current / 4;
358 } else {
359 damage = -2;
361 if (damage != -1) {
362 sprintf(buf, "the %s hits the %s", s, mon_name(monster));
363 message(buf, 0);
364 mon_damage(monster, damage);
367 } else if ((row == rogue.row) && (col == rogue.col)) {
368 if (rand_percent(10 + (3 * get_armor_class(rogue.armor)))) {
369 sprintf(buf, "the %s misses", s);
370 message(buf, 0);
371 goto ND;
372 } else {
373 damage = get_rand(3, (3 * rogue.exp));
374 if (ball == FIRE) {
375 damage = (damage * 3) / 2;
376 damage -= get_armor_class(rogue.armor);
378 sprintf(buf, "the %s hits", s);
379 rogue_damage(damage, NULL,
380 ((ball == FIRE) ? KFIRE : HYPOTHERMIA));
381 message(buf, 0);
383 } else {
384 short nrow, ncol;
386 ND: for (i = 0; i < 10; i++) {
387 dir = get_rand(0, DIRS-1);
388 nrow = orow;
389 ncol = ocol;
390 get_dir_rc(dir, &nrow, &ncol, 1);
391 if (((ncol >= 0) && (ncol <= DCOLS-1)) &&
392 (dungeon[nrow][ncol] != NOTHING) &&
393 (!(dungeon[nrow][ncol] & (VERTWALL | HORWALL)))) {
394 new_dir = dir;
395 break;
398 if (new_dir != -1) {
399 bounce(ball, new_dir, orow, ocol, r);