Mercurial > hg > early-roguelike
diff urogue/player.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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/urogue/player.c Tue Jan 31 19:56:04 2017 -0500 @@ -0,0 +1,538 @@ +/* + player.c - functions for dealing with special player abilities + + 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" + +/* + * Pray to a deity + * + * 00-10 Good stuff happens + * 11-40 A good deity answers + * 41-60 Nothing happens + * 61-90 A bad deity answers, but with good results + * 91-99 You were better off before + */ + +void +prayer(void) +{ + int chance, i, times; + char num_str[20]; + int ch; + struct linked_list *item; + struct thing *tp; + int is_godly; + + if (player.t_praycnt > pstats.s_lvl) + { + msg("Are you sure you want to bother the gods?"); + ch = readchar(); + + if (tolower(ch) != 'y') + { + after = FALSE; + return; + } + else + msg("Here goes..."); + } + + msg("You are surrounded by orange smoke..."); + + if (rnd(3) == 0) + luck--; + + if (is_wearing(R_PIETY) || (rnd(luck) == 0 && + (player.t_ctype == C_DRUID || player.t_ctype == C_CLERIC || + ((player.t_ctype == C_PALADIN || player.t_ctype == C_RANGER) + && pstats.s_lvl > 8)))) + is_godly = ISBLESSED; + else + is_godly = ISNORMAL; + + if (is_wearing(R_PIETY)) + player.t_praycnt += rnd(2); + else + player.t_praycnt++; + + if (wizard) + { + msg("What roll?[0..%d] ", 99); + ch = get_string(num_str, cw); + + if (ch == QUIT) + { + msg(""); + return; + } + chance = atoi(num_str); + } + else + { + chance = rnd(100) + roll(10, luck) - 5; + + if (player.t_praycnt > pstats.s_lvl) + chance += 50; + + if (is_godly) + chance -= 50; + } + + chance = max(0, min(chance, 100)); + + if (chance == 0) + { + msg("The heavens open and glorious radiance surrounds you!"); + + pstats.s_hpt = max_stats.s_hpt; + pstats.s_power = max_stats.s_power; + + if (is_godly) + times = 8; + else + times = 1; + + /* + * kill all monsters surrounding the hero except unique ones + * This will change when I implement the deity option. If + * The deity is "stronger" than the unique monster, then the + * monster will be killed. + */ + + for (i = 0; i < times; i++) + { + item = f_mons_a(player.t_pos.y, player.t_pos.x, TRUE); + + if (item) + { + tp = THINGPTR(item); + + msg("A bolt of eldritch energy strikes down the %s!", + monsters[tp->t_index].m_name); + + killed(NULL, item, NOMESSAGE, POINTS); + } + } + } + else if (chance == 2) + { + msg("Aule, Lord of Crafts, hears your call."); + read_scroll(&player, S_MAKEITEMEM, is_godly); + } + + /* Save 3-9 for other wonderful stuff */ + else if (chance < 15) + { + msg("Orome, Lord of Forests, hears your call."); + read_scroll(&player, S_SUMMON, is_godly); + } + else if (chance < 20) + { + msg("Hermes, the Winged Messenger, hears your call."); + quaff(&player, P_HASTE, is_godly); + } + else if (chance < 25) + { + msg("Lorien, Master of Dreams, hears your call."); + read_scroll(&player, S_SLEEP, is_godly); + } + else if (chance < 30) + { + msg("Este, Lady of Healing, hears your call."); + quaff(&player, P_RESTORE, is_godly); + quaff(&player, P_HEALING, is_godly); + } + else if (chance < 35) + { + msg("Thor, God of Thunder, hears your call."); + msg("A bolt of lighting strikes you!"); + read_scroll(&player, S_ELECTRIFY, is_godly); + } + else if (chance < 40) + { + msg("Lorien, Master of Illusion, hears your call."); + quaff(&player, P_DISGUISE, is_godly); + } + else if (chance < 60) /* Nothing happens */ + { + msg("Boccob, the Uncaring, ignores you."); + } + + /* You don't really want one of these gods answering your call */ + + else if (chance < 65) + { + msg("Jubilex, Master of Slimes and Oozes, hears your call."); + read_scroll(&player, S_HOLD, is_godly); + luck++; + } + else if (chance < 70) + { + msg("Sauron, Lord of the Ring, hears your call."); + quaff(&player, P_INVIS, is_godly); + luck++; + } + else if (chance < 75) + { + msg("Orcus, Lord of Undead, hears your call."); + quaff(&player, P_PHASE, is_godly); + luck++; + } + else if (chance < 80) + { + msg("Incabulos, God of Evil Sendings, hears your call."); + quaff(&player, P_CLEAR, is_godly); + luck++; + } + else if (chance < 85) + { + msg("Raxivort, Night Flutterer, hears your call."); + quaff(&player, P_SEEINVIS, is_godly); + luck++; + } + else if (chance < 90) + { + msg("Morgoth, Lord of Fire, hears your call."); + quaff(&player, P_FIRERESIST, is_godly); + luck++; + } + else if (chance < 100) /* You are in for it now! */ + { + msg("You fall into a horrible trance-like state."); + no_command += SLEEPTIME; + } + if (chance == 100) + { + msg("The heavens open - but wait!"); + msg("A bolt of eldritch energy strikes you!"); + + if (pstats.s_hpt > 1) + pstats.s_hpt /= 2; + + msg("The gods must be angry with you."); + } +} + +/* Routines for thieves */ + +/* + gsense() + Sense gold returns TRUE if gold was detected +*/ + +int +gsense(void) +{ + if (lvl_obj != NULL) + { + struct linked_list *gitem; + struct object *cur; + int gtotal = 0; + + wclear(hw); + + for (gitem = lvl_obj; gitem != NULL; gitem = next(gitem)) + { + cur = OBJPTR(gitem); + + if (cur->o_type == GOLD) + { + gtotal += cur->o_count; + mvwaddch(hw, cur->o_pos.y, cur->o_pos.x, GOLD); + + } + } + + if (gtotal) + { + msg("You sense gold!"); + overlay(hw, cw); + return(TRUE); + } + } + + nothing_message(ISNORMAL); + + return(FALSE); +} + + +/* + is_stealth() + is player quiet about something +*/ + +int +is_stealth(struct thing *tp) +{ + return (rnd(25) < tp->t_stats.s_dext || + (tp == &player && is_wearing(R_STEALTH))); +} + +/* + steal() + Steal in direction given in delta +*/ + +void +steal(void) +{ + struct linked_list *item; + struct thing *tp; + coord new_pos; + short thief_bonus; + char *unsuccess = ""; + char *gain = ""; + char *notice = "is not"; + + new_pos.y = hero.y + delta.y; + new_pos.x = hero.x + delta.x; + + /* Anything there? */ + + if (new_pos.y < 0 || new_pos.y > LINES - 3 || + new_pos.x < 0 || new_pos.x > COLS - 1 || + mvwinch(mw, new_pos.y, new_pos.x) == ' ') + { + msg("There is no one to steal from."); + return; + } + + if ((item = find_mons(new_pos.y, new_pos.x)) == NULL) + return; + + tp = THINGPTR(item); + + /* Can player steal something unnoticed? */ + + if (player.t_ctype == C_THIEF || player.t_ctype == C_NINJA) + thief_bonus = 10; + else + thief_bonus = -50; + + if (rnd(50) >= 3 * pstats.s_dext + thief_bonus) + { + chase_it(&new_pos, &player); + turn_off(*tp, ISFRIENDLY); + notice = "is"; + } + + if (rnd(100) < + (thief_bonus + 2 * pstats.s_dext + 5 * pstats.s_lvl - + 5 * (tp->t_stats.s_lvl - 3))) + { + struct linked_list *s_item, *pack_ptr; + int cnt = 0; + + s_item = NULL; /* Start stolen goods out as nothing */ + + /* Find a good item to take */ + + if (tp->t_pack != NULL) + { + /* Count up the number of items in the monster's pack */ + + for (pack_ptr = tp->t_pack; pack_ptr != NULL; pack_ptr = next(pack_ptr)) + cnt++; + + /* Pick one */ + cnt = rnd(cnt); + + /* Take it from the monster */ + + for (pack_ptr = tp->t_pack; --cnt == 0; pack_ptr = next(pack_ptr)) + ; + + s_item = pack_ptr; + detach(tp->t_pack, s_item); + + /* Give it to player */ + + if (add_pack(s_item, MESSAGE) == FALSE) + { + (OBJPTR(s_item))->o_pos = hero; + fall(&player, s_item, TRUE, FALSE); + } + + /* Get points for stealing from unfriendly monsters */ + + if (off(*tp, ISFRIENDLY)) + { + if (player.t_ctype == C_THIEF) + pstats.s_exp += 2 * tp->t_stats.s_exp / 3; + else + pstats.s_exp += tp->t_stats.s_exp / min(pstats.s_lvl, 10); + + check_level(); + } + } + else + { + gain = " gains you nothing and"; + } + } + else + { + unsuccess = " unsuccessful"; + } + + msg("Your%s attempt%s %s noticed.", unsuccess, gain, notice); +} + +/* + affect() + cleric affecting undead +*/ + +void +affect(void) +{ + struct linked_list *item; + struct thing *tp; + char *mname; + coord new_pos; + int is_godly; + int effective_level; + + if (player.t_ctype != C_CLERIC && player.t_ctype != C_PALADIN && + !is_wearing(R_PIETY)) + { + msg("Only clerics and paladins can affect undead."); + return; + } + + is_godly = (player.t_ctype == C_CLERIC || player.t_ctype == C_PALADIN); + + if (is_godly && is_wearing(R_PIETY)) + effective_level = 2 * pstats.s_lvl; + else + effective_level = pstats.s_lvl; + + new_pos.y = hero.y + delta.y; + new_pos.x = hero.x + delta.x; + + /* Anything there? */ + + if (new_pos.y < 0 || new_pos.y > LINES - 3 || + new_pos.x < 0 || new_pos.x > COLS - 1 || + mvwinch(mw, new_pos.y, new_pos.x) == ' ') + { + msg("Nothing to affect."); + return; + } + + if ((item = find_mons(new_pos.y, new_pos.x)) == NULL) + { + debug("Affect what @ %d,%d?", new_pos.y, new_pos.x); + return; + } + + tp = THINGPTR(item); + mname = monsters[tp->t_index].m_name; + + if (off(*tp, ISUNDEAD)) + { + msg("Your holy symbol has no effect on the %s.", mname); + goto annoy; + } + + if (on(*tp, WASTURNED)) + { + msg("Your holy symbol merely enrages the %s.", mname); + goto annoy; + } + + /* Can cleric destroy it? */ + + if (effective_level >= 3 * tp->t_stats.s_lvl) + { + msg("You have destroyed the %s.", mname); + killed(&player, item, NOMESSAGE, POINTS); + return; + } + + /* Can cleric turn it? */ + + if (rnd(100) + 1 > + (100 * ((2 * tp->t_stats.s_lvl) - effective_level)) / + effective_level) + { + msg("You have turned the %s.", mname); + turn_on(*tp, WASTURNED); /* One turn per monster */ + turn_on(*tp, ISRUN); + turn_on(*tp, ISFLEE); + + /* If monster was suffocating, stop it */ + if (on(*tp, DIDSUFFOCATE)) + { + turn_off(*tp, DIDSUFFOCATE); + extinguish_fuse(FUSE_SUFFOCATE); + } + + /* If monster held us, stop it */ + if (on(*tp, DIDHOLD) && (--hold_count == 0)) + turn_off(player, ISHELD); + + turn_off(*tp, DIDHOLD); + + return; + } + + msg("The %s momentarily recoils from your holy symbol.", mname); + +annoy: + + if (off(*tp, WASTURNED)) + chase_it(&new_pos, &player); +} + +/* + undead_sense() + cleric or paladin finding the ungodly +*/ + +void +undead_sense(void) +{ + struct linked_list *item; + struct thing *tp; + int showit = FALSE; + + wclear(hw); + + for (item = mlist; item != NULL; item = next(item)) + { + tp = THINGPTR(item); + + if (on(*tp, ISUNDEAD)) + { + mvwaddch(hw, tp->t_pos.y, tp->t_pos.x, '&'); + showit = TRUE; + } + } + + if (showit) + { + msg("You feel the presense of the ungodly."); + overlay(hw, cw); + wrefresh(cw); + wclear(hw); + } +}