Mercurial > hg > early-roguelike
diff urogue/move.c @ 256:c495a4f288c6
Import UltraRogue from the Roguelike Restoration Project (r1490)
author | John "Elwin" Edwards |
---|---|
date | Tue, 31 Jan 2017 19:56:04 -0500 |
parents | |
children | e52a8a7ad4c5 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/urogue/move.c Tue Jan 31 19:56:04 2017 -0500 @@ -0,0 +1,1837 @@ +/* + move.c - Hero movement commands + + UltraRogue: The Ultimate Adventure in the Dungeons of Doom + Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong + All rights reserved. + + Based on "Advanced Rogue" + Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka + All rights reserved. + + Based on "Rogue: Exploring the Dungeons of Doom" + Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + All rights reserved. + + See the file LICENSE.TXT for full copyright and licensing information. +*/ + +#include <stdlib.h> +#include <ctype.h> +#include "rogue.h" + +/* + do_run() + Start the hero running +*/ + +void +do_run(char ch) +{ + running = TRUE; + after = FALSE; + runch = ch; + + if (doorstop && !on(player, ISBLIND)) + { + door_stop = TRUE; + firstmove = TRUE; + } +} + +/* + step_ok() + returns true if it is ok for type to step on ch flgptr will be + NULL if we don't know what the monster is yet! +*/ + +int +step_ok(int y, int x, int can_on_monst, struct thing *flgptr) +{ + struct linked_list *item; + char ch; + + /* What is here? Don't check monster window if MONSTOK is set */ + + if (can_on_monst == MONSTOK) + ch = CCHAR( mvinch(y, x) ); + else + ch = winat(y, x); + + switch (ch) + { + case ' ': + case '|': + case '-': + case SECRETDOOR: + if (flgptr && on(*flgptr, CANINWALL)) + return(TRUE); + + return(FALSE); + + case SCROLL: + /* + * If it is a scroll, it might be a scare monster scroll so + * we need to look it up to see what type it is. + */ + + if (flgptr && flgptr->t_ctype == C_MONSTER) + { + item = find_obj(y, x); + + if (item != NULL && (OBJPTR(item))->o_type == SCROLL + && (OBJPTR(item))->o_which == S_SCARE + && rnd(flgptr->t_stats.s_intel) < 12) + return(FALSE); /* All but smart ones are scared */ + } + return(TRUE); + + default: + return(!isalpha(ch)); + } +} + +/* + corr_move() + Check to see that a move is legal. If so, return correct + character. If not, if player came from a legal place, then try to turn + him. +*/ + +void +corr_move(int dy, int dx) +{ + char ch; + short legal = 0; /* Number of legal alternatives */ + int y = 0, x = 0; /* Holds legal new position */ + int *ny, *nx; /* Point to which direction to change */ + + /* New position */ + + player.t_nxtpos.y = hero.y + dy; + player.t_nxtpos.x = hero.x + dx; + + /* A bad diagonal move is illegal */ + + if (!diag_ok(&hero, &player.t_nxtpos, &player)) + return; + + /* If it is a legal move, just return */ + + if (player.t_nxtpos.x >= 0 && player.t_nxtpos.x < COLS && player.t_nxtpos.y > 0 && player.t_nxtpos.y < LINES - 2) + { + ch = winat(player.t_nxtpos.y, player.t_nxtpos.x); + + switch (ch) + { + case ' ': + case '|': + case '-': + break; + default: + return; + } + } + + /* Check the legal alternatives */ + + if (dy == 0) + { + ny = &dy; + nx = &dx; + } + else + { + ny = &dx; + nx = &dy; + } + + for (*nx = 0, *ny = -1; *ny < 2; *ny += 2) + { + /* New position */ + player.t_nxtpos.y = hero.y + dy; + player.t_nxtpos.x = hero.x + dx; + + if (player.t_nxtpos.x < 0 || player.t_nxtpos.x > COLS - 1 || player.t_nxtpos.y < 1 || player.t_nxtpos.y > LINES - 3) + continue; + + ch = winat(player.t_nxtpos.y, player.t_nxtpos.x); + + switch (ch) + { + case ' ': + case '|': + case '-': + break; + default: + legal++; + y = dy; + x = dx; + } + } + + /* If we have 2 legal moves, make no change */ + + if (legal != 1) + return; + + /* Make the change */ + + if (y == 0) /* Move horizontally */ + { + if (x == 1) + runch = 'l'; + else + runch = 'h'; + } + else /* Move vertically */ + { + if (y == 1) + runch = 'j'; + else + runch = 'k'; + } + + return; +} + + +/* + do_move() + Check to see that a move is legal. If it is handle the + consequences (fighting, picking up, etc.) +*/ + +void +do_move(int dy, int dx) +{ + char ch; + coord old_hero; + char hch; + + firstmove = FALSE; + + if (player.t_no_move) + { + player.t_no_move--; + msg("You are still stuck in the bear trap."); + return; + } + + /* Do a confused move (maybe) */ + + if ((rnd(100) < 80 && on(player, ISHUH)) || + (is_wearing(R_DELUSION) && rnd(100) < 25) || + on(player, STUMBLER) && rnd(40) == 0) + player.t_nxtpos = rndmove(&player); + else + { + player.t_nxtpos.y = hero.y + dy; + player.t_nxtpos.x = hero.x + dx; + } + + /* + * Check if he tried to move off the screen or make an illegal + * diagonal move, and stop him if he did. + */ + + if (player.t_nxtpos.x < 0 || player.t_nxtpos.x > COLS - 1 || player.t_nxtpos.y < 1 || player.t_nxtpos.y >= LINES - 2 + || !diag_ok(&hero, &player.t_nxtpos, &player)) + { + after = fighting = running = FALSE; + return; + } + + if (running && ce(hero, player.t_nxtpos)) + after = running = FALSE; + + ch = winat(player.t_nxtpos.y, player.t_nxtpos.x); + + if (isalpha(ch)) + debug("Moving onto monster %c",ch); + + /* Take care of hero trying to move close to something frightening */ + + if (on(player, ISFLEE)) + { + if (rnd(10) < 1) + { + turn_off(player, ISFLEE); + msg("You regain your composure."); + } + else if (DISTANCE(player.t_nxtpos, player.t_chasee->t_pos) < + DISTANCE(hero,player.t_chasee->t_pos)) + return; + } + + /* Take care of hero being held */ + + if (on(player, ISHELD) && !isalpha(ch)) + { + if (rnd(pstats.s_str) > 14) + { + msg("You break free of the hold."); + + if (--hold_count == 0) + turn_off(player, ISHELD); + } + else + { + msg("You are being held."); + return; + } + } + + /* Might lose disguise */ + + if (on(player, ISDISGUISE) && rnd(11 * pstats.s_dext) == 0) + { + extinguish_fuse(FUSE_UNDISGUISE); + undisguise(NULL); + } + + /* assume he's not in a wall */ + + if (!isalpha(ch)) + turn_off(player, ISINWALL); + + hch = CCHAR( mvinch(hero.y, hero.x) ); /* Where hero was */ + old_hero = hero; /* Save hero's old position */ + + switch (ch) + { + case ' ': + case '|': + case '-': + case SECRETDOOR: + if (off(player, CANINWALL)) + { + after = running = FALSE; + return; + } + else if (running) + { + after = running = FALSE; + return; + } + turn_on(player, ISINWALL); + break; + + case TRAPDOOR: + case TELTRAP: + case BEARTRAP: + case SLEEPTRAP: + case ARROWTRAP: + case DARTTRAP: + case POOL: + case MAZETRAP: + case FIRETRAP: + case POISONTRAP: + case LAIR: + case RUSTTRAP: + ch = be_trapped(&player, player.t_nxtpos); + + if (!is_wearing(R_LEVITATION) && off(player, CANFLY) && + (old_hero.x != hero.x || old_hero.y != hero.y + || pool_teleport)) + { + pool_teleport = FALSE; + return; + } + + break; + + case GOLD: + case POTION: + case SCROLL: + case FOOD: + case WEAPON: + case ARMOR: + case RING: + case ARTIFACT: + case STICK: + running = FALSE; + take = ch; + break; + + default: + break; + } + + if (ch == FIRETRAP) + light(&hero); + + hero = player.t_nxtpos; /* Move the hero */ + + /* adjust lighting */ + + if (roomin(hero) == NULL && (hch == '-' || hch == '|' || + hch == DOOR || hch == SECRETDOOR)) + { + /* Leaving a room -- darken it */ + struct room *rp = roomin(old_hero); + int is_lit = FALSE; + + if (!(rp->r_flags & ISDARK)) + is_lit = TRUE; + + rp->r_flags |= ISDARK; /* Fake darkness */ + light(&old_hero); + + if (is_lit) + rp->r_flags &= ~ISDARK; /* Restore light state */ + } + else if (ch == DOOR || ch == SECRETDOOR || ch == '|' || ch == '-') + { + /* Entering a room */ + running = FALSE; + if (hch != '|' && hch != '-') + light(&hero); /* knows whether the hero can see things in */ + } + + /* handle other situations */ + + if (ch == STAIRS) + running = FALSE; + else if (ch == POST) + { + running = FALSE; + new_level(POSTLEV,0); + return; + } + else if (isalpha(ch)) + { + struct linked_list *mp; + struct thing *tp; + char t; + + running = FALSE; + + mp = find_mons(hero.y, hero.x); + + if (mp == NULL) + return; + + tp = THINGPTR(mp); + + if (good_monster(*tp)) /* Exchange places with your buddy */ + { + mvwaddch(cw, old_hero.y, old_hero.x, ch); + mvwaddch(mw, old_hero.y, old_hero.x, ch); + mvwaddch(mw, hero.y, hero.x, ' '); + mvwaddch(cw, hero.y, hero.x, tp->t_oldch); + + (*tp).t_pos.x = old_hero.x; /* Update monster position variables */ + (*tp).t_pos.y = old_hero.y; + (*tp).t_oldpos.x = old_hero.x; + (*tp).t_oldpos.y = old_hero.y; + + t = (*tp).t_oldch; + (*tp).t_oldch = player.t_oldch; + player.t_oldch = t; + + turn_on(*tp, ISRUN); + + mvwaddch(cw, hero.y, hero.x, PLAYER); + + /* make sure that the room shows OK */ + + light(&hero); + + wrefresh(cw); + return; + } + else + { + hero = old_hero; /* Restore hero -- we'll fight instead of move */ + + /* make sure that the room shows OK */ + light(&hero); + + fight(&player.t_nxtpos, cur_weapon, NOTHROWN); + + return; + } + } + else + fighting = FALSE; + + ch = winat(old_hero.y, old_hero.x); + mvwaddch(cw, old_hero.y, old_hero.x, ch); + mvwaddch(cw, hero.y, hero.x, PLAYER); +} + +/* + light() + Called to illuminate a room. If it is dark, remove anything that might + move. +*/ + +void +light(coord *cp) +{ + struct room *rp; + int j, k, x, y; + char ch, rch; + struct linked_list *item; + int jlow, jhigh, klow, khigh; /* Boundaries of lit area */ + + if ((rp = roomin(*cp)) != NULL && !on(player, ISBLIND)) + { + + /* is he wearing ring of illumination and in same room? */ + + if ((is_wearing(R_LIGHT) || on(player, ISELECTRIC)) && + cp == &hero) + rp->r_flags &= ~ISDARK; + + /* If we are in a maze, don't look at the whole room (level) */ + + if (levtype == MAZELEV) + { + jlow = max(0, hero.y - 2 - rp->r_pos.y); + jhigh = min(rp->r_max.y, hero.y + 2 - rp->r_pos.y + 1); + klow = max(0, hero.x - 2 - rp->r_pos.x); + khigh = min(rp->r_max.x, hero.x + 2 - rp->r_pos.x + 1); + } + else + { + jlow = klow = 0; + jhigh = rp->r_max.y; + khigh = rp->r_max.x; + } + + for (j = 0; j < rp->r_max.y; j++) + { + for (k = 0; k < rp->r_max.x; k++) + { + /* Is this in the given area -- needed for maze */ + + if ((j < jlow || j >= jhigh) && (k < klow || k >= khigh)) + continue; + + y = rp->r_pos.y + j; + x = rp->r_pos.x + k; + + ch = show(y, x); + wmove(cw, y, x); + + /* Figure out how to display a secret door */ + + if (ch == SECRETDOOR) + { + if (j == 0 || j == rp->r_max.y - 1) + ch = '-'; + else + ch = '|'; + } + + /* + * For monsters, if they were previously not + * seen and now can be seen, or vice-versa, + * make sure that will happen. + */ + + if (isalpha(ch)) + { + struct thing *tp; + + item = wake_monster(y, x); + + if (item == NULL) + continue; + + tp = THINGPTR(item); + + /* Previously not seen -- now can see it */ + + if (tp->t_oldch == ' ' && cansee(tp->t_pos.y, tp->t_pos.x)) + tp->t_oldch = CCHAR( mvinch(y, x) ); + + /* Previously seen -- now can't see it */ + + else if (off(player, ISBLIND) && tp->t_oldch != ' ' && + !cansee(tp->t_pos.y, tp->t_pos.x)) + tp->t_oldch = ' '; + } + + /* + * If the room is a dark room, we might want + * to remove monsters and the like from it + * (since they might move). A dark room or + * not in line-of-sight in a maze. + */ + + if (((rp->r_flags & ISDARK) && + !(rp->r_flags & HASFIRE)) || + (levtype == MAZELEV && + !maze_view(y, x))) + { + rch = CCHAR( mvwinch(cw, y, x) ); + + switch (rch) + { + case DOOR: + case STAIRS: + case TRAPDOOR: + case TELTRAP: + case BEARTRAP: + case SLEEPTRAP: + case ARROWTRAP: + case DARTTRAP: + case POOL: + case MAZETRAP: + case FIRETRAP: + case POISONTRAP: + case LAIR: + case RUSTTRAP: + case POST: + case '|': + case '-': + case ' ': + ch = rch; + break; + + case FLOOR: + ch = (on(player, ISBLIND) ? FLOOR : ' '); + break; + default: + ch = ' '; + break; + } + } + mvwaddch(cw, y, x, ch); + } + } + } +} + +/* + blue_light() + magically light up a room (or level or make it dark) +*/ + +int +blue_light(int flags) +{ + struct room *rp; + int blessed = (flags & ISBLESSED); + int cursed = (flags & ISCURSED); + int ret_val = FALSE; /* Whether or not affect is known */ + + rp = roomin(hero); /* What room is hero in? */ + + /* Darken the room if the magic is cursed */ + + if (cursed) + { + if ((rp == NULL) || (rp->r_flags & ISDARK)) + nothing_message(flags); + else + { + if (!(rp->r_flags & HASFIRE)) + msg("The room suddenly goes dark."); + else + nothing_message(flags); + + rp->r_flags |= ISDARK; + ret_val = TRUE; + } + } + else + { + ret_val = TRUE; + + if (rp && (rp->r_flags & ISDARK) && !(rp->r_flags & HASFIRE)) + { + msg("The room is lit by a %s blue light.", + blessed ? "bright" : "shimmering"); + } + else if (winat(hero.y, hero.x) == PASSAGE) + msg("The corridor glows %sand then fades.", blessed ? "brightly " : ""); + else + { + ret_val = FALSE; + nothing_message(flags); + } + + if (blessed) + { + short i; /* Index through rooms */ + + for (i = 0; i < MAXROOMS; i++) + rooms[i].r_flags &= ~ISDARK; + } + else if (rp) + rp->r_flags &= ~ISDARK; + } + + /* Light the room and put the player back up */ + + light(&hero); + mvwaddch(cw, hero.y, hero.x, PLAYER); + + return (ret_val); +} + +/*