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
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * @(#)move.c 8.1 (Berkeley) 5/31/93
37 * $FreeBSD: src/games/rogue/move.c,v 1.7 1999/11/30 03:49:24 billf Exp $
38 * $DragonFly: src/games/rogue/move.c,v 1.4 2006/09/02 19:31:07 pavalos Exp $
44 * This source herein may be modified and/or distributed by anybody who
45 * so desires, with the following restrictions:
46 * 1.) No portion of this notice shall be removed.
47 * 2.) Credit shall not be taken for the creation of this source.
48 * 3.) This code is not to be traded, sold, or used for personal
57 const char *you_can_move_again = "you can move again";
59 extern short cur_room, halluc, blind, levitate;
60 extern short cur_level, max_level;
61 extern short bear_trap, haste_self, confused;
62 extern short e_rings, regeneration, auto_search;
63 extern boolean being_held, interrupted, r_teleport, passgo;
65 static boolean next_to_something(int, int);
66 static boolean check_hunger(boolean);
67 static short gr_dir(void);
68 static void heal(void);
69 static boolean can_turn(short, short);
70 static void turn_passage(short, boolean);
73 one_move_rogue(short dirch, short pickup)
86 is_direction(dirch, &d);
87 get_dir_rc(d, &row, &col, 1);
89 if (!can_move(rogue.row, rogue.col, row, col)) {
92 if (being_held || bear_trap) {
93 if (!(dungeon[row][col] & MONSTER)) {
95 message("you are being held", 1);
97 message("you are still stuck in the bear trap", 0);
104 if (rand_percent(R_TELE_PERCENT)) {
106 return(STOPPED_ON_SOMETHING);
109 if (dungeon[row][col] & MONSTER) {
110 rogue_hit(object_at(&level_monsters, row, col), 0);
114 if (dungeon[row][col] & DOOR) {
115 if (cur_room == PASSAGE) {
116 cur_room = get_room_number(row, col);
117 light_up_room(cur_room);
118 wake_room(cur_room, 1, row, col);
120 light_passage(row, col);
122 } else if ((dungeon[rogue.row][rogue.col] & DOOR) &&
123 (dungeon[row][col] & TUNNEL)) {
124 light_passage(row, col);
125 wake_room(cur_room, 0, rogue.row, rogue.col);
126 darken_room(cur_room);
128 } else if (dungeon[row][col] & TUNNEL) {
129 light_passage(row, col);
131 mvaddch(rogue.row, rogue.col, get_dungeon_char(rogue.row, rogue.col));
132 mvaddch(row, col, rogue.fchar);
139 if (dungeon[row][col] & OBJECT) {
140 if (levitate && pickup) {
141 return(STOPPED_ON_SOMETHING);
143 if (pickup && !levitate) {
144 if ((obj = pick_up(row, col, &status))) {
146 if (obj->what_is == GOLD) {
150 } else if (!status) {
157 obj = object_at(&level_objects, row, col);
158 strcpy(desc, "moved onto ");
159 get_desc(obj, desc+11);
164 desc[n+1] = obj->ichar;
170 return(STOPPED_ON_SOMETHING);
172 if (dungeon[row][col] & (DOOR | STAIRS | TRAP)) {
173 if ((!levitate) && (dungeon[row][col] & TRAP)) {
174 trap_player(row, col);
177 return(STOPPED_ON_SOMETHING);
179 MVED: if (reg_move()) { /* fainted from hunger */
180 return(STOPPED_ON_SOMETHING);
182 return((confused ? STOPPED_ON_SOMETHING : MOVED));
186 multiple_move_rogue(short dirch)
203 if (((m = one_move_rogue((dirch + 96), 1)) == MOVE_FAILED) ||
204 (m == STOPPED_ON_SOMETHING) ||
208 } while (!next_to_something(row, col));
209 if ( (!interrupted) && passgo && (m == MOVE_FAILED) &&
210 (dungeon[rogue.row][rogue.col] & TUNNEL)) {
211 turn_passage(dirch + 96, 0);
222 while ((!interrupted) && (one_move_rogue((dirch + 32), 1) == MOVED)) ;
224 if ( (!interrupted) && passgo &&
225 (dungeon[rogue.row][rogue.col] & TUNNEL)) {
226 turn_passage(dirch + 32, 1);
233 is_passable(int row, int col)
235 if ((row < MIN_ROW) || (row > (DROWS - 2)) || (col < 0) ||
239 if (dungeon[row][col] & HIDDEN) {
240 return((dungeon[row][col] & TRAP) ? 1 : 0);
242 return(dungeon[row][col] & (FLOOR | TUNNEL | DOOR | STAIRS | TRAP));
246 next_to_something(int drow, int dcol)
248 short i, j, i_end, j_end, row, col;
249 short pass_count = 0;
258 i_end = (rogue.row < (DROWS-2)) ? 1 : 0;
259 j_end = (rogue.col < (DCOLS-1)) ? 1 : 0;
261 for (i = ((rogue.row > MIN_ROW) ? -1 : 0); i <= i_end; i++) {
262 for (j = ((rogue.col > 0) ? -1 : 0); j <= j_end; j++) {
263 if ((i == 0) && (j == 0)) {
266 if (((rogue.row+i) == drow) && ((rogue.col+j) == dcol)) {
271 s = dungeon[row][col];
275 /* If the rogue used to be right, up, left, down, or right of
276 * row,col, and now isn't, then don't stop */
277 if (s & (MONSTER | OBJECT | STAIRS)) {
278 if (((row == drow) || (col == dcol)) &&
279 (!((row == rogue.row) || (col == rogue.col)))) {
286 if (((row == drow) || (col == dcol)) &&
287 (!((row == rogue.row) || (col == rogue.col)))) {
293 if ((((i - j) == 1) || ((i - j) == -1)) && (s & TUNNEL)) {
294 if (++pass_count > 1) {
298 if ((s & DOOR) && ((i == 0) || (j == 0))) {
307 can_move(short row1, short col1, short row2, short col2)
309 if (!is_passable(row2, col2)) {
312 if ((row1 != row2) && (col1 != col2)) {
313 if ((dungeon[row1][col1] & DOOR) || (dungeon[row2][col2] & DOOR)) {
316 if ((!dungeon[row1][col2]) || (!dungeon[row2][col1])) {
327 boolean first_miss = 1;
329 while (!is_direction(ch = rgetchar(), &d)) {
332 message("direction? ", 0);
338 one_move_rogue(ch, 0);
343 is_direction(short c, short *d)
379 check_hunger(boolean msg_only)
384 if (rogue.moves_left == HUNGRY) {
385 strcpy(hunger_str, "hungry");
386 message(hunger_str, 0);
387 print_stats(STAT_HUNGER);
389 if (rogue.moves_left == WEAK) {
390 strcpy(hunger_str, "weak");
391 message(hunger_str, 1);
392 print_stats(STAT_HUNGER);
394 if (rogue.moves_left <= FAINT) {
395 if (rogue.moves_left == FAINT) {
396 strcpy(hunger_str, "faint");
397 message(hunger_str, 1);
398 print_stats(STAT_HUNGER);
400 n = get_rand(0, (FAINT - rogue.moves_left));
403 if (rand_percent(40)) {
406 message("you faint", 1);
407 for (i = 0; i < n; i++) {
412 message(you_can_move_again, 1);
418 if (rogue.moves_left <= STARVE) {
419 killed_by((object *) 0, STARVATION);
424 rogue.moves_left -= (rogue.moves_left % 2);
432 rogue.moves_left -= (rogue.moves_left % 2);
448 if ((rogue.moves_left <= HUNGRY) || (cur_level >= max_level)) {
449 fainted = check_hunger(0);
456 if (++m_moves >= 120) {
482 message("you float gently to the ground", 1);
483 if (dungeon[rogue.row][rogue.col] & TRAP) {
484 trap_player(rogue.row, rogue.col);
489 if (!(--haste_self)) {
490 message("you feel yourself slowing down", 0);
494 if (auto_search > 0) {
495 search(auto_search, auto_search);
507 for (i = 0; i < count; i++) {
554 static short heal_exp = -1, n, c = 0;
557 if (rogue.hp_current == rogue.hp_max) {
561 if (rogue.exp != heal_exp) {
562 heal_exp = rogue.exp;
609 if ((rogue.hp_current += regeneration) > rogue.hp_max) {
610 rogue.hp_current = rogue.hp_max;
612 print_stats(STAT_HP);
617 can_turn(short nrow, short ncol)
619 if ((dungeon[nrow][ncol] & TUNNEL) && is_passable(nrow, ncol)) {
626 turn_passage(short dir, boolean fast)
628 short crow = rogue.row, ccol = rogue.col, turns = 0;
631 if ((dir != 'h') && can_turn(crow, ccol + 1)) {
635 if ((dir != 'l') && can_turn(crow, ccol - 1)) {
639 if ((dir != 'k') && can_turn(crow + 1, ccol)) {
643 if ((dir != 'j') && can_turn(crow - 1, ccol)) {
648 multiple_move_rogue(ndir - (fast ? 32 : 96));