There should only be two changes in behavior: arogue7/fight.c, arogue7/fight.c: a to-hit bonus is now correctly applied to characters who are not monks instead of monks who are not empty-handed. urogue/fight.c: fixed an interaction with the "debug" macro that could cause the wrong message to be displayed.
1839 lines
49 KiB
C
1839 lines
49 KiB
C
/*
|
|
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);
|
|
}
|
|
|
|
/*
|
|
show()
|
|
returns what a certain thing will display as to the un-initiated
|
|
*/
|
|
|
|
char
|
|
show(int y, int x)
|
|
{
|
|
char ch = winat(y, x);
|
|
struct linked_list *it;
|
|
struct thing *tp;
|
|
|
|
if (isatrap(ch))
|
|
{
|
|
struct trap *trp = trap_at(y, x);
|
|
return (trp->tr_flags & ISFOUND) ? ch : trp->tr_show;
|
|
}
|
|
else if (isalpha(ch))
|
|
{
|
|
if ((it = find_mons(y, x)) == NULL)
|
|
{
|
|
debug("Can't find monster in move.");
|
|
return ' ';
|
|
}
|
|
tp = THINGPTR(it);
|
|
|
|
if (on(*tp, ISDISGUISE))
|
|
ch = tp->t_disguise; /* As a mimic */
|
|
else if (on(*tp, ISINVIS) || (on(*tp, ISSHADOW) &&
|
|
rnd(100) < 90) || on(*tp, CANSURPRISE))
|
|
{
|
|
if (off(player, CANSEE) || on(*tp, CANSURPRISE))
|
|
ch = CCHAR( mvwinch(stdscr, y, x) ); /* Invisible */
|
|
}
|
|
else if (on(*tp, CANINWALL))
|
|
{
|
|
char tch;
|
|
|
|
tch = CCHAR( mvwinch(stdscr, y, x) );
|
|
|
|
if (tch == WALL || tch == '-' || tch == '|')
|
|
ch = CCHAR( winch(stdscr) ); /* As Xorn */
|
|
}
|
|
}
|
|
return(ch);
|
|
}
|
|
|
|
/*
|
|
be_trapped()
|
|
The guy stepped on a trap.... Make him pay.
|
|
*/
|
|
|
|
char
|
|
be_trapped(struct thing *th, coord tc)
|
|
{
|
|
struct trap *tp;
|
|
char ch, *mname = NULL;
|
|
int is_player = (th == &player), can_see = cansee(tc.y, tc.x);
|
|
struct linked_list *mitem = NULL;
|
|
|
|
tp = trap_at(tc.y, tc.x);
|
|
ch = tp->tr_type;
|
|
|
|
if (!is_player)
|
|
{
|
|
mitem = find_mons(th->t_pos.y, th->t_pos.x);
|
|
mname = monsters[th->t_index].m_name;
|
|
|
|
/* Flying monsters do not set off traps */
|
|
|
|
if (!mitem || (on(*th, CANFLY) &&
|
|
(ch == BEARTRAP || ch == MAZETRAP || ch == TRAPDOOR
|
|
|| ch == ARROWTRAP || ch == DARTTRAP)))
|
|
{
|
|
debug("%s avoided trap.", mname);
|
|
return(ch);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
short thief_bonus = -50;
|
|
|
|
count = running = FALSE;
|
|
mvwaddch(cw, tp->tr_pos.y, tp->tr_pos.x, tp->tr_type);
|
|
|
|
if (no_command)
|
|
return(ch);
|
|
|
|
if (player.t_ctype == C_THIEF || player.t_ctype == C_NINJA)
|
|
thief_bonus = 10;
|
|
|
|
if (((is_wearing(R_LEVITATION) || on(player, CANFLY)) &&
|
|
(ch != FIRETRAP ||
|
|
(ch == FIRETRAP && !(tp->tr_flags & ISFOUND))))
|
|
|| ((moving && (tp->tr_flags & ISFOUND) && rnd(100) <
|
|
thief_bonus + 2 * pstats.s_dext + 5 * pstats.s_lvl) &&
|
|
(ch == BEARTRAP || ch == MAZETRAP || ch == TRAPDOOR
|
|
|| ch == ARROWTRAP || ch == DARTTRAP)))
|
|
{
|
|
static char trname[1024];
|
|
msg(tr_name(ch,trname));
|
|
tp->tr_flags |= ISFOUND;
|
|
return(ch);
|
|
}
|
|
|
|
if (moving)
|
|
msg("Your attempt fails.");
|
|
}
|
|
|
|
tp->tr_flags |= ISFOUND;
|
|
|
|
switch(ch)
|
|
{
|
|
case TRAPDOOR:
|
|
if (is_player)
|
|
{
|
|
level++;
|
|
new_level(NORMLEV,0);
|
|
addmsg("You fell into a trap");
|
|
|
|
if (player.t_ctype != C_THIEF
|
|
&& player.t_ctype != C_ASSASIN
|
|
&& player.t_ctype != C_NINJA
|
|
&& rnd(pstats.s_dext) < 4)
|
|
{
|
|
addmsg(" and were damaged by the fall");
|
|
|
|
if ((pstats.s_hpt -= roll(1, 6)) <= 0)
|
|
{
|
|
addmsg("! The fall killed you.");
|
|
endmsg();
|
|
death(D_FALL);
|
|
|
|
return(ch);
|
|
}
|
|
}
|
|
|
|
addmsg("!");
|
|
endmsg();
|
|
|
|
if (off(player, ISCLEAR) && rnd(4) < 3)
|
|
{
|
|
if (on(player, ISHUH))
|
|
lengthen_fuse(FUSE_UNCONFUSE, rnd(8) + HUHDURATION);
|
|
else
|
|
light_fuse(FUSE_UNCONFUSE,0,rnd(8)+HUHDURATION, AFTER);
|
|
|
|
turn_on(player, ISHUH);
|
|
}
|
|
else
|
|
msg("You feel dizzy for a moment, but it quickly passes.");
|
|
}
|
|
else
|
|
{
|
|
if (can_see)
|
|
msg("The %s fell into a trap!", mname);
|
|
|
|
if (on(*th, ISFAMILIAR))
|
|
turn_off(player, HASFAMILIAR);
|
|
|
|
killed(NULL,mitem,NOMESSAGE,NOPOINTS);
|
|
}
|
|
break;
|
|
|
|
case BEARTRAP:
|
|
if (is_stealth(th))
|
|
{
|
|
if (is_player)
|
|
msg("You pass a bear trap.");
|
|
else if (can_see)
|
|
msg("The %s passes a bear trap.", mname);
|
|
}
|
|
else
|
|
{
|
|
th->t_no_move += BEARTIME;
|
|
|
|
if (is_player)
|
|
msg("You are caught in a bear trap.");
|
|
else if (can_see)
|
|
msg("The %s is caught in a bear trap.", mname);
|
|
}
|
|
break;
|
|
|
|
case SLEEPTRAP:
|
|
if (is_player)
|
|
{
|
|
msg("A strange white mist envelops you.");
|
|
|
|
if (!is_wearing(R_ALERT))
|
|
{
|
|
if (!is_wearing(R_BREATHE) && off(player, HASOXYGEN))
|
|
{
|
|
msg("You fall asleep.");
|
|
no_command += SLEEPTIME;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (can_see)
|
|
msg("A strange white mist envelops the %s.", mname);
|
|
|
|
if (on(*th, ISUNDEAD))
|
|
{
|
|
if (can_see)
|
|
msg("The mist doesn't seem to affect the %s.", mname);
|
|
}
|
|
|
|
if (on(*th, ISUNDEAD) || on(*th, HASOXYGEN))
|
|
{
|
|
if (can_see)
|
|
msg("The mist doesn't seem to affect the %s.", mname);
|
|
}
|
|
else
|
|
{
|
|
th->t_no_move += SLEEPTIME;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ARROWTRAP:
|
|
if (swing(th->t_ctype, th->t_stats.s_lvl - 1, th->t_stats.s_arm, 1))
|
|
{
|
|
if (is_player)
|
|
{
|
|
msg("Oh no! An arrow shot you.");
|
|
|
|
if ((pstats.s_hpt -= roll(1, 6)) <= 0)
|
|
{
|
|
msg("The arrow killed you.");
|
|
death(D_ARROW);
|
|
return(ch);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (can_see)
|
|
msg("An arrow shot the %s.", mname);
|
|
|
|
if (on(*th, NOSHARP))
|
|
{
|
|
if (can_see)
|
|
msg("The arrow has no effect!");
|
|
}
|
|
else
|
|
{
|
|
if ((th->t_stats.s_hpt -= roll(1, 6)) <= 0)
|
|
{
|
|
if (can_see)
|
|
msg("The arrow killed the %s.", mname);
|
|
|
|
if (on(*th, ISFAMILIAR))
|
|
turn_off(player, HASFAMILIAR);
|
|
|
|
killed(NULL, mitem, NOMESSAGE, NOPOINTS);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
struct linked_list *itm;
|
|
struct object *an_arrow;
|
|
|
|
if (is_player)
|
|
msg("An arrow shoots past you.");
|
|
else if (can_see)
|
|
msg("An arrow shoots by the %s.", mname);
|
|
|
|
itm = new_item(sizeof *an_arrow);
|
|
an_arrow = OBJPTR(itm);
|
|
an_arrow->o_type = WEAPON;
|
|
an_arrow->o_which = ARROW;
|
|
an_arrow->o_hplus = rnd(3) - 1;
|
|
an_arrow->o_dplus = rnd(3) - 1;
|
|
init_weapon(an_arrow, ARROW);
|
|
an_arrow->o_count = 1;
|
|
an_arrow->o_pos = tc;
|
|
an_arrow->o_mark[0] = '\0';
|
|
fall(&player, itm, FALSE, FALSE);
|
|
}
|
|
break;
|
|
|
|
case TELTRAP:
|
|
if (is_player)
|
|
{
|
|
teleport();
|
|
|
|
if (off(player, ISCLEAR))
|
|
{
|
|
msg("Wait, what's going on here. Huh? What? Who?");
|
|
|
|
if (on(player, ISHUH))
|
|
lengthen_fuse(FUSE_UNCONFUSE, rnd(8) + HUHDURATION);
|
|
else
|
|
light_fuse(FUSE_UNCONFUSE,0,rnd(8)+HUHDURATION, AFTER);
|
|
|
|
turn_on(player, ISHUH);
|
|
}
|
|
else
|
|
msg("You feel dizzy for a moment, but it quickly passes.");
|
|
}
|
|
else
|
|
{
|
|
int rm;
|
|
|
|
/* Erase the monster from the old position */
|
|
|
|
if (isalpha(mvwinch(cw, th->t_pos.y, th->t_pos.x)))
|
|
mvwaddch(cw, th->t_pos.y, th->t_pos.x, th->t_oldch);
|
|
|
|
mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' ');
|
|
|
|
/* Get a new position */
|
|
|
|
do
|
|
{
|
|
rm = rnd_room();
|
|
rnd_pos(&rooms[rm], &th->t_pos);
|
|
}
|
|
while(winat(th->t_pos.y, th->t_pos.x) != FLOOR);
|
|
|
|
/* Put it there */
|
|
|
|
mvwaddch(mw, th->t_pos.y, th->t_pos.x, th->t_type);
|
|
th->t_oldch = CCHAR( mvwinch(cw, th->t_pos.y, th->t_pos.x) );
|
|
|
|
if (can_see)
|
|
msg("The %s seems to have disappeared!", mname);
|
|
}
|
|
break;
|
|
|
|
case DARTTRAP:
|
|
|
|
if (swing(th->t_ctype, th->t_stats.s_lvl + 1,th->t_stats.s_arm, 1))
|
|
{
|
|
if (is_player)
|
|
{
|
|
msg("A small dart just hit you in the shoulder.");
|
|
|
|
if ((pstats.s_hpt -= roll(1, 4)) <= 0)
|
|
{
|
|
msg("The dart killed you.");
|
|
death(D_DART);
|
|
return(ch);
|
|
}
|
|
|
|
/* Now the poison */
|
|
|
|
if (player.t_ctype != C_PALADIN
|
|
&& !(player.t_ctype == C_NINJA &&
|
|
pstats.s_lvl > 12) && !save(VS_POISON))
|
|
{
|
|
|
|
/*
|
|
* 75% chance it will do point
|
|
* damage - else strength
|
|
*/
|
|
|
|
if (rnd(100) < 75)
|
|
{
|
|
pstats.s_hpt /= 2;
|
|
|
|
if (pstats.s_hpt == 0)
|
|
{
|
|
death(D_POISON);
|
|
return(ch);
|
|
}
|
|
}
|
|
else if (!is_wearing(R_SUSABILITY))
|
|
chg_str(-1, FALSE, FALSE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int orig_hp = th->t_stats.s_hpt;
|
|
|
|
if (can_see)
|
|
msg("A small dart just hit the %s.", mname);
|
|
|
|
/*
|
|
* Poison has no effect on poisonous or
|
|
* undead monsters
|
|
*/
|
|
|
|
if (off(*th, CANPOISON) &&
|
|
off(*th, ISUNDEAD) &&
|
|
!save_throw(VS_POISON, th))
|
|
th->t_stats.s_hpt /= 2;
|
|
|
|
/* Now the dart damage */
|
|
|
|
if (off(*th, NOSHARP))
|
|
th->t_stats.s_hpt -= roll(1, 4);
|
|
|
|
if (orig_hp == th->t_stats.s_hpt)
|
|
{
|
|
if (can_see)
|
|
msg("The dart has not effect!");
|
|
else if (th->t_stats.s_hpt < 0)
|
|
{
|
|
if (can_see)
|
|
msg("The dart killed the %s.", mname);
|
|
|
|
if (on(*th, ISFAMILIAR))
|
|
turn_off(player, HASFAMILIAR);
|
|
|
|
killed(NULL, mitem, NOMESSAGE, NOPOINTS);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (is_player)
|
|
msg("A small dart whizzes by your ear and vanishes.");
|
|
else if (can_see)
|
|
msg("A small dart whizzes by the %s and vanishes.", mname);
|
|
}
|
|
break;
|
|
|
|
case POOL:
|
|
{
|
|
int i;
|
|
|
|
i = rnd(100);
|
|
|
|
if (is_player)
|
|
{
|
|
if (on(player, ISELECTRIC))
|
|
{
|
|
msg("Oh no!!! The water shorts you out");
|
|
extinguish_fuse(FUSE_UNELECTRIFY);
|
|
turn_off(player, ISELECTRIC);
|
|
|
|
if (!is_wearing(R_ELECTRESIST))
|
|
{
|
|
if ((pstats.s_hpt -= roll(1, 10)) <= 0)
|
|
{
|
|
addmsg("! The shock killed you.");
|
|
endmsg();
|
|
death(D_DROWN);
|
|
return(ch);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((tp->tr_flags & ISGONE))
|
|
{
|
|
if (i < 30)
|
|
{
|
|
teleport(); /* teleport away */
|
|
|
|
if (off(player, ISCLEAR))
|
|
{
|
|
if (on(player, ISHUH))
|
|
lengthen_fuse(FUSE_UNCONFUSE,rnd(8)+HUHDURATION);
|
|
else
|
|
light_fuse(FUSE_UNCONFUSE,0,rnd(8)+HUHDURATION,AFTER);
|
|
turn_on(player, ISHUH);
|
|
}
|
|
else
|
|
msg("You feel dizzy for a moment, but it quickly passes.");
|
|
|
|
pool_teleport = TRUE;
|
|
}
|
|
else if ((i < 45) && level > 2)
|
|
{
|
|
level -= rnd(2) + 1;
|
|
new_level(NORMLEV,0);
|
|
pool_teleport = TRUE;
|
|
msg("You here a faint groan from below.");
|
|
|
|
if (off(player, ISCLEAR))
|
|
{
|
|
if (on(player, ISHUH))
|
|
lengthen_fuse(FUSE_UNCONFUSE,rnd(8)+HUHDURATION);
|
|
else
|
|
light_fuse(FUSE_UNCONFUSE, 0, rnd(8) + HUHDURATION, AFTER);
|
|
|
|
turn_on(player, ISHUH);
|
|
}
|
|
else
|
|
msg("You feel dizzy for a moment, but it quickly passes.");
|
|
}
|
|
else if (i < 70)
|
|
{
|
|
level += rnd(4) + 1;
|
|
new_level(NORMLEV,0);
|
|
pool_teleport = TRUE;
|
|
msg("You find yourself in strange surroundings.");
|
|
|
|
if (off(player, ISCLEAR))
|
|
{
|
|
if (on(player, ISHUH))
|
|
lengthen_fuse(FUSE_UNCONFUSE, rnd(8) + HUHDURATION);
|
|
else
|
|
light_fuse(FUSE_UNCONFUSE, 0, rnd(8) + HUHDURATION, AFTER);
|
|
|
|
turn_on(player, ISHUH);
|
|
}
|
|
else
|
|
msg("You feel dizzy for a moment, but it quickly passes.");
|
|
}
|
|
else if (i > 95)
|
|
{
|
|
if (is_wearing(R_BREATHE) || on(player, HASOXYGEN))
|
|
msg("You splash in the pool unharmed.");
|
|
else
|
|
{
|
|
msg("Oh no!!! You drown in the pool!!! --More--");
|
|
wait_for(' ');
|
|
death(D_DROWN);
|
|
return(ch);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (can_see)
|
|
msg("The %s fell into the pool!", mname);
|
|
|
|
if (i < 15)
|
|
{
|
|
if (off(*th, HASOXYGEN))
|
|
{
|
|
if (can_see)
|
|
msg("The %s has drowned!", mname);
|
|
|
|
if (on(*th, ISFAMILIAR))
|
|
turn_off(player, HASFAMILIAR);
|
|
|
|
killed(NULL, mitem, NOMESSAGE, NOPOINTS);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MAZETRAP:
|
|
|
|
if (is_player)
|
|
{
|
|
level++;
|
|
new_level(MAZELEV,0);
|
|
addmsg("You are surrounded by twisty passages");
|
|
|
|
if (rnd(4) < 1)
|
|
{
|
|
addmsg(" and were damaged by the fall");
|
|
|
|
if ((pstats.s_hpt -= roll(1, 6)) <= 0)
|
|
{
|
|
addmsg("! The fall killed you.");
|
|
endmsg();
|
|
death(D_FALL);
|
|
return(ch);
|
|
}
|
|
}
|
|
|
|
addmsg("!");
|
|
endmsg();
|
|
|
|
if (off(player, ISCLEAR))
|
|
{
|
|
if (on(player, ISHUH))
|
|
lengthen_fuse(FUSE_UNCONFUSE, rnd(8) + HUHDURATION);
|
|
else
|
|
{
|
|
light_fuse(FUSE_UNCONFUSE, 0, rnd(8) + HUHDURATION, AFTER);
|
|
turn_on(player, ISHUH);
|
|
}
|
|
}
|
|
else
|
|
msg("You feel dizzy for a moment, but it quickly passes.");
|
|
}
|
|
else
|
|
{
|
|
if (can_see)
|
|
msg("The %s fell into a trap!", mname);
|
|
|
|
if (on(*th, ISFAMILIAR))
|
|
turn_off(player, HASFAMILIAR);
|
|
|
|
killed(NULL, mitem, NOMESSAGE, NOPOINTS);
|
|
}
|
|
break;
|
|
|
|
case FIRETRAP:
|
|
{
|
|
struct room *rp = roomin(hero);
|
|
|
|
if (is_player)
|
|
{
|
|
if (is_wearing(R_FIRERESIST) || on(player, NOFIRE))
|
|
msg("You pass through the flames unharmed.");
|
|
else
|
|
{
|
|
addmsg("You are burned by the flames");
|
|
|
|
if ((pstats.s_hpt -= roll(pstats.s_lvl, 2)) <= 0)
|
|
{
|
|
addmsg("! The flames killed you.");
|
|
endmsg();
|
|
death(D_FIRE);
|
|
return(ch);
|
|
}
|
|
|
|
addmsg("!");
|
|
|
|
endmsg();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (on(*th, CANBBURN))
|
|
{
|
|
if (can_see)
|
|
msg("The %s is burned to death by the flames.", mname);
|
|
|
|
killed(NULL, mitem, NOMESSAGE, NOPOINTS);
|
|
}
|
|
else if (on(*th, NOFIRE))
|
|
{
|
|
if (can_see)
|
|
msg("The %s passes through the flames unharmed.", mname);
|
|
}
|
|
else
|
|
{
|
|
if (can_see)
|
|
msg("The %s is burned by the flames.", mname);
|
|
|
|
if ((th->t_stats.s_hpt -= roll(th->t_stats.s_lvl, 3)) < 0)
|
|
{
|
|
if (can_see)
|
|
msg("The %s is burned to death by the flames.", mname);
|
|
|
|
if (on(*th, ISFAMILIAR))
|
|
turn_off(player, HASFAMILIAR);
|
|
|
|
killed(NULL, mitem, NOMESSAGE, NOPOINTS);
|
|
}
|
|
else if (th->t_stats.s_intel < rnd(20))
|
|
{
|
|
if (can_see)
|
|
msg("The %s turns and runs away in fear.", mname);
|
|
|
|
turn_on(*th, ISFLEE);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (rp != NULL)
|
|
{
|
|
rp->r_flags &= ~ISDARK;
|
|
light(&hero);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case POISONTRAP:
|
|
if (is_player)
|
|
{
|
|
msg("You fall into a pool of poison.");
|
|
|
|
if (rnd(4) > 0)
|
|
{
|
|
msg("You swallow some of the liquid and feel very sick.");
|
|
pstats.s_hpt -= pstats.s_hpt / 3;
|
|
|
|
if (player.t_ctype != C_PALADIN
|
|
&& !(player.t_ctype == C_NINJA &&
|
|
pstats.s_lvl > 12)
|
|
&& !is_wearing(R_SUSABILITY))
|
|
chg_str(-2, FALSE, FALSE);
|
|
}
|
|
else
|
|
msg("The stuff tastes horrible.");
|
|
}
|
|
else
|
|
{
|
|
if (can_see)
|
|
msg("The %s falls into the pool of poison.", mname);
|
|
|
|
if (rnd(4) > 0 && off(*th, ISUNDEAD))
|
|
if (th->t_stats.s_hpt *= 2.0 / 3.0 < 0)
|
|
{
|
|
if (can_see)
|
|
msg("The %s dies from the poison.", mname);
|
|
|
|
if (on(*th, ISFAMILIAR))
|
|
turn_off(player, HASFAMILIAR);
|
|
|
|
killed(NULL, mitem, NOMESSAGE, NOPOINTS);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case LAIR:
|
|
if (is_player)
|
|
{
|
|
msg("You found a monster lair!");
|
|
mpos = 0;
|
|
new_level(THRONE,0);
|
|
}
|
|
else
|
|
{
|
|
if (can_see)
|
|
msg("The %s fell into a trap!", mname);
|
|
|
|
if (on(*th, ISFAMILIAR))
|
|
turn_off(player, HASFAMILIAR);
|
|
|
|
killed(NULL, mitem, NOMESSAGE, NOPOINTS);
|
|
}
|
|
break;
|
|
|
|
case RUSTTRAP:
|
|
if (is_player)
|
|
{
|
|
msg("You are splashed by water.");
|
|
|
|
if (cur_armor != NULL &&
|
|
cur_armor->o_which != SOFT_LEATHER &&
|
|
cur_armor->o_which != HEAVY_LEATHER &&
|
|
cur_armor->o_which != CUIRBOLILLI &&
|
|
cur_armor->o_which != PADDED_ARMOR &&
|
|
cur_armor->o_which != CRYSTAL_ARMOR &&
|
|
cur_armor->o_which != MITHRIL &&
|
|
!(cur_armor->o_flags & ISPROT) &&
|
|
cur_armor->o_ac < pstats.s_arm + 1)
|
|
{
|
|
msg("Your armor weakens!");
|
|
cur_armor->o_ac++;
|
|
}
|
|
else if (cur_armor != NULL && (cur_armor->o_flags & ISPROT))
|
|
msg("The rust vanishes instantly!");
|
|
}
|
|
else
|
|
{
|
|
if (can_see)
|
|
msg("The %s is splashed by water.", mname);
|
|
}
|
|
}
|
|
|
|
return(ch);
|
|
}
|
|
|
|
/*
|
|
dip_it()
|
|
Dip an object into a magic pool
|
|
*/
|
|
|
|
void
|
|
dip_it(void)
|
|
{
|
|
struct linked_list *what;
|
|
struct object *ob;
|
|
struct trap *tp;
|
|
int wh, i;
|
|
|
|
tp = trap_at(hero.y, hero.x);
|
|
|
|
if (tp == NULL || !(tp->tr_type == POOL || tp->tr_type == POISONTRAP))
|
|
{
|
|
msg("I see no pools here.");
|
|
return;
|
|
}
|
|
|
|
if (tp->tr_flags & ISGONE)
|
|
{
|
|
msg("This %s appears to have been used once already.",
|
|
(tp->tr_type == POOL ? "shimmering pool" : "poison pool"));
|
|
return;
|
|
}
|
|
|
|
if ((what = get_item("dip", 0)) == NULL)
|
|
{
|
|
msg("");
|
|
after = FALSE;
|
|
return;
|
|
}
|
|
|
|
ob = OBJPTR(what);
|
|
mpos = 0;
|
|
|
|
if (ob == cur_armor)
|
|
{
|
|
msg("You have to take off your armor before you can dip it.");
|
|
return;
|
|
}
|
|
else if (ob == cur_ring[LEFT_1] || ob == cur_ring[LEFT_2] ||
|
|
ob == cur_ring[LEFT_3] || ob == cur_ring[LEFT_4] ||
|
|
ob == cur_ring[RIGHT_1] || ob == cur_ring[RIGHT_2] ||
|
|
ob == cur_ring[RIGHT_3] || ob == cur_ring[RIGHT_4])
|
|
{
|
|
msg("You have to take that ring off before you can dip it.");
|
|
return;
|
|
}
|
|
|
|
tp->tr_flags |= ISGONE;
|
|
|
|
if (ob != NULL && tp->tr_type == POOL)
|
|
{
|
|
wh = ob->o_which;
|
|
ob->o_flags |= ISKNOW;
|
|
i = rnd(100);
|
|
|
|
switch (ob->o_type)
|
|
{
|
|
case WEAPON:
|
|
if (i < 50)
|
|
{
|
|
if (!(ob->o_flags & ISCURSED))
|
|
{
|
|
ob->o_hplus += 1;
|
|
ob->o_dplus += 1;
|
|
}
|
|
else
|
|
{
|
|
ob->o_hplus = rnd(2);
|
|
ob->o_dplus = rnd(2);
|
|
}
|
|
|
|
ob->o_flags &= ~ISCURSED;
|
|
msg("The %s glows blue for a moment.", weaps[wh].w_name);
|
|
}
|
|
else if (i < 70) /* curse weapon here */
|
|
{
|
|
if (!(ob->o_flags & ISCURSED))
|
|
{
|
|
ob->o_hplus = -(rnd(2) + 1);
|
|
ob->o_dplus = -(rnd(2) + 1);
|
|
}
|
|
else /* if already cursed */
|
|
{
|
|
ob->o_hplus--;
|
|
ob->o_dplus--;
|
|
}
|
|
|
|
ob->o_flags |= ISCURSED;
|
|
msg("The %s glows red for a moment.", weaps[wh].w_name);
|
|
}
|
|
else
|
|
msg("Nothing seems to happen.");
|
|
break;
|
|
|
|
case ARMOR:
|
|
|
|
if (i < 50) /* enchant armor */
|
|
{
|
|
if (!(ob->o_flags & ISCURSED))
|
|
ob->o_ac -= rnd(2) + 1;
|
|
else
|
|
ob->o_ac = -rnd(3) + armors[wh].a_class;
|
|
|
|
ob->o_flags &= ~ISCURSED;
|
|
msg("The %s glows blue for a moment.", armors[wh].a_name);
|
|
}
|
|
else if (i < 75) /* curse armor */
|
|
{
|
|
if (!(ob->o_flags & ISCURSED))
|
|
ob->o_ac = rnd(3) + armors[wh].a_class;
|
|
else
|
|
ob->o_ac += rnd(2) + 1;
|
|
|
|
ob->o_flags |= ISCURSED;
|
|
msg("The %s glows red for a moment.", armors[wh].a_name);
|
|
}
|
|
else
|
|
msg("Nothing seems to happen");
|
|
break;
|
|
|
|
case STICK:
|
|
{
|
|
int j;
|
|
|
|
j = rnd(8) + 1;
|
|
|
|
if (i < 50) /* add charges */
|
|
{
|
|
ob->o_charges += j;
|
|
know_items[TYP_STICK][wh] = TRUE;
|
|
|
|
if (ob->o_flags & ISCURSED)
|
|
ob->o_flags &= ~ISCURSED;
|
|
|
|
msg("The %s %s glows blue for a moment.",
|
|
ws_made[wh], ws_type[wh]);
|
|
}
|
|
else if (i < 65) /* remove charges */
|
|
{
|
|
if ((ob->o_charges -= i) < 0)
|
|
ob->o_charges = 0;
|
|
|
|
know_items[TYP_STICK][wh] = TRUE;
|
|
|
|
if (ob->o_flags & ISBLESSED)
|
|
ob->o_flags &= ~ISBLESSED;
|
|
else
|
|
ob->o_flags |= ISCURSED;
|
|
|
|
msg("The %s %s glows red for a moment.",
|
|
ws_made[wh], ws_type[wh]);
|
|
}
|
|
else
|
|
msg("Nothing seems to happen.");
|
|
}
|
|
break;
|
|
|
|
case SCROLL:
|
|
|
|
know_items[TYP_SCROLL][wh] = TRUE;
|
|
msg("The '%s' scroll unfurls.", s_names[wh]);
|
|
break;
|
|
|
|
case POTION:
|
|
|
|
know_items[TYP_POTION][wh] = TRUE;
|
|
msg("The %s potion bubbles for a moment.", p_colors[wh]);
|
|
break;
|
|
|
|
case RING:
|
|
if (i < 50) /* enchant ring */
|
|
{
|
|
if (!(ob->o_flags & ISCURSED))
|
|
ob->o_ac += rnd(2) + 1;
|
|
else
|
|
ob->o_ac = rnd(2) + 1;
|
|
|
|
ob->o_flags &= ~ISCURSED;
|
|
}
|
|
else if (i < 80) /* curse ring */
|
|
{
|
|
if (!(ob->o_flags & ISCURSED))
|
|
ob->o_ac = -(rnd(2) + 1);
|
|
else
|
|
ob->o_ac -= (rnd(2) + 1);
|
|
|
|
ob->o_flags |= ISCURSED;
|
|
}
|
|
|
|
know_items[TYP_RING][wh] = TRUE;
|
|
msg("The %s ring vibrates for a moment.", r_stones[wh]);
|
|
break;
|
|
|
|
default:
|
|
msg("The pool bubbles for a moment.");
|
|
}
|
|
}
|
|
else if (ob != NULL && tp->tr_type == POISONTRAP)
|
|
{
|
|
if ((player.t_ctype == C_PALADIN) ||
|
|
(player.t_ctype == C_CLERIC && rnd(2)))
|
|
{
|
|
msg("Trying to use poison is evil.");
|
|
luck += 2;
|
|
}
|
|
|
|
if (ob->o_type != WEAPON || rnd(10) > 0)
|
|
msg("Nothing seems to happen.");
|
|
else
|
|
{
|
|
msg("Your %s is covered with a black sticky liquid.",
|
|
weaps[ob->o_which].w_name);
|
|
ob->o_flags |= ISPOISON;
|
|
}
|
|
}
|
|
else
|
|
msg("Nothing seems to happen.");
|
|
}
|
|
|
|
/*
|
|
trap_at()
|
|
find the trap at (y,x) on screen.
|
|
*/
|
|
|
|
struct trap *
|
|
trap_at(int y, int x)
|
|
{
|
|
struct trap *tp, *ep;
|
|
|
|
ep = &traps[ntraps];
|
|
|
|
for (tp = traps; tp < ep; tp++)
|
|
if (tp->tr_pos.y == y && tp->tr_pos.x == x)
|
|
break;
|
|
|
|
if (tp == ep)
|
|
{
|
|
debug((sprintf(prbuf, "Trap at %d,%d not in array", y, x), prbuf));
|
|
tp = NULL;
|
|
}
|
|
|
|
return(tp);
|
|
}
|
|
|
|
/*
|
|
set_trap()
|
|
set a trap at (y, x) on screen.
|
|
*/
|
|
|
|
void
|
|
set_trap(struct thing *tp, int y, int x)
|
|
{
|
|
int is_player = (tp == &player);
|
|
int selection = rnd(7) + 1;
|
|
char ch = 0, och;
|
|
int thief_bonus = 0;
|
|
|
|
switch(och = CCHAR( mvinch(y, x) ))
|
|
{
|
|
case WALL:
|
|
case FLOOR:
|
|
case PASSAGE:
|
|
break;
|
|
default:
|
|
msg("The trap failed!");
|
|
return;
|
|
}
|
|
|
|
if (is_player && (player.t_ctype == C_THIEF ||
|
|
player.t_ctype == C_NINJA))
|
|
thief_bonus = 10;
|
|
|
|
if (ntraps >= 2 * MAXTRAPS || ++trap_tries >= MAXTRPTRY ||
|
|
rnd(60) >= (tp->t_stats.s_dext + tp->t_stats.s_lvl / 2 +
|
|
thief_bonus))
|
|
{
|
|
if (is_player)
|
|
msg("The trap failed!");
|
|
|
|
return;
|
|
}
|
|
|
|
/* Set up for redraw */
|
|
|
|
clearok(cw, TRUE);
|
|
touchwin(cw);
|
|
|
|
if (is_player)
|
|
{
|
|
add_line("[1] Trap Door");
|
|
add_line("[2] Bear Trap");
|
|
add_line("[3] Sleep Trap");
|
|
add_line("[4] Arrow Trap");
|
|
add_line("[5] Teleport Trap");
|
|
add_line("[6] Dart Trap");
|
|
add_line("[7] Fire Trap");
|
|
end_line();
|
|
msg("Which trap? ");
|
|
|
|
selection = (short) ((readchar() & 0177) - '0');
|
|
|
|
while (selection < 1 || selection > 7)
|
|
{
|
|
if (selection == (short) ESCAPE - (short) '0')
|
|
{
|
|
after = FALSE;
|
|
return;
|
|
}
|
|
|
|
msg("");
|
|
msg("Please enter a selection between 1 and 7: ");
|
|
selection = (short) ((readchar() & 0177) - '0');
|
|
}
|
|
}
|
|
|
|
switch (selection)
|
|
{
|
|
case 1: ch = TRAPDOOR; break;
|
|
case 2: ch = BEARTRAP; break;
|
|
case 3: ch = SLEEPTRAP;break;
|
|
case 4: ch = ARROWTRAP;break;
|
|
case 5: ch = TELTRAP; break;
|
|
case 6: ch = DARTTRAP; break;
|
|
case 7: ch = FIRETRAP; break;
|
|
}
|
|
|
|
mvaddch(y, x, ch);
|
|
|
|
traps[ntraps].tr_type = ch;
|
|
traps[ntraps].tr_flags = ISTHIEFSET;
|
|
traps[ntraps].tr_show = och;
|
|
traps[ntraps].tr_pos.y = y;
|
|
traps[ntraps++].tr_pos.x = x;
|
|
}
|
|
|
|
|
|
/*
|
|
rndmove()
|
|
move in a random direction if the monster/person is confused
|
|
*/
|
|
|
|
coord
|
|
rndmove(struct thing *who)
|
|
{
|
|
int x, y;
|
|
int ex, ey, nopen = 0;
|
|
coord ret; /* what we will be returning */
|
|
coord dest;
|
|
|
|
ret = who->t_pos;
|
|
|
|
/*
|
|
* Now go through the spaces surrounding the player and set that
|
|
* place in the array to true if the space can be moved into
|
|
*/
|
|
|
|
ey = ret.y + 1;
|
|
ex = ret.x + 1;
|
|
|
|
for (y = who->t_pos.y - 1; y <= ey; y++)
|
|
if (y > 0 && y < LINES - 2)
|
|
for (x = who->t_pos.x - 1; x <= ex; x++)
|
|
{
|
|
if (x < 0 || x >= COLS)
|
|
continue;
|
|
|
|
if (step_ok(y, x, NOMONST, who))
|
|
{
|
|
dest.y = y;
|
|
dest.x = x;
|
|
|
|
if (!diag_ok(&who->t_pos, &dest, who))
|
|
continue;
|
|
|
|
if (rnd(++nopen) == 0)
|
|
ret = dest;
|
|
}
|
|
}
|
|
|
|
return(ret);
|
|
}
|
|
|
|
/*
|
|
isatrap()
|
|
Returns TRUE if this character is some kind of trap
|
|
*/
|
|
|
|
int
|
|
isatrap(int ch)
|
|
{
|
|
switch(ch)
|
|
{
|
|
case DARTTRAP:
|
|
case TELTRAP:
|
|
case TRAPDOOR:
|
|
case ARROWTRAP:
|
|
case SLEEPTRAP:
|
|
case POOL:
|
|
case MAZETRAP:
|
|
case FIRETRAP:
|
|
case POISONTRAP:
|
|
case LAIR:
|
|
case RUSTTRAP:
|
|
case BEARTRAP:
|
|
return (TRUE);
|
|
default:
|
|
return (FALSE);
|
|
}
|
|
}
|