/* 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 #include #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); } }