view arogue7/misc.c @ 143:7faf4568c295

Advanced Rogue family: overhaul privilege handling. Advanced Rogue 5 and 7, and XRogue, now open the scorefile and logfile at startup and then drop any set[ug]id privileges if the savedir is not being used.
author John "Elwin" Edwards
date Sat, 16 May 2015 13:39:26 -0400
parents b786053d2f37
children cadff8f047a1
line wrap: on
line source

/*
 * misc.c - routines dealing specifically with miscellaneous magic
 *
 * Advanced Rogue
 * Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
 * 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 "curses.h"
#include <stdlib.h>
#include <ctype.h>
#include "rogue.h"
#ifdef PC7300
#include "menu.h"
#endif

/*
 * routines dealing specifically with miscellaneous magic
 */

/*
 * changeclass:
 *	Change the player's class to the specified one.
 */

changeclass(newclass)
int newclass;
{
    if (newclass == player.t_ctype) {
	msg("You feel more skillful.");
	raise_level();
    }
    else {
	/*
	 * reset his class and then use check_level to reset hit
	 * points and the right level for his exp pts
	 * drop exp pts by 10%
	 */
	long save;

	msg("You feel like a whole new person!");

	/*
	 * if he becomes a thief he has to have leather armor
	 */
	if ((newclass == C_THIEF || newclass == C_ASSASIN)	&&
	    cur_armor != NULL					&&
	    cur_armor->o_which != LEATHER			&&
	    cur_armor->o_which != STUDDED_LEATHER ) 
		cur_armor->o_which = STUDDED_LEATHER;
	/*
	 * if he becomes a monk he can't wear armor
	 */
	if (newclass == C_MONK && cur_armor != NULL) {
		cur_armor->o_ac = armors[cur_armor->o_which].a_class - 
				  cur_armor->o_ac;
		cur_armor->o_type = MM;
		cur_armor->o_which = MM_PROTECT;
		cur_armor->o_flags &= ~(ISPROT | ISKNOW | ISMETAL);
		cur_misc[WEAR_CLOAK] = cur_armor;
		cur_armor = NULL;
	}
	/*
	 * if he used to be a spell caster of some sort, kill the fuse
	 */
	if (player.t_ctype == C_MAGICIAN || player.t_ctype == C_RANGER)
		extinguish(spell_recovery);
	if (player.t_ctype == C_DRUID || player.t_ctype == C_RANGER)
		extinguish(chant_recovery);
	if ((player.t_ctype == C_CLERIC || player.t_ctype == C_PALADIN) &&
	     !cur_relic[HEIL_ANKH])
		extinguish(prayer_recovery);
	/*
	 * if he becomes a spell caster of some kind, give him a fuse
	 */
	if (newclass == C_MAGICIAN || newclass == C_RANGER)
		fuse(spell_recovery, 0, SPELLTIME, AFTER);
	if (newclass == C_DRUID || newclass == C_RANGER)
		fuse(chant_recovery, 0, SPELLTIME, AFTER);
	if ((newclass==C_CLERIC || newclass==C_PALADIN) && !cur_misc[HEIL_ANKH])
		fuse(prayer_recovery, 0, SPELLTIME, AFTER);
	/*
	 * if he's changing from a fighter then may have to change
	 * his sword since only fighter can use two-handed
	 * and bastard swords
	 */
	if ((player.t_ctype == C_FIGHTER	||
	     player.t_ctype == C_RANGER		||
	     player.t_ctype == C_PALADIN)		&&
	    cur_weapon != NULL				&&
	    cur_weapon->o_type == WEAPON		&&
	   (cur_weapon->o_which== BASWORD	||
	    cur_weapon->o_which== TWOSWORD )		&&
	   !(newclass == C_FIGHTER		||
	     newclass == C_RANGER		||
	     newclass == C_PALADIN)			&&
	   !(newclass == C_ASSASIN		&&
	     cur_weapon->o_which == BASWORD))
		cur_weapon->o_which = SWORD;

	/*
	 * if he was a thief then take out the trap_look() daemon
	 */
	if (player.t_ctype == C_THIEF || 
	    player.t_ctype == C_MONK  ||
	    player.t_ctype == C_ASSASIN)
	    kill_daemon(trap_look);

	/*
	 * if he becomes a thief then add the trap_look() daemon
	 */
	if (newclass == C_THIEF || newclass == C_ASSASIN || newclass == C_MONK)
	    daemon(trap_look, 0, AFTER);
	char_type = player.t_ctype = newclass;
	save = pstats.s_hpt;
	max_stats.s_hpt = pstats.s_hpt = 0;
	max_stats.s_lvl = pstats.s_lvl = 0; 
	max_stats.s_lvladj = pstats.s_lvladj = 0; 
	max_stats.s_exp = pstats.s_exp -= pstats.s_exp/10;
	check_level();
	if (pstats.s_hpt > save) /* don't add to current hits */
	    pstats.s_hpt = save;
    }
}

