diff options
author | B. Watson <yalhcru@gmail.com> | 2015-05-07 16:32:32 -0400 |
---|---|---|
committer | B. Watson <yalhcru@gmail.com> | 2015-05-07 16:32:32 -0400 |
commit | 013ac7742311556022304e8b30ca170d48b3a016 (patch) | |
tree | 53faa33e75991363f1a6dcc7edc83a66b70e6995 /rogue/move.c | |
download | bsd-games-extra-013ac7742311556022304e8b30ca170d48b3a016.tar.gz |
initial commit
Diffstat (limited to 'rogue/move.c')
-rw-r--r-- | rogue/move.c | 649 |
1 files changed, 649 insertions, 0 deletions
diff --git a/rogue/move.c b/rogue/move.c new file mode 100644 index 0000000..8378654 --- /dev/null +++ b/rogue/move.c @@ -0,0 +1,649 @@ +/* $NetBSD: move.c,v 1.13 2011/05/23 23:01:17 joerg Exp $ */ + +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Timothy C. Stoehr. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +#ifndef lint +#if 0 +static char sccsid[] = "@(#)move.c 8.1 (Berkeley) 5/31/93"; +#else +__RCSID("$NetBSD: move.c,v 1.13 2011/05/23 23:01:17 joerg Exp $"); +#endif +#endif /* not lint */ + +/* + * move.c + * + * This source herein may be modified and/or distributed by anybody who + * so desires, with the following restrictions: + * 1.) No portion of this notice shall be removed. + * 2.) Credit shall not be taken for the creation of this source. + * 3.) This code is not to be traded, sold, or used for personal + * gain or profit. + * + */ + +#include "rogue.h" + +short m_moves = 0; +boolean jump = 0; +const char you_can_move_again[] = "you can move again"; + +static boolean can_turn(short, short); +static boolean check_hunger(boolean); +static char gr_dir(void); +static void heal(void); +static boolean next_to_something(int, int); +static void turn_passage(short, boolean); + +int +one_move_rogue(short dirch, short pickup) +{ + short row, col; + object *obj; + char desc[DCOLS]; + short status, d = 0; /* XXX: GCC */ + + row = rogue.row; + col = rogue.col; + + if (confused) { + dirch = gr_dir(); + } + (void)is_direction(dirch, &d); + get_dir_rc(d, &row, &col, 1); + + if (!can_move(rogue.row, rogue.col, row, col)) { + return(MOVE_FAILED); + } + if (being_held || bear_trap) { + if (!(dungeon[row][col] & MONSTER)) { + if (being_held) { + messagef(1, "you are being held"); + } else { + messagef(0, "you are still stuck in the bear trap"); + (void)reg_move(); + } + return(MOVE_FAILED); + } + } + if (r_teleport) { + if (rand_percent(R_TELE_PERCENT)) { + tele(); + return(STOPPED_ON_SOMETHING); + } + } + if (dungeon[row][col] & MONSTER) { + rogue_hit(object_at(&level_monsters, row, col), 0); + (void)reg_move(); + return(MOVE_FAILED); + } + if (dungeon[row][col] & DOOR) { + if (cur_room == PASSAGE) { + cur_room = get_room_number(row, col); + if (cur_room == NO_ROOM) + clean_up("one_move_rogue: door to nowhere"); + light_up_room(cur_room); + wake_room(cur_room, 1, row, col); + } else { + light_passage(row, col); + } + } else if ((dungeon[rogue.row][rogue.col] & DOOR) && + (dungeon[row][col] & TUNNEL)) { + light_passage(row, col); + wake_room(cur_room, 0, rogue.row, rogue.col); + darken_room(cur_room); + cur_room = PASSAGE; + } else if (dungeon[row][col] & TUNNEL) { + light_passage(row, col); + } + mvaddch(rogue.row, rogue.col, get_dungeon_char(rogue.row, rogue.col)); + mvaddch(row, col, rogue.fchar); + + if (!jump) { + refresh(); + } + rogue.row = row; + rogue.col = col; + if (dungeon[row][col] & OBJECT) { + if (levitate && pickup) { + return(STOPPED_ON_SOMETHING); + } + if (pickup && !levitate) { + if ((obj = pick_up(row, col, &status)) != NULL) { + get_desc(obj, desc, sizeof(desc)); + if (obj->what_is == GOLD) { + free_object(obj); + messagef(1, "%s", desc); + goto NOT_IN_PACK; + } + } else if (!status) { + goto MVED; + } else { + goto MOVE_ON; + } + } else { +MOVE_ON: + obj = object_at(&level_objects, row, col); + get_desc(obj, desc, sizeof(desc)); + messagef(1, "moved onto %s", desc); + goto NOT_IN_PACK; + } + messagef(1, "%s(%c)", desc, obj->ichar); +NOT_IN_PACK: + (void)reg_move(); + return(STOPPED_ON_SOMETHING); + } + if (dungeon[row][col] & (DOOR | STAIRS | TRAP)) { + if ((!levitate) && (dungeon[row][col] & TRAP)) { + trap_player(row, col); + } + (void)reg_move(); + return(STOPPED_ON_SOMETHING); + } +MVED: if (reg_move()) { /* fainted from hunger */ + return(STOPPED_ON_SOMETHING); + } + return((confused ? STOPPED_ON_SOMETHING : MOVED)); +} + +void +multiple_move_rogue(short dirch) +{ + short row, col; + short m; + + switch(dirch) { + case '\010': + case '\012': + case '\013': + case '\014': + case '\031': + case '\025': + case '\016': + case '\002': + do { + row = rogue.row; + col = rogue.col; + if (((m = one_move_rogue((dirch + 96), 1)) == MOVE_FAILED) || + (m == STOPPED_ON_SOMETHING) || + interrupted) { + break; + } + } while (!next_to_something(row, col)); + if ( (!interrupted) && passgo && (m == MOVE_FAILED) && + (dungeon[rogue.row][rogue.col] & TUNNEL)) { + turn_passage(dirch + 96, 0); + } + break; + case 'H': + case 'J': + case 'K': + case 'L': + case 'B': + case 'Y': + case 'U': + case 'N': + while ((!interrupted) && (one_move_rogue((dirch + 32), 1) == MOVED)) + ; + + if ( (!interrupted) && passgo && + (dungeon[rogue.row][rogue.col] & TUNNEL)) { + turn_passage(dirch + 32, 1); + } + break; + } +} + +boolean +is_passable(int row, int col) +{ + if ((row < MIN_ROW) || (row > (DROWS - 2)) || (col < 0) || + (col > (DCOLS-1))) { + return(0); + } + if (dungeon[row][col] & HIDDEN) { + return((dungeon[row][col] & TRAP) ? 1 : 0); + } + return(dungeon[row][col] & (FLOOR | TUNNEL | DOOR | STAIRS | TRAP)); +} + +static boolean +next_to_something(int drow, int dcol) +{ + short i, j, i_end, j_end, row, col; + short pass_count = 0; + unsigned short s; + + if (confused) { + return(1); + } + if (blind) { + return(0); + } + i_end = (rogue.row < (DROWS-2)) ? 1 : 0; + j_end = (rogue.col < (DCOLS-1)) ? 1 : 0; + + for (i = ((rogue.row > MIN_ROW) ? -1 : 0); i <= i_end; i++) { + for (j = ((rogue.col > 0) ? -1 : 0); j <= j_end; j++) { + if ((i == 0) && (j == 0)) { + continue; + } + if (((rogue.row+i) == drow) && ((rogue.col+j) == dcol)) { + continue; + } + row = rogue.row + i; + col = rogue.col + j; + s = dungeon[row][col]; + if (s & HIDDEN) { + continue; + } + /* If the rogue used to be right, up, left, down, or right of + * row,col, and now isn't, then don't stop */ + if (s & (MONSTER | OBJECT | STAIRS)) { + if (((row == drow) || (col == dcol)) && + (!((row == rogue.row) || (col == rogue.col)))) { + continue; + } + return(1); + } + if (s & TRAP) { + if (!(s & HIDDEN)) { + if (((row == drow) || (col == dcol)) && + (!((row == rogue.row) || (col == rogue.col)))) { + continue; + } + return(1); + } + } + if ((((i - j) == 1) || ((i - j) == -1)) && (s & TUNNEL)) { + if (++pass_count > 1) { + return(1); + } + } + if ((s & DOOR) && ((i == 0) || (j == 0))) { + return(1); + } + } + } + return(0); +} + +boolean +can_move(int row1, int col1, int row2, int col2) +{ + if (!is_passable(row2, col2)) { + return(0); + } + if ((row1 != row2) && (col1 != col2)) { + if ((dungeon[row1][col1] & DOOR) || (dungeon[row2][col2] & DOOR)) { + return(0); + } + if ((!dungeon[row1][col2]) || (!dungeon[row2][col1])) { + return(0); + } + } + return(1); +} + +void +move_onto(void) +{ + short ch, d; + boolean first_miss = 1; + + while (!is_direction(ch = rgetchar(), &d)) { + sound_bell(); + if (first_miss) { + messagef(0, "direction? "); + first_miss = 0; + } + } + check_message(); + if (ch != CANCEL) { + (void)one_move_rogue(ch, 0); + } +} + +boolean +is_direction(short c, short *d) +{ + switch(c) { + case 'h': + *d = LEFT; + break; + case 'j': + *d = DOWN; + break; + case 'k': + *d = UPWARD; + break; + case 'l': + *d = RIGHT; + break; + case 'b': + *d = DOWNLEFT; + break; + case 'y': + *d = UPLEFT; + break; + case 'u': + *d = UPRIGHT; + break; + case 'n': + *d = DOWNRIGHT; + break; + case CANCEL: + break; + default: + return(0); + } + return(1); +} + +static boolean +check_hunger(boolean msg_only) +{ + short i, n; + boolean fainted = 0; + + if (rogue.moves_left == HUNGRY) { + (void)strlcpy(hunger_str, "hungry", sizeof(hunger_str)); + messagef(0, "%s", hunger_str); + print_stats(STAT_HUNGER); + } + if (rogue.moves_left == WEAK) { + (void)strlcpy(hunger_str, "weak", sizeof(hunger_str)); + messagef(1, "%s", hunger_str); + print_stats(STAT_HUNGER); + } + if (rogue.moves_left <= FAINT) { + if (rogue.moves_left == FAINT) { + (void)strlcpy(hunger_str, "faint", sizeof(hunger_str)); + messagef(1, "%s", hunger_str); + print_stats(STAT_HUNGER); + } + n = get_rand(0, (FAINT - rogue.moves_left)); + if (n > 0) { + fainted = 1; + if (rand_percent(40)) { + rogue.moves_left++; + } + messagef(1, "you faint"); + for (i = 0; i < n; i++) { + if (coin_toss()) { + mv_mons(); + } + } + messagef(1, "%s", you_can_move_again); + } + } + if (msg_only) { + return(fainted); + } + if (rogue.moves_left <= STARVE) { + killed_by(NULL, STARVATION); + } + + switch(e_rings) { + /*case -2: + Subtract 0, i.e. do nothing. + break;*/ + case -1: + rogue.moves_left -= (rogue.moves_left % 2); + break; + case 0: + rogue.moves_left--; + break; + case 1: + rogue.moves_left--; + (void)check_hunger(1); + rogue.moves_left -= (rogue.moves_left % 2); + break; + case 2: + rogue.moves_left--; + (void)check_hunger(1); + rogue.moves_left--; + break; + } + return(fainted); +} + +boolean +reg_move(void) +{ + boolean fainted; + + if ((rogue.moves_left <= HUNGRY) || (cur_level >= max_level)) { + fainted = check_hunger(0); + } else { + fainted = 0; + } + + mv_mons(); + + if (++m_moves >= 120) { + m_moves = 0; + wanderer(); + } + if (halluc) { + if (!(--halluc)) { + unhallucinate(); + } else { + hallucinate(); + } + } + if (blind) { + if (!(--blind)) { + unblind(); + } + } + if (confused) { + if (!(--confused)) { + unconfuse(); + } + } + if (bear_trap) { + bear_trap--; + } + if (levitate) { + if (!(--levitate)) { + messagef(1, "you float gently to the ground"); + if (dungeon[rogue.row][rogue.col] & TRAP) { + trap_player(rogue.row, rogue.col); + } + } + } + if (haste_self) { + if (!(--haste_self)) { + messagef(0, "you feel yourself slowing down"); + } + } + heal(); + if (auto_search > 0) { + search(auto_search, auto_search); + } + return(fainted); +} + +void +rest(int count) +{ + int i; + + interrupted = 0; + + for (i = 0; i < count; i++) { + if (interrupted) { + break; + } + (void)reg_move(); + } +} + +static char +gr_dir(void) +{ + short d; + + d = get_rand(1, 8); + + switch(d) { + case 1: + d = 'j'; + break; + case 2: + d = 'k'; + break; + case 3: + d = 'l'; + break; + case 4: + d = 'h'; + break; + case 5: + d = 'y'; + break; + case 6: + d = 'u'; + break; + case 7: + d = 'b'; + break; + case 8: + d = 'n'; + break; + } + return(d); +} + +static void +heal(void) +{ + static short heal_exp = -1, n, c = 0; + static boolean alt; + + if (rogue.hp_current == rogue.hp_max) { + c = 0; + return; + } + if (rogue.exp != heal_exp) { + heal_exp = rogue.exp; + + switch(heal_exp) { + case 1: + n = 20; + break; + case 2: + n = 18; + break; + case 3: + n = 17; + break; + case 4: + n = 14; + break; + case 5: + n = 13; + break; + case 6: + n = 10; + break; + case 7: + n = 9; + break; + case 8: + n = 8; + break; + case 9: + n = 7; + break; + case 10: + n = 4; + break; + case 11: + n = 3; + break; + case 12: + default: + n = 2; + } + } + if (++c >= n) { + c = 0; + rogue.hp_current++; + if ((alt = !alt) != 0) { + rogue.hp_current++; + } + if ((rogue.hp_current += regeneration) > rogue.hp_max) { + rogue.hp_current = rogue.hp_max; + } + print_stats(STAT_HP); + } +} + +static boolean +can_turn(short nrow, short ncol) +{ + if ((dungeon[nrow][ncol] & TUNNEL) && is_passable(nrow, ncol)) { + return(1); + } + return(0); +} + +static void +turn_passage(short dir, boolean fast) +{ + short crow = rogue.row, ccol = rogue.col, turns = 0; + short ndir = 0; + + if ((dir != 'h') && can_turn(crow, ccol + 1)) { + turns++; + ndir = 'l'; + } + if ((dir != 'l') && can_turn(crow, ccol - 1)) { + turns++; + ndir = 'h'; + } + if ((dir != 'k') && can_turn(crow + 1, ccol)) { + turns++; + ndir = 'j'; + } + if ((dir != 'j') && can_turn(crow - 1, ccol)) { + turns++; + ndir = 'k'; + } + if (turns == 1) { + multiple_move_rogue(ndir - (fast ? 32 : 96)); + } +} |