Mercurial > hg > early-roguelike
diff urogue/misc.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/misc.c Tue Jan 31 19:56:04 2017 -0500 @@ -0,0 +1,1208 @@ +/* + misc.c - all sorts of miscellaneous routines + + 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 <string.h> +#include <ctype.h> +#include "rogue.h" + +/* + tr_name() + print the name of a trap +*/ + +char * +tr_name(char ch, char *trname) +{ + const char *s = NULL; + + if (trname == NULL) + return(" Your found an error in UltraRogue #100."); + + switch(ch) + { + case TRAPDOOR: + s = "trapdoor."; + break; + case BEARTRAP: + s = "beartrap."; + break; + case SLEEPTRAP: + s = "sleeping gas trap."; + break; + case ARROWTRAP: + s = "arrow trap."; + break; + case TELTRAP: + s = "teleport trap."; + break; + case DARTTRAP: + s = "dart trap."; + break; + case POOL: + s = "shimmering pool."; + break; + case MAZETRAP: + s = "maze entrance."; + break; + case FIRETRAP: + s = "fire trap."; + break; + case POISONTRAP: + s = "poison pool trap."; + break; + case LAIR: + s = "monster lair."; + break; + case RUSTTRAP: + s = "rust trap."; + break; + default: + ; + } + + sprintf(trname, "You found a %s.", s); + + return(trname); +} + +/* + look() + A quick glance all around the player +*/ + +void +look(int wakeup) +{ + int x, y; + char ch, och; + int oldx, oldy; + int inpass, horizontal, vertical, do_light = FALSE, do_blank = FALSE; + int passcount = 0; + struct room *rp; + int ey, ex; + + /* Are we moving vertically or horizontally? */ + + if (runch == 'h' || runch == 'l') + horizontal = TRUE; + else + horizontal = FALSE; + + if (runch == 'j' || runch == 'k') + vertical = TRUE; + else + vertical = FALSE; + + getyx(cw, oldy, oldx); /* Save current position */ + + /* + * Blank out the floor around our last position and check for moving + * out of a corridor in a maze. + */ + + if (oldrp != NULL && (oldrp->r_flags & ISDARK) && + !(oldrp->r_flags & HASFIRE) && off(player, ISBLIND)) + do_blank = TRUE; + + for (x = player.t_oldpos.x - 1; x <= player.t_oldpos.x + 1; x++) + for (y = player.t_oldpos.y - 1; y <= player.t_oldpos.y + 1; + y++) + { + ch = show(y, x); + + if (do_blank && (y != hero.y || x != hero.x) && ch == FLOOR) + mvwaddch(cw, y, x, ' '); + + /* Moving out of a corridor? */ + + if (levtype == MAZELEV && + (ch != '|' && ch != '-') && /* Not a wall */ + ((vertical && x != player.t_oldpos.x && + y == player.t_oldpos.y) || + (horizontal && y != player.t_oldpos.y && + x == player.t_oldpos.x))) + do_light = TRUE; /* Just came to a turn */ + } + + inpass = ((rp = roomin(hero)) == NULL); /* Are we in a passage? */ + + /* Are we coming out of a wall into a corridor in a maze? */ + och = show(player.t_oldpos.y, player.t_oldpos.x); + ch = show(hero.y, hero.x); + + if (levtype == MAZELEV && (och == '|' || och == '-' || + och == SECRETDOOR) && (ch != '|' && ch != '-' && ch != SECRETDOOR)) + { + do_light = off(player, ISBLIND); /* Light it up if not blind */ + } + + /* Look around the player */ + + ey = hero.y + 1; + ex = hero.x + 1; + + for (x = hero.x - 1; x <= ex; x++) + if (x >= 0 && x < COLS) + for (y = hero.y - 1; y <= ey; y++) + { + if (y <= 0 || y >= LINES - 2) + continue; + + if (isalpha(mvwinch(mw, y, x))) + { + struct linked_list *it; + struct thing *tp; + + if (wakeup) + it = wake_monster(y, x); + else + it = find_mons(y, x); + + if (it == NULL) + continue; + + tp = THINGPTR(it); + tp->t_oldch = CCHAR( mvinch(y, x) ); + + if (isatrap(tp->t_oldch)) + { + struct trap *trp = trap_at(y, x); + + tp->t_oldch = (trp->tr_flags & ISFOUND) ? tp->t_oldch + : trp->tr_show; + } + + if (tp->t_oldch == FLOOR && + (rp->r_flags & ISDARK) + && !(rp->r_flags & HASFIRE) && + off(player, ISBLIND)) + tp->t_oldch = ' '; + } + + /* Secret doors show as walls */ + + if ((ch = show(y, x)) == SECRETDOOR) + ch = secretdoor(y, x); + + /* + * Don't show room walls if he is in a + * passage and check for maze turns + */ + + if (off(player, ISBLIND)) + { + if (y == hero.y && x == hero.x || (inpass && (ch == '-' || + ch == '|'))) + continue; + + /* Are we at a crossroads in a maze? */ + + if (levtype == MAZELEV && (ch != '|' && ch != '-') && + /* Not a wall */ + ((vertical && x != hero.x && y == hero.y) || + (horizontal && y != hero.y && x == hero.x))) + do_light = TRUE; + /* Just came to a turn */ + } + else if (y != hero.y || x != hero.x) + continue; + + wmove(cw, y, x); + waddch(cw, ch); + + if (door_stop && !firstmove && running) + { + switch (runch) + { + case 'h': + if (x == ex) + continue; + break; + case 'j': + if (y == hero.y - 1) + continue; + break; + case 'k': + if (y == ey) + continue; + break; + case 'l': + if (x == hero.x - 1) + continue; + break; + case 'y': + if ((x + y) - (hero.x + hero.y) >= 1) + continue; + break; + case 'u': + if ((y - x) - (hero.y - hero.x) >= 1) + continue; + break; + case 'n': + if ((x + y) - (hero.x + hero.y) <= -1) + continue; + break; + case 'b': + if ((y - x) - (hero.y - hero.x) <= -1) + continue; + break; + } + + switch (ch) + { + case DOOR: + if (x == hero.x || y == hero.y) + running = FALSE; + break; + case PASSAGE: + if (x == hero.x || y == hero.y) + passcount++; + break; + case FLOOR: + + /* + * Stop by new passages in a + * maze (floor next to us) + */ + if ((levtype == MAZELEV) && + ((horizontal && x == hero.x && y != hero.y) || + (vertical && y == hero.y && x != hero.x))) + running = FALSE; + + case '|': + case '-': + case ' ': + break; + + default: + running = FALSE; + break; + } + } + } + + if (door_stop && !firstmove && passcount > 1) + running = FALSE; + + /* + * Do we have to light up the area (just stepped into a new + * corridor)? + */ + + if (do_light && wakeup && /* wakeup will be true on a normal move */ + !(rp->r_flags & ISDARK) && /* We have some light */ + !ce(hero, player.t_oldpos)) /* Don't do anything if we didn't move */ + light(&hero); + + mvwaddch(cw, hero.y, hero.x, PLAYER); + wmove(cw, oldy, oldx); + + if (wakeup) + { + player.t_oldpos = hero; /* Don't change if we didn't move */ + oldrp = rp; + } +} + +/* + secret_door() + Figure out what a secret door looks like. +*/ + +char +secretdoor(int y, int x) +{ + struct room *rp; + coord cp; + + cp.x = x; + cp.y = y; + + if ((rp = roomin(cp)) != NULL) + { + if (y == rp->r_pos.y || y == rp->r_pos.y + rp->r_max.y - 1) + return ('-'); + else + return ('|'); + } + return ('p'); +} + +/* + find_obj() + find the unclaimed object at y, x +*/ + +struct linked_list * +find_obj(int y, int x) +{ + struct linked_list *obj, *sobj; + struct object *op; + + sobj = lvl_obj; + + for (obj = sobj; obj != NULL; obj = next(obj)) + { + op = OBJPTR(obj); + + if (op && op->o_pos.y == y && op->o_pos.x == x) + return(obj); + } + + return(NULL); +} + +/* + eat() + He wants to eat something, so let him try +*/ + +void +eat(void) +{ + struct object *obj; + int amount; + float scale = (float) (LINES * COLS) / (25.0F * 80.0F); + + if ((obj = get_object(pack, "eat", FOOD, NULL)) == NULL) + return; + + switch (obj->o_which) + { + case FD_RATION: + amount = (int)(scale * (HUNGERTIME + rnd(400) - 200)); + + if (rnd(100) > 70) + { + msg("Yuk, this food tastes awful."); + pstats.s_exp++; + check_level(); + } + else + msg("Yum, that tasted good."); + break; + + case FD_FRUIT: + amount = (int)(scale * (200 + rnd(HUNGERTIME))); + msg("My, that was a yummy %s.", fruit); + break; + + case FD_CRAM: + amount = (int)(scale * (rnd(HUNGERTIME / 2) + 600)); + msg("The cram tastes dry in your mouth."); + break; + + case FD_CAKES: + amount = (int)(scale * ((HUNGERTIME / 3) + rnd(600))); + msg("Yum, the honey cakes tasted good."); + break; + + case FD_LEMBA: + amount = (int)(scale * ((HUNGERTIME / 2) + rnd(900))); + quaff(&player, P_HEALING, ISNORMAL); + break; + + case FD_MIRUVOR: + amount = (int)(scale * ((HUNGERTIME / 3) + rnd(500))); + quaff(&player, P_HEALING, ISNORMAL); + quaff(&player, P_RESTORE, ISNORMAL); + break; + + default: + msg("What a strange thing to eat!"); + amount = (int)(scale * HUNGERTIME); + } + + food_left += amount; + + if (obj->o_flags & ISBLESSED) + { + food_left += 2 * amount; + msg("You have a tingling feeling in your mouth."); + } + else if (food_left > scale * STOMACHSIZE) + { + food_left = (int)(scale * STOMACHSIZE); + msg("You feel satiated and too full to move."); + no_command = HOLDTIME; + } + + hungry_state = F_OK; + updpack(); + + if (obj == cur_weapon) + cur_weapon = NULL; + + if (--obj->o_count <= 0) /* Remove this pack entry if last of food */ + discard_pack(obj); +} + +/* + * Used to modify the player's strength it keeps track of the highest it has + * been, just in case + */ + +void +chg_str(int amt, int both, int lost) +{ + int ring_str; /* ring strengths */ + struct stats *ptr; /* for speed */ + + ptr = &pstats; + + ring_str = ring_value(R_ADDSTR) + (on(player, POWERSTR) ? 10 : 0) + + (on(player, SUPERHERO) ? 10 : 0); + + ptr->s_str -= ring_str; + ptr->s_str += amt; + + if (ptr->s_str < 3) + { + ptr->s_str = 3; + lost = FALSE; + } + else if (ptr->s_str > 25) + ptr->s_str = 25; + + if (both) + max_stats.s_str = ptr->s_str; + + if (lost) + lost_str -= amt; + + ptr->s_str += ring_str; + + if (ptr->s_str < 0) + ptr->s_str = 0; + + updpack(); +} + +/* + * Used to modify the player's dexterity it keeps track of the highest it has + * been, just in case + */ + +void +chg_dext(int amt, int both, int lost) +{ + int ring_dext; /* ring strengths */ + struct stats *ptr; /* for speed */ + + ptr = &pstats; + + ring_dext = ring_value(R_ADDHIT) + (on(player, POWERDEXT) ? 10 : 0) + + (on(player, SUPERHERO) ? 5 : 0); + + ptr->s_dext -= ring_dext; + ptr->s_dext += amt; + + if (ptr->s_dext < 3) + { + ptr->s_dext = 3; + lost = FALSE; + } + else if (ptr->s_dext > 25) + ptr->s_dext = 25; + + if (both) + max_stats.s_dext = ptr->s_dext; + + if (lost) + lost_dext -= amt; + + ptr->s_dext += ring_dext; + + if (ptr->s_dext < 0) + ptr->s_dext = 0; +} + +/* + add_haste() + add a haste to the player +*/ + +void +add_haste(int blessed) +{ + short hasttime; + + if (blessed) + hasttime = 10; + else + hasttime = 6; + + if (on(player, ISSLOW)) /* Is person slow? */ + { + extinguish_fuse(FUSE_NOSLOW); + noslow(NULL); + + if (blessed) + hasttime = 4; + else + return; + } + + if (on(player, ISHASTE)) + { + msg("You faint from exhaustion."); + no_command += rnd(hasttime); + lengthen_fuse(FUSE_NOHASTE, rnd(hasttime) + (roll(1, 4) * hasttime)); + } + else + { + turn_on(player, ISHASTE); + light_fuse(FUSE_NOHASTE, 0, roll(hasttime, hasttime), AFTER); + } +} + +/* + aggravate() + aggravate all the monsters on this level +*/ + +void +aggravate(void) +{ + struct linked_list *mi; + struct thing *tp; + + for (mi = mlist; mi != NULL; mi = next(mi)) + { + tp = THINGPTR(mi); + chase_it(&tp->t_pos, &player); + } +} + +/* + vowelstr() + for printfs: if string starts with a vowel, return "n" for an "an" +*/ + +char * +vowelstr(char *str) +{ + switch (*str) + { + case 'a': + case 'A': + case 'e': + case 'E': + case 'i': + case 'I': + case 'o': + case 'O': + case 'u': + case 'U': + return "n"; + default: + return ""; + } +} + +/* + is_object() + see if the object is one of the currently used items +*/ + +int +is_current(struct object *obj) +{ + if (obj == NULL) + return FALSE; + + if (obj == cur_armor || obj == cur_weapon || + obj == cur_ring[LEFT_1] || obj == cur_ring[LEFT_2] || + obj == cur_ring[LEFT_3] || obj == cur_ring[LEFT_4] || + obj == cur_ring[LEFT_5] || + obj == cur_ring[RIGHT_1] || obj == cur_ring[RIGHT_2] || + obj == cur_ring[RIGHT_3] || obj == cur_ring[RIGHT_4] || + obj == cur_ring[RIGHT_5]) { + msg("That's already in use."); + return TRUE; + } + + return FALSE; +} + +/* + get_dir() + set up the direction co_ordinate for use in varios "prefix" commands +*/ + +int +get_dir(void) +{ + char *prompt; + int gotit; + + prompt = "Which direction? "; + msg(prompt); + + do + { + gotit = TRUE; + + switch (readchar()) + { + case 'h': + case 'H': + delta.y = 0; + delta.x = -1; + break; + + case 'j': + case 'J': + delta.y = 1; + delta.x = 0; + break; +