/*
 * Use the relic that our monster is wielding.
 */
m_use_relic(monster)
register struct thing *monster;
{
    register struct object *obj;

    /* Make sure we really have it */
    if (monster->t_using) obj = OBJPTR(monster->t_using);
    else {
	debug("Relic not set!");
	monster->t_action = A_NIL;
	return;
    }

    /* Now let's see what we're using */
    if (obj->o_type == RELIC) switch (obj->o_which) {
	case MING_STAFF: {
	    static struct object missile = {
	      MISSILE, {0,0}, "", 0, "", "0d4 " , NULL, 0, WS_MISSILE, 100, 1
	    };

	    debug("Firing Ming's staff");
	    sprintf(missile.o_hurldmg, "%dd4", monster->t_stats.s_lvl);
	    do_motion(&missile,
		       monster->t_newpos.y, monster->t_newpos.x, monster);
	    hit_monster(unc(missile.o_pos), &missile, monster);
	    monster->t_artifact = monster->t_artifact * 4 / 5;
	}
	when EMORI_CLOAK:
	    debug("stunning with Emori's cloak");
	    do_zap(monster, obj, &monster->t_newpos, WS_PARALYZE, NULL);
	    obj->o_charges = 0;

	when ASMO_ROD: {
	    char *name;

	    switch (rnd(3)) { /* Select a function */
		case 0:	   name = "lightning bolt";
		when 1:	   name = "flame";
		otherwise: name = "ice";
	    }
	    shoot_bolt(	monster, 
			monster->t_pos, 
			monster->t_newpos, 
			FALSE, 
			monster->t_index, 
			name, 
			roll(monster->t_stats.s_lvl,6));
	    monster->t_artifact /= 2;
	}
	when BRIAN_MANDOLIN:
	    /* Make sure the defendant is still around */
	    if (DISTANCE(monster->t_pos.y, monster->t_pos.x,
			 hero.y, hero.x) < 25) {
		if (!save(VS_MAGIC, &player, -4) &&
		    !ISWEARING(R_ALERT)) {
		    msg("Some beautiful music enthralls you.");
		    player.t_no_move += movement(&player) * FREEZETIME;
		    player.t_action = A_FREEZE;
		    monster->t_artifact = monster->t_artifact * 2 / 3;
		}
		else {
		    msg("You wince at a sour note.");
		    monster->t_artifact /= 3;
		}
	    }
	when GERYON_HORN:
	    /* Make sure the defendant is still around */
	    if (DISTANCE(monster->t_pos.y, monster->t_pos.x,
			 hero.y, hero.x) < 25) {
		if (!ISWEARING(R_HEROISM) &&
		    !save(VS_MAGIC, &player, -4)) {
			turn_on(player, ISFLEE);
			player.t_dest = &monster->t_pos;
			msg("A shrill blast terrifies you.");
			monster->t_artifact = monster->t_artifact * 3 / 4;
		}
		else  {
		    msg("A shrill blast sends chills up your spine.");
		    monster->t_artifact /= 3;
		}
	    }

	otherwise:
	    /* Unknown RELIC! */
	    debug("Unknown wielded relic %d", obj->o_which);
    }
    else debug("Declared relic is %d", obj->o_type);

    turn_off(*monster, CANSURPRISE);
    /* Reset the monsters actions */
    monster->t_action = A_NIL;
    monster->t_using = NULL;
}
 
/*
 * add something to the contents of something else
 */
put_contents(bag, item)
register struct object *bag;		/* the holder of the items */
register struct linked_list *item;	/* the item to put inside  */
{
    register struct linked_list *titem;
    register struct object *tobj;

    bag->o_ac++;
    tobj = OBJPTR(item);
    for (titem = bag->contents; titem != NULL; titem = next(titem)) {
	if ((OBJPTR(titem))->o_which == tobj->o_which)
	    break;
    }
    if (titem == NULL) {	/* if not a duplicate put at beginning */
	attach(bag->contents, item);
    }
    else {
	item->l_prev = titem;
	item->l_next = titem->l_next;
	if (next(titem) != NULL) 
	    (titem->l_next)->l_prev = item;
	titem->l_next = item;
    }
}

