]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - rogue/move.c
mark non-returning functions (PR#6144 by Joseph Myers <jsm28@cam.ac.uk>)
[bsdgames-darwin.git] / rogue / move.c
1 /* $NetBSD: move.c,v 1.4 1997/10/12 11:45:31 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[] = "@(#)move.c 8.1 (Berkeley) 5/31/93";
43 #else
44 __RCSID("$NetBSD: move.c,v 1.4 1997/10/12 11:45:31 lukem Exp $");
45 #endif
46 #endif /* not lint */
47
48 /*
49 * move.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 short m_moves = 0;
63 boolean jump = 0;
64 char *you_can_move_again = "you can move again";
65
66 int
67 one_move_rogue(dirch, pickup)
68 short dirch, pickup;
69 {
70 short row, col;
71 object *obj;
72 char desc[DCOLS];
73 short n, status, d;
74
75 row = rogue.row;
76 col = rogue.col;
77
78 if (confused) {
79 dirch = gr_dir();
80 }
81 (void) is_direction(dirch, &d);
82 get_dir_rc(d, &row, &col, 1);
83
84 if (!can_move(rogue.row, rogue.col, row, col)) {
85 return(MOVE_FAILED);
86 }
87 if (being_held || bear_trap) {
88 if (!(dungeon[row][col] & MONSTER)) {
89 if (being_held) {
90 message("you are being held", 1);
91 } else {
92 message("you are still stuck in the bear trap", 0);
93 (void) reg_move();
94 }
95 return(MOVE_FAILED);
96 }
97 }
98 if (r_teleport) {
99 if (rand_percent(R_TELE_PERCENT)) {
100 tele();
101 return(STOPPED_ON_SOMETHING);
102 }
103 }
104 if (dungeon[row][col] & MONSTER) {
105 rogue_hit(object_at(&level_monsters, row, col), 0);
106 (void) reg_move();
107 return(MOVE_FAILED);
108 }
109 if (dungeon[row][col] & DOOR) {
110 if (cur_room == PASSAGE) {
111 cur_room = get_room_number(row, col);
112 light_up_room(cur_room);
113 wake_room(cur_room, 1, row, col);
114 } else {
115 light_passage(row, col);
116 }
117 } else if ((dungeon[rogue.row][rogue.col] & DOOR) &&
118 (dungeon[row][col] & TUNNEL)) {
119 light_passage(row, col);
120 wake_room(cur_room, 0, rogue.row, rogue.col);
121 darken_room(cur_room);
122 cur_room = PASSAGE;
123 } else if (dungeon[row][col] & TUNNEL) {
124 light_passage(row, col);
125 }
126 mvaddch(rogue.row, rogue.col, get_dungeon_char(rogue.row, rogue.col));
127 mvaddch(row, col, rogue.fchar);
128
129 if (!jump) {
130 refresh();
131 }
132 rogue.row = row;
133 rogue.col = col;
134 if (dungeon[row][col] & OBJECT) {
135 if (levitate && pickup) {
136 return(STOPPED_ON_SOMETHING);
137 }
138 if (pickup && !levitate) {
139 if ((obj = pick_up(row, col, &status)) != NULL) {
140 get_desc(obj, desc);
141 if (obj->what_is == GOLD) {
142 free_object(obj);
143 goto NOT_IN_PACK;
144 }
145 } else if (!status) {
146 goto MVED;
147 } else {
148 goto MOVE_ON;
149 }
150 } else {
151 MOVE_ON:
152 obj = object_at(&level_objects, row, col);
153 (void) strcpy(desc, "moved onto ");
154 get_desc(obj, desc+11);
155 goto NOT_IN_PACK;
156 }
157 n = strlen(desc);
158 desc[n] = '(';
159 desc[n+1] = obj->ichar;
160 desc[n+2] = ')';
161 desc[n+3] = 0;
162 NOT_IN_PACK:
163 message(desc, 1);
164 (void) reg_move();
165 return(STOPPED_ON_SOMETHING);
166 }
167 if (dungeon[row][col] & (DOOR | STAIRS | TRAP)) {
168 if ((!levitate) && (dungeon[row][col] & TRAP)) {
169 trap_player(row, col);
170 }
171 (void) reg_move();
172 return(STOPPED_ON_SOMETHING);
173 }
174 MVED: if (reg_move()) { /* fainted from hunger */
175 return(STOPPED_ON_SOMETHING);
176 }
177 return((confused ? STOPPED_ON_SOMETHING : MOVED));
178 }
179
180 void
181 multiple_move_rogue(dirch)
182 short dirch;
183 {
184 short row, col;
185 short m;
186
187 switch(dirch) {
188 case '\010':
189 case '\012':
190 case '\013':
191 case '\014':
192 case '\031':
193 case '\025':
194 case '\016':
195 case '\002':
196 do {
197 row = rogue.row;
198 col = rogue.col;
199 if (((m = one_move_rogue((dirch + 96), 1)) == MOVE_FAILED) ||
200 (m == STOPPED_ON_SOMETHING) ||
201 interrupted) {
202 break;
203 }
204 } while (!next_to_something(row, col));
205 if ( (!interrupted) && passgo && (m == MOVE_FAILED) &&
206 (dungeon[rogue.row][rogue.col] & TUNNEL)) {
207 turn_passage(dirch + 96, 0);
208 }
209 break;
210 case 'H':
211 case 'J':
212 case 'K':
213 case 'L':
214 case 'B':
215 case 'Y':
216 case 'U':
217 case 'N':
218 while ((!interrupted) && (one_move_rogue((dirch + 32), 1) == MOVED)) ;
219
220 if ( (!interrupted) && passgo &&
221 (dungeon[rogue.row][rogue.col] & TUNNEL)) {
222 turn_passage(dirch + 32, 1);
223 }
224 break;
225 }
226 }
227
228 boolean
229 is_passable(row, col)
230 int row, col;
231 {
232 if ((row < MIN_ROW) || (row > (DROWS - 2)) || (col < 0) ||
233 (col > (DCOLS-1))) {
234 return(0);
235 }
236 if (dungeon[row][col] & HIDDEN) {
237 return((dungeon[row][col] & TRAP) ? 1 : 0);
238 }
239 return(dungeon[row][col] & (FLOOR | TUNNEL | DOOR | STAIRS | TRAP));
240 }
241
242 boolean
243 next_to_something(drow, dcol)
244 int drow, dcol;
245 {
246 short i, j, i_end, j_end, row, col;
247 short pass_count = 0;
248 unsigned short s;
249
250 if (confused) {
251 return(1);
252 }
253 if (blind) {
254 return(0);
255 }
256 i_end = (rogue.row < (DROWS-2)) ? 1 : 0;
257 j_end = (rogue.col < (DCOLS-1)) ? 1 : 0;
258
259 for (i = ((rogue.row > MIN_ROW) ? -1 : 0); i <= i_end; i++) {
260 for (j = ((rogue.col > 0) ? -1 : 0); j <= j_end; j++) {
261 if ((i == 0) && (j == 0)) {
262 continue;
263 }
264 if (((rogue.row+i) == drow) && ((rogue.col+j) == dcol)) {
265 continue;
266 }
267 row = rogue.row + i;
268 col = rogue.col + j;
269 s = dungeon[row][col];
270 if (s & HIDDEN) {
271 continue;
272 }
273 /* If the rogue used to be right, up, left, down, or right of
274 * row,col, and now isn't, then don't stop */
275 if (s & (MONSTER | OBJECT | STAIRS)) {
276 if (((row == drow) || (col == dcol)) &&
277 (!((row == rogue.row) || (col == rogue.col)))) {
278 continue;
279 }
280 return(1);
281 }
282 if (s & TRAP) {
283 if (!(s & HIDDEN)) {
284 if (((row == drow) || (col == dcol)) &&
285 (!((row == rogue.row) || (col == rogue.col)))) {
286 continue;
287 }
288 return(1);
289 }
290 }
291 if ((((i - j) == 1) || ((i - j) == -1)) && (s & TUNNEL)) {
292 if (++pass_count > 1) {
293 return(1);
294 }
295 }
296 if ((s & DOOR) && ((i == 0) || (j == 0))) {
297 return(1);
298 }
299 }
300 }
301 return(0);
302 }
303
304 boolean
305 can_move(row1, col1, row2, col2)
306 int row1, col1, row2, col2;
307 {
308 if (!is_passable(row2, col2)) {
309 return(0);
310 }
311 if ((row1 != row2) && (col1 != col2)) {
312 if ((dungeon[row1][col1] & DOOR) || (dungeon[row2][col2] & DOOR)) {
313 return(0);
314 }
315 if ((!dungeon[row1][col2]) || (!dungeon[row2][col1])) {
316 return(0);
317 }
318 }
319 return(1);
320 }
321
322 void
323 move_onto()
324 {
325 short ch, d;
326 boolean first_miss = 1;
327
328 while (!is_direction(ch = rgetchar(), &d)) {
329 sound_bell();
330 if (first_miss) {
331 message("direction? ", 0);
332 first_miss = 0;
333 }
334 }
335 check_message();
336 if (ch != CANCEL) {
337 (void) one_move_rogue(ch, 0);
338 }
339 }
340
341 boolean
342 is_direction(c, d)
343 short c;
344 short *d;
345 {
346 switch(c) {
347 case 'h':
348 *d = LEFT;
349 break;
350 case 'j':
351 *d = DOWN;
352 break;
353 case 'k':
354 *d = UPWARD;
355 break;
356 case 'l':
357 *d = RIGHT;
358 break;
359 case 'b':
360 *d = DOWNLEFT;
361 break;
362 case 'y':
363 *d = UPLEFT;
364 break;
365 case 'u':
366 *d = UPRIGHT;
367 break;
368 case 'n':
369 *d = DOWNRIGHT;
370 break;
371 case CANCEL:
372 break;
373 default:
374 return(0);
375 }
376 return(1);
377 }
378
379 boolean
380 check_hunger(msg_only)
381 boolean msg_only;
382 {
383 short i, n;
384 boolean fainted = 0;
385
386 if (rogue.moves_left == HUNGRY) {
387 (void) strcpy(hunger_str, "hungry");
388 message(hunger_str, 0);
389 print_stats(STAT_HUNGER);
390 }
391 if (rogue.moves_left == WEAK) {
392 (void) strcpy(hunger_str, "weak");
393 message(hunger_str, 1);
394 print_stats(STAT_HUNGER);
395 }
396 if (rogue.moves_left <= FAINT) {
397 if (rogue.moves_left == FAINT) {
398 (void) strcpy(hunger_str, "faint");
399 message(hunger_str, 1);
400 print_stats(STAT_HUNGER);
401 }
402 n = get_rand(0, (FAINT - rogue.moves_left));
403 if (n > 0) {
404 fainted = 1;
405 if (rand_percent(40)) {
406 rogue.moves_left++;
407 }
408 message("you faint", 1);
409 for (i = 0; i < n; i++) {
410 if (coin_toss()) {
411 mv_mons();
412 }
413 }
414 message(you_can_move_again, 1);
415 }
416 }
417 if (msg_only) {
418 return(fainted);
419 }
420 if (rogue.moves_left <= STARVE) {
421 killed_by((object *) 0, STARVATION);
422 }
423
424 switch(e_rings) {
425 /*case -2:
426 Subtract 0, i.e. do nothing.
427 break;*/
428 case -1:
429 rogue.moves_left -= (rogue.moves_left % 2);
430 break;
431 case 0:
432 rogue.moves_left--;
433 break;
434 case 1:
435 rogue.moves_left--;
436 (void) check_hunger(1);
437 rogue.moves_left -= (rogue.moves_left % 2);
438 break;
439 case 2:
440 rogue.moves_left--;
441 (void) check_hunger(1);
442 rogue.moves_left--;
443 break;
444 }
445 return(fainted);
446 }
447
448 boolean
449 reg_move()
450 {
451 boolean fainted;
452
453 if ((rogue.moves_left <= HUNGRY) || (cur_level >= max_level)) {
454 fainted = check_hunger(0);
455 } else {
456 fainted = 0;
457 }
458
459 mv_mons();
460
461 if (++m_moves >= 120) {
462 m_moves = 0;
463 wanderer();
464 }
465 if (halluc) {
466 if (!(--halluc)) {
467 unhallucinate();
468 } else {
469 hallucinate();
470 }
471 }
472 if (blind) {
473 if (!(--blind)) {
474 unblind();
475 }
476 }
477 if (confused) {
478 if (!(--confused)) {
479 unconfuse();
480 }
481 }
482 if (bear_trap) {
483 bear_trap--;
484 }
485 if (levitate) {
486 if (!(--levitate)) {
487 message("you float gently to the ground", 1);
488 if (dungeon[rogue.row][rogue.col] & TRAP) {
489 trap_player(rogue.row, rogue.col);
490 }
491 }
492 }
493 if (haste_self) {
494 if (!(--haste_self)) {
495 message("you feel yourself slowing down", 0);
496 }
497 }
498 heal();
499 if (auto_search > 0) {
500 search(auto_search, auto_search);
501 }
502 return(fainted);
503 }
504
505 void
506 rest(count)
507 int count;
508 {
509 int i;
510
511 interrupted = 0;
512
513 for (i = 0; i < count; i++) {
514 if (interrupted) {
515 break;
516 }
517 (void) reg_move();
518 }
519 }
520
521 char
522 gr_dir()
523 {
524 short d;
525
526 d = get_rand(1, 8);
527
528 switch(d) {
529 case 1:
530 d = 'j';
531 break;
532 case 2:
533 d = 'k';
534 break;
535 case 3:
536 d = 'l';
537 break;
538 case 4:
539 d = 'h';
540 break;
541 case 5:
542 d = 'y';
543 break;
544 case 6:
545 d = 'u';
546 break;
547 case 7:
548 d = 'b';
549 break;
550 case 8:
551 d = 'n';
552 break;
553 }
554 return(d);
555 }
556
557 void
558 heal()
559 {
560 static short heal_exp = -1, n, c = 0;
561 static boolean alt;
562
563 if (rogue.hp_current == rogue.hp_max) {
564 c = 0;
565 return;
566 }
567 if (rogue.exp != heal_exp) {
568 heal_exp = rogue.exp;
569
570 switch(heal_exp) {
571 case 1:
572 n = 20;
573 break;
574 case 2:
575 n = 18;
576 break;
577 case 3:
578 n = 17;
579 break;
580 case 4:
581 n = 14;
582 break;
583 case 5:
584 n = 13;
585 break;
586 case 6:
587 n = 10;
588 break;
589 case 7:
590 n = 9;
591 break;
592 case 8:
593 n = 8;
594 break;
595 case 9:
596 n = 7;
597 break;
598 case 10:
599 n = 4;
600 break;
601 case 11:
602 n = 3;
603 break;
604 case 12:
605 default:
606 n = 2;
607 }
608 }
609 if (++c >= n) {
610 c = 0;
611 rogue.hp_current++;
612 if ((alt = !alt) != 0) {
613 rogue.hp_current++;
614 }
615 if ((rogue.hp_current += regeneration) > rogue.hp_max) {
616 rogue.hp_current = rogue.hp_max;
617 }
618 print_stats(STAT_HP);
619 }
620 }
621
622 boolean
623 can_turn(nrow, ncol)
624 short nrow, ncol;
625 {
626 if ((dungeon[nrow][ncol] & TUNNEL) && is_passable(nrow, ncol)) {
627 return(1);
628 }
629 return(0);
630 }
631
632 void
633 turn_passage(dir, fast)
634 short dir;
635 boolean fast;
636 {
637 short crow = rogue.row, ccol = rogue.col, turns = 0;
638 short ndir = 0;
639
640 if ((dir != 'h') && can_turn(crow, ccol + 1)) {
641 turns++;
642 ndir = 'l';
643 }
644 if ((dir != 'l') && can_turn(crow, ccol - 1)) {
645 turns++;
646 ndir = 'h';
647 }
648 if ((dir != 'k') && can_turn(crow + 1, ccol)) {
649 turns++;
650 ndir = 'j';
651 }
652 if ((dir != 'j') && can_turn(crow - 1, ccol)) {
653 turns++;
654 ndir = 'k';
655 }
656 if (turns == 1) {
657 multiple_move_rogue(ndir - (fast ? 32 : 96));
658 }
659 }