/*
 * remove something from something else
 */
take_contents(bag, item)
register struct object *bag;		/* the holder of the items */
register struct linked_list *item;
{

    if (bag->o_ac <= 0) {
	msg("Nothing to take out");
	return;
    }
    bag->o_ac--;
    detach(bag->contents, item);
    if (!add_pack(item, FALSE, NULL))
	put_contents(bag, item);
}


do_bag(item)
register struct linked_list *item;
{

    register struct linked_list *titem;
    register struct object *obj, *tobj;
    bool doit = TRUE;

    obj = OBJPTR(item);
    while (doit) {
	msg("What do you want to do? (* for a list): ");
	mpos = 0;
	switch (readchar()) {
	    case EOF:
	    case ESCAPE:
		msg ("");
		doit = FALSE;
	    when '1':
		inventory(obj->contents, ALL);

	    when '2':
		if (obj->o_ac >= MAXCONTENTS) {
		    msg("the %s is full", m_magic[obj->o_which].mi_name);
		    break;
		}
		switch (obj->o_which) {
		case MM_BEAKER:
		    titem = get_item(pack, "put in", POTION, FALSE, FALSE);
		when MM_BOOK:
		    titem = get_item(pack, "put in", SCROLL, FALSE, FALSE);
		}
		if (titem == NULL)
		    break;
		detach(pack, titem);
		inpack--;
		put_contents(obj, titem);
	    
	    when '3':
		titem = get_item(obj->contents,"take out",ALL,FALSE,FALSE);
		if (titem == NULL)
		    break;
		take_contents(obj, titem);
		
	    when '4': 
		switch (obj->o_which) {
		case MM_BEAKER: 
		    titem = get_item(obj->contents,"quaff",ALL,FALSE,FALSE);
		    if (titem == NULL)
			break;
		    tobj = OBJPTR(titem);
		    obj->o_ac--;
		    detach(obj->contents, titem);
		    quaff(tobj->o_which, 
			  tobj->o_kind,
			  tobj->o_flags,
			  TRUE);
		    if (p_know[tobj->o_which] && p_guess[tobj->o_which])
		    {
			free(p_guess[tobj->o_which]);
			p_guess[tobj->o_which] = NULL;
		    }
		    else if (!p_know[tobj->o_which]		&& 
			     askme				&&
			     (tobj->o_flags & ISKNOW) == 0	&&
			     (tobj->o_flags & ISPOST) == 0	&&
			     p_guess[tobj->o_which] == NULL) {
			nameitem(titem, FALSE);
		    }
		    o_discard(titem);
		when MM_BOOK:   
		    if (on(player, ISBLIND)) {
			msg("You can't see to read anything");
			break;
		    }
		    titem = get_item(obj->contents,"read",ALL,FALSE,FALSE);
		    if (titem == NULL)
			break;
		    tobj = OBJPTR(titem);
		    obj->o_ac--;
		    detach(obj->contents, titem);
		    read_scroll(tobj->o_which, 
			        tobj->o_flags & (ISCURSED|ISBLESSED),
				TRUE);
		    if (s_know[tobj->o_which] && s_guess[tobj->o_which])
		    {
			free(s_guess[tobj->o_which]);
			s_guess[tobj->o_which] = NULL;
		    }
		    else if (!s_know[tobj->o_which]		&& 
			     askme				&&
			     (tobj->o_flags & ISKNOW) == 0	&&
			     (tobj->o_flags & ISPOST) == 0	&&
			     s_guess[tobj->o_which] == NULL) {
			nameitem(titem, FALSE);
		    }
		    o_discard(titem);
		}
		doit = FALSE;

	    otherwise:
		wclear(hw);
		touchwin(hw);
		mvwaddstr(hw,0,0,"The following operations are available:");
		mvwaddstr(hw,2,0,"[1]\tInventory\n");
		wprintw(hw,"[2]\tPut something in the %s\n",
			m_magic[obj->o_which].mi_name);
		wprintw(hw,"[3]\tTake something out of the %s\n",
			m_magic[obj->o_which].mi_name);
		switch(obj->o_which) {
		    case MM_BEAKER: waddstr(hw,"[4]\tQuaff a potion\n");
		    when MM_BOOK:   waddstr(hw,"[4]\tRead a scroll\n");
		}
		waddstr(hw,"[ESC]\tLeave this menu\n");
		mvwaddstr(hw, lines-1, 0, spacemsg);
		draw(hw);
		wait_for (' ');
		clearok(cw, TRUE);