[BACK]Return to interplayer.c CVS log [TXT][DIR] Up to [local] / src / games / phantasia

File: [local] / src / games / phantasia / interplayer.c (download)

Revision 1.8, Wed Jan 6 14:28:09 2016 UTC (8 years, 4 months ago) by mestre
Branch: MAIN
CVS Tags: OPENBSD_7_5_BASE, OPENBSD_7_5, OPENBSD_7_4_BASE, OPENBSD_7_4, OPENBSD_7_3_BASE, OPENBSD_7_3, OPENBSD_7_2_BASE, OPENBSD_7_2, OPENBSD_7_1_BASE, OPENBSD_7_1, OPENBSD_7_0_BASE, OPENBSD_7_0, OPENBSD_6_9_BASE, OPENBSD_6_9, OPENBSD_6_8_BASE, OPENBSD_6_8, OPENBSD_6_7_BASE, OPENBSD_6_7, OPENBSD_6_6_BASE, OPENBSD_6_6, OPENBSD_6_5_BASE, OPENBSD_6_5, OPENBSD_6_4_BASE, OPENBSD_6_4, OPENBSD_6_3_BASE, OPENBSD_6_3, OPENBSD_6_2_BASE, OPENBSD_6_2, OPENBSD_6_1_BASE, OPENBSD_6_1, OPENBSD_6_0_BASE, OPENBSD_6_0, OPENBSD_5_9_BASE, OPENBSD_5_9, HEAD
Changes since 1.7: +11 -2 lines

Remove unnecessary header files from phantasia(6)

Lesson learnt: don't include an header sorted alphabetically just because. The
external definition of variables was done on phantglobs.h but their declaration
was on phantstruct.h and therefore the latter must be included before the
former. It's easier to just include phantstruct.h inside phantglobs.h since it
always need it.

With help and OK from tb@

/*	$OpenBSD: interplayer.c,v 1.8 2016/01/06 14:28:09 mestre Exp $	*/
/*	$NetBSD: interplayer.c,v 1.2 1995/03/24 03:58:47 cgd Exp $	*/

/*
 * interplayer.c - player to player routines for Phantasia
 */

#include <curses.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include "macros.h"
#include "pathnames.h"
#include "phantdefs.h"
#include "phantglobs.h"

/************************************************************************
/
/ FUNCTION NAME: checkbattle()
/
/ FUNCTION: check to see if current player should battle another
/
/ AUTHOR: E. A. Estes, 12/4/85
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: battleplayer(), fread(), fseek()
/
/ GLOBAL INPUTS: Other, Users, Player, Fileloc, *Playersfp
/
/ GLOBAL OUTPUTS: Users
/
/ DESCRIPTION:
/	Seach player file for a foe at the same coordinates as the
/	current player.
/	Also update user count.
/
*************************************************************************/

void
checkbattle(void)
{
	long    foeloc = 0L;	/* location in file of person to fight */

	Users = 0;
	fseek(Playersfp, 0L, SEEK_SET);

	while (fread(&Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) {
		if (Other.p_status != S_OFF
		    && Other.p_status != S_NOTUSED
		    && Other.p_status != S_HUNGUP
		    && (Other.p_status != S_CLOAKED || Other.p_specialtype != SC_VALAR))
			/* player is on and not a cloaked valar */
		{
			++Users;

			if (Player.p_x == Other.p_x
			    && Player.p_y == Other.p_y
			/* same coordinates */
			    && foeloc != Fileloc
			/* not self */
			    && Player.p_status == S_PLAYING
			    && (Other.p_status == S_PLAYING || Other.p_status == S_INBATTLE)
			/* both are playing */
			    && Other.p_specialtype != SC_VALAR
			    && Player.p_specialtype != SC_VALAR)
				/* neither is valar */
			{
				battleplayer(foeloc);
				return;
			}
		}
		foeloc += SZ_PLAYERSTRUCT;
	}
}
/**/
/************************************************************************
/
/ FUNCTION NAME: battleplayer()
/
/ FUNCTION: inter-terminal battle with another player
/
/ AUTHOR: E. A. Estes, 2/15/86
/
/ ARGUMENTS:
/	long foeplace - location in player file of person to battle
/
/ RETURN VALUE: none
/
/ MODULES CALLED: readrecord(), readmessage(), writerecord(), collecttaxes(), 
/	displaystats(), fabs(), more(), death(), sleep(), wmove(), waddch(), printw(), 
/	myturn(), altercoordinates(), waddstr(), wrefresh(), mvprintw(), 
/	getanswer(), wclrtoeol(), wclrtobot()
/
/ GLOBAL INPUTS: Foestrikes, LINES, Lines, Other, Shield, Player, *stdscr, 
/	Fileloc, *Enemyname
/
/ GLOBAL OUTPUTS: Foestrikes, Lines, Shield, Player, Luckout, *Enemyname
/
/ DESCRIPTION:
/	Inter-terminal battle is a very fragile and slightly klugy thing.
/	At any time, one player is master and the other is slave.
/	We pick who is master first by speed and level.  After that,
/	the slave waits for the master to relinquish its turn, and
/	the slave becomes master, and so on.
/
/	The items in the player structure which control the handshake are:
/	    p_tampered:
/		master increments this to relinquish control
/	    p_istat:
/		master sets this to specify particular action
/	    p_1scratch:
/		set to total damage inflicted so far; changes to indicate action
/
*************************************************************************/

void
battleplayer(long foeplace)
{
	double  dtemp;		/* for temporary calculations */
	double  oldhits = 0.0;	/* previous damage inflicted by foe */
	int     loop;		/* for timing out */
	int     ch;		/* input */
	short   oldtampered;	/* old value of foe's p_tampered */

	Lines = 8;
	Luckout = FALSE;
	mvaddstr(4, 0, "Preparing for battle!\n");
	refresh();

	/* set up variables, file, etc. */
	Player.p_status = S_INBATTLE;
	Shield = Player.p_energy;

	/* if p_tampered is not 0, someone else may try to change it (king,
	 * etc.) */
	Player.p_tampered = oldtampered = 1;
	Player.p_1scratch = 0.0;
	Player.p_istat = I_OFF;

	readrecord(&Other, foeplace);
	if (fabs(Player.p_level - Other.p_level) > 20.0)
		/* see if players are greatly mismatched */
	{
		dtemp = (Player.p_level - Other.p_level) / MAX(Player.p_level, Other.p_level);
		if (dtemp < -0.5)
			/* foe outweighs this one */
			Player.p_speed *= 2.0;
	}
	writerecord(&Player, Fileloc);	/* write out all our info */

	if (Player.p_blindness)
		Enemyname = "someone";
	else
		Enemyname = Other.p_name;

	mvprintw(6, 0, "You have encountered %s   Level: %.0f\n", Enemyname, Other.p_level);
	refresh();

	for (loop = 0; Other.p_status != S_INBATTLE && loop < 30; ++loop)
		/* wait for foe to respond */
	{
		readrecord(&Other, foeplace);
		sleep(1);
	}

	if (Other.p_status != S_INBATTLE)
		/* foe did not respond */
	{
		mvprintw(5, 0, "%s is not responding.\n", Enemyname);
		goto LEAVE;
	}
	/* else, we are ready to battle */

	move(4, 0);
	clrtoeol();

	/*
         * determine who is first master
         * if neither player is faster, check level
         * if neither level is greater, battle is not allowed
         * (this should never happen, but we have to handle it)
         */
	if (Player.p_speed > Other.p_speed)
		Foestrikes = FALSE;
	else if (Other.p_speed > Player.p_speed)
		Foestrikes = TRUE;
	else if (Player.p_level > Other.p_level)
		Foestrikes = FALSE;
	else if (Other.p_level > Player.p_level)
		Foestrikes = TRUE;
	else {
		/* no one is faster */
		printw("You can't fight %s yet.", Enemyname);
		goto LEAVE;
	}

	for (;;) {
		displaystats();
		readmessage();
		mvprintw(1, 26, "%20.0f", Shield);	/* overprint energy */

		if (!Foestrikes)
			/* take action against foe */
			myturn();
		else
			/* wait for foe to take action */
		{
			mvaddstr(4, 0, "Waiting...\n");
			clrtoeol();
			refresh();

			for (loop = 0; loop < 20; ++loop)
				/* wait for foe to act */
			{
				readrecord(&Other, foeplace);
				if (Other.p_1scratch != oldhits)
					/* p_1scratch changes to indicate
					 * action */
					break;
				else
					/* wait and try again */
				{
					sleep(1);
					addch('.');
					refresh();
				}
			}

			if (Other.p_1scratch == oldhits) {
				/* timeout */
				mvaddstr(22, 0, "Timeout: waiting for response.  Do you want to wait ? ");
				ch = getanswer("NY", FALSE);
				move(22, 0);
				clrtobot();
				if (ch == 'Y')
					continue;
				else
					break;
			} else
				/* foe took action */
			{
				switch (Other.p_istat) {
				case I_RAN:	/* foe ran away */
					mvprintw(Lines++, 0, "%s ran away!", Enemyname);
					break;

				case I_STUCK:	/* foe tried to run, but
						 * couldn't */
					mvprintw(Lines++, 0, "%s tried to run away.", Enemyname);
					break;

				case I_BLEWIT:	/* foe tried to luckout, but
						 * didn't */
					mvprintw(Lines++, 0, "%s tried to luckout!", Enemyname);
					break;

				default:
					dtemp = Other.p_1scratch - oldhits;
					mvprintw(Lines++, 0, "%s hit you %.0f times!", Enemyname, dtemp);
					Shield -= dtemp;
					break;
				}

				oldhits = Other.p_1scratch;	/* keep track of old
								 * hits */

				if (Other.p_tampered != oldtampered)
					/* p_tampered changes to relinquish
					 * turn */
				{
					oldtampered = Other.p_tampered;
					Foestrikes = FALSE;
				}
			}
		}

		/* decide what happens next */
		refresh();
		if (Lines > LINES - 2) {
			more(Lines);
			move(Lines = 8, 0);
			clrtobot();
		}
		if (Other.p_istat == I_KILLED || Shield < 0.0)
			/* we died */
		{
			Shield = -2.0;	/* insure this value is negative */
			break;
		}
		if (Player.p_istat == I_KILLED)
			/* we killed foe; award treasre */
		{
			mvprintw(Lines++, 0, "You killed %s!", Enemyname);
			Player.p_experience += Other.p_experience;
			Player.p_crowns += (Player.p_level < 1000.0) ? Other.p_crowns : 0;
			Player.p_amulets += Other.p_amulets;
			Player.p_charms += Other.p_charms;
			collecttaxes(Other.p_gold, Other.p_gems);
			Player.p_sword = MAX(Player.p_sword, Other.p_sword);
			Player.p_shield = MAX(Player.p_shield, Other.p_shield);
			Player.p_quksilver = MAX(Player.p_quksilver, Other.p_quksilver);
			if (Other.p_virgin && !Player.p_virgin) {
				mvaddstr(Lines++, 0, "You have rescued a virgin.  Will you be honorable ? ");
				if ((ch = getanswer("YN", FALSE)) == 'Y')
					Player.p_virgin = TRUE;
				else {
					++Player.p_sin;
					Player.p_experience += 8000.0;
				}
			}
			sleep(3);	/* give other person time to die */
			break;
		} else
			if (Player.p_istat == I_RAN || Other.p_istat == I_RAN)
				/* either player ran away */
				break;
	}

LEAVE:
	/* clean up things and leave */
	writerecord(&Player, Fileloc);	/* update a final time */
	altercoordinates(0.0, 0.0, A_NEAR);	/* move away from battle site */
	Player.p_energy = Shield;	/* set energy to actual value */
	Player.p_tampered = T_OFF;	/* clear p_tampered */

	more(Lines);		/* pause */

	move(4, 0);
	clrtobot();		/* clear bottom area of screen */

	if (Player.p_energy < 0.0)
		/* we are dead */
		death("Interterminal battle");
}
/**/
/************************************************************************
/
/ FUNCTION NAME: myturn()
/
/ FUNCTION: process players action against foe in battle
/
/ AUTHOR: E. A. Estes, 2/7/86
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), inputoption(), floor(), wmove(), drandom(), 
/	waddstr(), wrefresh(), mvprintw(), wclrtoeol(), wclrtobot()
/
/ GLOBAL INPUTS: Lines, Other, Player, *stdscr, Fileloc, Luckout, 
/	*Enemyname
/
/ GLOBAL OUTPUTS: Foestrikes, Lines, Player, Luckout
/
/ DESCRIPTION:
/	Take action action against foe, and decide who is master
/	for next iteration.
/
*************************************************************************/

void
myturn(void)
{
	double  dtemp;		/* for temporary calculations */
	int     ch;		/* input */

	mvaddstr(7, 0, "1:Fight  2:Run Away!  3:Power Blast  ");
	if (Luckout)
		clrtoeol();
	else
		addstr("4:Luckout  ");

	ch = inputoption();
	move(Lines = 8, 0);
	clrtobot();

	switch (ch) {
	default:		/* fight */
		dtemp = ROLL(2.0, Player.p_might);
HIT:
		mvprintw(Lines++, 0, "You hit %s %.0f times!", Enemyname, dtemp);
		Player.p_sin += 0.5;
		Player.p_1scratch += dtemp;
		Player.p_istat = I_OFF;
		break;

	case '2':		/* run away */
		Player.p_1scratch -= 1.0;	/* change this to indicate
						 * action */
		if (drandom() > 0.25) {
			mvaddstr(Lines++, 0, "You got away!");
			Player.p_istat = I_RAN;
		} else {
			mvprintw(Lines++, 0, "%s is still after you!", Enemyname);
			Player.p_istat = I_STUCK;
		}
		break;

	case '3':		/* power blast */
		dtemp = MIN(Player.p_mana, Player.p_level * 5.0);
		Player.p_mana -= dtemp;
		dtemp *= (drandom() + 0.5) * Player.p_magiclvl * 0.2 + 2.0;
		mvprintw(Lines++, 0, "You blasted %s !", Enemyname);
		goto HIT;

	case '4':		/* luckout */
		if (Luckout || drandom() > 0.1) {
			if (Luckout)
				mvaddstr(Lines++, 0, "You already tried that!");
			else {
				mvaddstr(Lines++, 0, "Not this time . . .");
				Luckout = TRUE;
			}

			Player.p_1scratch -= 1.0;
			Player.p_istat = I_BLEWIT;
		} else {
			mvaddstr(Lines++, 0, "You just lucked out!");
			Player.p_1scratch = Other.p_energy * 1.1;
		}
		break;
	}

	refresh();
	Player.p_1scratch = floor(Player.p_1scratch);	/* clean up any mess */

	if (Player.p_1scratch > Other.p_energy)
		Player.p_istat = I_KILLED;
	else
		if (drandom() * Player.p_speed < drandom() * Other.p_speed)
			/* relinquish control */
		{
			++Player.p_tampered;
			Foestrikes = TRUE;
		}
	writerecord(&Player, Fileloc);	/* let foe know what we did */
}
/**/
/************************************************************************
/
/ FUNCTION NAME: checktampered()
/
/ FUNCTION: check if current player has been tampered with
/
/ AUTHOR: E. A. Estes, 12/4/85
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: readrecord(), fread(), fseek(), tampered(), writevoid()
/
/ GLOBAL INPUTS: *Energyvoidfp, Other, Player, Fileloc, Enrgyvoid
/
/ GLOBAL OUTPUTS: Enrgyvoid
/
/ DESCRIPTION:
/	Check for energy voids, holy grail, and tampering by other
/	players.
/
*************************************************************************/

void
checktampered(void)
{
	long    loc = 0L;	/* location in energy void file */

	/* first check for energy voids */
	fseek(Energyvoidfp, 0L, SEEK_SET);
	while (fread(&Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp) == 1)
		if (Enrgyvoid.ev_active
		    && Enrgyvoid.ev_x == Player.p_x
		    && Enrgyvoid.ev_y == Player.p_y)
			/* sitting on one */
		{
			if (loc > 0L)
				/* not the holy grail; inactivate energy void */
			{
				Enrgyvoid.ev_active = FALSE;
				writevoid(&Enrgyvoid, loc);
				tampered(T_NRGVOID, 0.0, 0.0);
			} else
				if (Player.p_status != S_CLOAKED)
					/* holy grail */
					tampered(T_GRAIL, 0.0, 0.0);
			break;
		} else
			loc += SZ_VOIDSTRUCT;

	/* now check for other things */
	readrecord(&Other, Fileloc);
	if (Other.p_tampered != T_OFF)
		tampered(Other.p_tampered, Other.p_1scratch, Other.p_2scratch);
}
/**/
/************************************************************************
/
/ FUNCTION NAME: tampered()
/
/ FUNCTION: take care of tampering by other players
/
/ AUTHOR: E. A. Estes, 12/4/85
/
/ ARGUMENTS:
/	int what - what type of tampering
/	double arg1, arg2 - rest of tampering info
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), more(), fread(), death(), fseek(), sleep(), 
/	floor(), wmove(), waddch(), drandom(), printw(), altercoordinates(), 
/	waddstr(), wrefresh(), encounter(), writevoid()
/
/ GLOBAL INPUTS: Other, Player, *stdscr, Enrgyvoid, *Playersfp
/
/ GLOBAL OUTPUTS: Other, Player, Changed, Enrgyvoid
/
/ DESCRIPTION:
/	Take care of energy voids, holy grail, decree and intervention
/	action on current player.
/
*************************************************************************/

void
tampered(int what, double arg1, double arg2)
{
	long    loc;		/* location in file of other players */

	Changed = TRUE;
	move(4, 0);

	Player.p_tampered = T_OFF;	/* no longer tampered with */

	switch (what) {
	case T_NRGVOID:
		addstr("You've hit an energy void !\n");
		Player.p_mana /= 3.0;
		Player.p_energy /= 2.0;
		Player.p_gold = floor(Player.p_gold / 1.25) + 0.1;
		altercoordinates(0.0, 0.0, A_NEAR);
		break;

	case T_TRANSPORT:
		addstr("The king transported you !  ");
		if (Player.p_charms > 0) {
			addstr("But your charm saved you. . .\n");
			--Player.p_charms;
		} else {
			altercoordinates(0.0, 0.0, A_FAR);
			addch('\n');
		}
		break;

	case T_BESTOW:
		printw("The king has bestowed %.0f gold pieces on you !\n", arg1);
		Player.p_gold += arg1;
		break;

	case T_CURSED:
		addstr("You've been cursed !  ");
		if (Player.p_blessing) {
			addstr("But your blessing saved you. . .\n");
			Player.p_blessing = FALSE;
		} else {
			addch('\n');
			Player.p_poison += 2.0;
			Player.p_energy = 10.0;
			Player.p_maxenergy *= 0.95;
			Player.p_status = S_PLAYING;	/* no longer cloaked */
		}
		break;

	case T_VAPORIZED:
		addstr("You have been vaporized!\n");
		more(7);
		death("Vaporization");
		break;

	case T_MONSTER:
		addstr("The Valar zapped you with a monster!\n");
		more(7);
		encounter((int) arg1);
		return;

	case T_BLESSED:
		addstr("The Valar has blessed you!\n");
		Player.p_energy = (Player.p_maxenergy *= 1.05) + Player.p_shield;
		Player.p_mana += 500.0;
		Player.p_strength += 0.5;
		Player.p_brains += 0.5;
		Player.p_magiclvl += 0.5;
		Player.p_poison = MIN(0.5, Player.p_poison);
		break;

	case T_RELOCATE:
		addstr("You've been relocated. . .\n");
		altercoordinates(arg1, arg2, A_FORCED);
		break;

	case T_HEAL:
		addstr("You've been healed!\n");
		Player.p_poison -= 0.25;
		Player.p_energy = Player.p_maxenergy + Player.p_shield;
		break;

	case T_EXVALAR:
		addstr("You are no longer Valar!\n");
		Player.p_specialtype = SC_COUNCIL;
		break;

	case T_GRAIL:
		addstr("You have found The Holy Grail!!\n");
		if (Player.p_specialtype < SC_COUNCIL)
			/* must be council of wise to behold grail */
		{
			addstr("However, you are not experienced enough to behold it.\n");
			Player.p_sin *= Player.p_sin;
			Player.p_mana += 1000;
		} else
			if (Player.p_specialtype == SC_VALAR
			    || Player.p_specialtype == SC_EXVALAR) {
				addstr("You have made it to the position of Valar once already.\n");
				addstr("The Grail is of no more use to you now.\n");
			} else {
				addstr("It is now time to see if you are worthy to behold it. . .\n");
				refresh();
				sleep(4);

				if (drandom() / 2.0 < Player.p_sin) {
					addstr("You have failed!\n");
					Player.p_strength =
					    Player.p_mana =
					    Player.p_energy =
					    Player.p_maxenergy =
					    Player.p_magiclvl =
					    Player.p_brains =
					    Player.p_experience =
					    Player.p_quickness = 1.0;

					altercoordinates(1.0, 1.0, A_FORCED);
					Player.p_level = 0.0;
				} else {
					addstr("You made to position of Valar!\n");
					Player.p_specialtype = SC_VALAR;
					Player.p_lives = 5;
					fseek(Playersfp, 0L, SEEK_SET);
					loc = 0L;
					while (fread(&Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
						/* search for existing valar */
						if (Other.p_specialtype == SC_VALAR
						    && Other.p_status != S_NOTUSED)
							/* found old valar */
						{
							Other.p_tampered = T_EXVALAR;
							writerecord(&Other, loc);
							break;
						} else
							loc += SZ_PLAYERSTRUCT;
				}
			}

		/* move grail to new location */
		Enrgyvoid.ev_active = TRUE;
		Enrgyvoid.ev_x = ROLL(-1.0e6, 2.0e6);
		Enrgyvoid.ev_y = ROLL(-1.0e6, 2.0e6);
		writevoid(&Enrgyvoid, 0L);
		break;
	}
	refresh();
	sleep(2);
}
/**/
/************************************************************************
/
/ FUNCTION NAME: userlist()
/
/ FUNCTION: print list of players and locations
/
/ AUTHOR: E. A. Estes, 2/28/86
/
/ ARGUMENTS:
/	bool ingameflag - set if called while playing
/
/ RETURN VALUE: none
/
/ MODULES CALLED: descrstatus(), descrlocation(), more(), fread(), fseek(), 
/	floor(), wmove(), printw(), waddstr(), distance(), wrefresh(), 
/	descrtype(), wclrtobot()
/
/ GLOBAL INPUTS: LINES, Other, Circle, Wizard, Player, *stdscr, *Playersfp
/
/ GLOBAL OUTPUTS: none
/
/ DESCRIPTION:
/	We can only see the coordinate of those closer to the origin
/	from us.
/	Kings and council of the wise can see and can be seen by everyone.
/	Palantirs are good for seeing everyone; and the valar can use
/	one to see through a 'cloak' spell.
/	The valar has no coordinates, and is completely invisible if
/	cloaked.
/
*************************************************************************/

void
userlist(bool ingameflag)
{
	int     numusers = 0;	/* number of users on file */

	if (ingameflag && Player.p_blindness) {
		mvaddstr(8, 0, "You cannot see anyone.\n");
		return;
	}
	fseek(Playersfp, 0L, SEEK_SET);
	mvaddstr(8, 0,
	    "Name                         X         Y    Lvl Type Login    Status\n");

	while (fread(&Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) {
		if (Other.p_status == S_NOTUSED
		/* record is unused */
		    || (Other.p_specialtype == SC_VALAR && Other.p_status == S_CLOAKED))
			/* cloaked valar */
		{
			if (!Wizard)
				/* wizard can see everything on file */
				continue;
		}
		++numusers;

		if (ingameflag &&
		/* must be playing for the rest of these conditions */
		    (Player.p_specialtype >= SC_KING
		/* kings and higher can see others */
			|| Other.p_specialtype >= SC_KING
		/* kings and higher can be seen by others */
			|| Circle >= CIRCLE(Other.p_x, Other.p_y)
		/* those nearer the origin can be seen */
			|| Player.p_palantir)
		/* palantir enables one to see others */
		    && (Other.p_status != S_CLOAKED
			|| (Player.p_specialtype == SC_VALAR && Player.p_palantir))
		/* not cloaked; valar can see through cloak with a palantir */
		    && Other.p_specialtype != SC_VALAR)
			/* not a valar */
			/* coordinates should be printed */
			printw("%-20s  %8.0f  %8.0f ",
			    Other.p_name, Other.p_x, Other.p_y);
		else
			/* cannot see player's coordinates */
			printw("%-20s %19.19s ",
			    Other.p_name, descrlocation(&Other, TRUE));

		printw("%6.0f %s  %-9.9s%s\n", Other.p_level, descrtype(&Other, TRUE),
		    Other.p_login, descrstatus(&Other));

		if ((numusers % (LINES - 10)) == 0) {
			more(LINES - 1);
			move(9, 0);
			clrtobot();
		}
	}

	printw("Total players on file = %d\n", numusers);
	refresh();
}
/**/
/************************************************************************
/
/ FUNCTION NAME: throneroom()
/
/ FUNCTION: king stuff upon entering throne
/
/ AUTHOR: E. A. Estes, 12/16/85
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), fread(), fseek(), fopen(), wmove(), fclose(), 
/	fwrite(), altercoordinates(), waddstr(), fprintf()
/
/ GLOBAL INPUTS: *Energyvoidfp, Other, Player, *stdscr,
/	Enrgyvoid, *Playersfp
/
/ GLOBAL OUTPUTS: Other, Player, Changed
/
/ DESCRIPTION:
/	If player is not already king, make him/her so if the old king
/	is not playing.
/	Clear energy voids with new king.
/	Print 'decree' prompt.
/
*************************************************************************/

void
throneroom(void)
{
	FILE   *fp;		/* to clear energy voids */
	long    loc = 0L;	/* location of old king in player file */

	if (Player.p_specialtype < SC_KING)
		/* not already king -- assumes crown */
	{
		fseek(Playersfp, 0L, SEEK_SET);
		while (fread(&Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
			if (Other.p_specialtype == SC_KING && Other.p_status != S_NOTUSED)
				/* found old king */
			{
				if (Other.p_status != S_OFF)
					/* old king is playing */
				{
					mvaddstr(4, 0, "The king is playing, so you cannot steal his throne\n");
					altercoordinates(0.0, 0.0, A_NEAR);
					move(6, 0);
					return;
				} else
					/* old king is not playing - remove
					 * him/her */
				{
					Other.p_specialtype = SC_NONE;
					if (Other.p_crowns)
						--Other.p_crowns;
					writerecord(&Other, loc);
					break;
				}
			} else
				loc += SZ_PLAYERSTRUCT;

		/* make player new king */
		Changed = TRUE;
		Player.p_specialtype = SC_KING;
		mvaddstr(4, 0, "You have become king!\n");

		/* let everyone else know */
		fp = fopen(_PATH_MESS, "w");
		fprintf(fp, "All hail the new king!");
		fclose(fp);

		/* clear all energy voids; retain location of holy grail */
		fseek(Energyvoidfp, 0L, SEEK_SET);
		fread(&Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp);
		fp = fopen(_PATH_VOID, "w");
		fwrite(&Enrgyvoid, SZ_VOIDSTRUCT, 1, fp);
		fclose(fp);
	}
	mvaddstr(6, 0, "0:Decree  ");
}
/**/
/************************************************************************
/
/ FUNCTION NAME: dotampered()
/
/ FUNCTION: king and valar special options
/
/ AUTHOR: E. A. Estes, 2/28/86
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), truncstring(), fread(), fseek(), fopen(), 
/	floor(), wmove(), drandom(), fclose(), fwrite(), sscanf(), strcmp(), 
/	infloat(), waddstr(), findname(), distance(), userlist(), mvprintw(), 
/	allocvoid(), getanswer(), getstring(), wclrtoeol(), writevoid()
/
/ GLOBAL INPUTS: *Energyvoidfp, Other, Illcmd[], Wizard, Player, *stdscr, 
/	Databuf[], Enrgyvoid
/
/ GLOBAL OUTPUTS: Other, Player, Enrgyvoid
/
/ DESCRIPTION:
/	Tamper with other players.  Handle king/valar specific options.
/
*************************************************************************/

void
dotampered(void)
{
	short   tamper;		/* value for tampering with other players */
	char   *option;		/* pointer to option description */
	double  temp1 = 0.0, temp2 = 0.0;	/* other tampering values */
	int     ch;		/* input */
	long    loc;		/* location in energy void file */
	FILE   *fp;		/* for opening gold file */

	move(6, 0);
	clrtoeol();
	if (Player.p_specialtype < SC_COUNCIL && !Wizard)
		/* king options */
	{
		addstr("1:Transport  2:Curse  3:Energy Void  4:Bestow  5:Collect Taxes  ");

		ch = getanswer(" ", TRUE);
		move(6, 0);
		clrtoeol();
		move(4, 0);
		switch (ch) {
		case '1':	/* transport someone */
			tamper = T_TRANSPORT;
			option = "transport";
			break;

		case '2':	/* curse another */
			tamper = T_CURSED;
			option = "curse";
			break;

		case '3':	/* create energy void */
			if ((loc = allocvoid()) > 20L * SZ_VOIDSTRUCT)
				/* can only have 20 void active at once */
				mvaddstr(5, 0, "Sorry, void creation limit reached.\n");
			else {
				addstr("Enter the X Y coordinates of void ? ");
				getstring(Databuf, SZ_DATABUF);
				sscanf(Databuf, "%lf %lf", &temp1, &temp2);
				Enrgyvoid.ev_x = floor(temp1);
				Enrgyvoid.ev_y = floor(temp2);
				Enrgyvoid.ev_active = TRUE;
				writevoid(&Enrgyvoid, loc);
				mvaddstr(5, 0, "It is done.\n");
			}
			return;

		case '4':	/* bestow gold to subject */
			tamper = T_BESTOW;
			addstr("How much gold to bestow ? ");
			temp1 = infloat();
			if (temp1 > Player.p_gold || temp1 < 0) {
				mvaddstr(5, 0, "You don't have that !\n");
				return;
			}
			/* adjust gold after we are sure it will be given to
			 * someone */
			option = "give gold to";
			break;

		case '5':	/* collect accumulated taxes */
			if ((fp = fopen(_PATH_GOLD, "r+")) != NULL)
				/* collect taxes */
			{
				fread(&temp1, sizeof(double), 1, fp);
				fseek(fp, 0L, SEEK_SET);
				/* clear out value */
				temp2 = 0.0;
				fwrite(&temp2, sizeof(double), 1, fp);
				fclose(fp);
			}
			mvprintw(4, 0, "You have collected %.0f in gold.\n", temp1);
			Player.p_gold += floor(temp1);
			return;

		default:
			return;
		}
		/* end of king options */
	} else
		/* council of wise, valar, wizard options */
	{
		addstr("1:Heal  ");
		if (Player.p_palantir || Wizard)
			addstr("2:Seek Grail  ");
		if (Player.p_specialtype == SC_VALAR || Wizard)
			addstr("3:Throw Monster  4:Relocate  5:Bless  ");
		if (Wizard)
			addstr("6:Vaporize  ");

		ch = getanswer(" ", TRUE);
		if (!Wizard) {
			if (ch > '2' && Player.p_specialtype != SC_VALAR) {
				ILLCMD();
				return;
			}
			if (Player.p_mana < MM_INTERVENE) {
				mvaddstr(5, 0, "No mana left.\n");
				return;
			} else
				Player.p_mana -= MM_INTERVENE;
		}
		switch (ch) {
		case '1':	/* heal another */
			tamper = T_HEAL;
			option = "heal";
			break;

		case '2':	/* seek grail */
			if (Player.p_palantir)
				/* need a palantir to seek */
			{
				fseek(Energyvoidfp, 0L, SEEK_SET);
				fread(&Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp);
				temp1 = distance(Player.p_x, Enrgyvoid.ev_x, Player.p_y, Enrgyvoid.ev_y);
				temp1 += ROLL(-temp1 / 10.0, temp1 / 5.0);	/* add some error */
				mvprintw(5, 0, "The palantir says the Grail is about %.0f away.\n", temp1);
			} else
				/* no palantir */
				mvaddstr(5, 0, "You need a palantir to seek the Grail.\n");
			return;

		case '3':	/* lob monster at someone */
			mvaddstr(4, 0, "Which monster [0-99] ? ");
			temp1 = infloat();
			temp1 = MAX(0.0, MIN(99.0, temp1));
			tamper = T_MONSTER;
			option = "throw a monster at";
			break;

		case '4':	/* move another player */
			mvaddstr(4, 0, "New X Y coordinates ? ");
			getstring(Databuf, SZ_DATABUF);
			sscanf(Databuf, "%lf %lf", &temp1, &temp2);
			tamper = T_RELOCATE;
			option = "relocate";
			break;

		case '5':	/* bless a player */
			tamper = T_BLESSED;
			option = "bless";
			break;

		case '6':	/* kill off a player */
			if (Wizard) {
				tamper = T_VAPORIZED;
				option = "vaporize";
				break;
			} else
				return;

		default:
			return;
		}

		/* adjust age after we are sure intervention will be done */
		/* end of valar, etc. options */
	}

	for (;;)
		/* prompt for player to affect */
	{
		mvprintw(4, 0, "Who do you want to %s ? ", option);
		getstring(Databuf, SZ_DATABUF);
		truncstring(Databuf);

		if (Databuf[0] == '\0')
			userlist(TRUE);
		else
			break;
	}

	if (strcmp(Player.p_name, Databuf) != 0)
		/* name other than self */
	{
		if ((loc = findname(Databuf, &Other)) >= 0L) {
			if (Other.p_tampered != T_OFF) {
				mvaddstr(5, 0, "That person has something pending already.\n");
				return;
			} else {
				if (tamper == T_RELOCATE
				    && CIRCLE(temp1, temp2) < CIRCLE(Other.p_x, Other.p_y)
				    && !Wizard)
					mvaddstr(5, 0, "Cannot move someone closer to the Lord's Chamber.\n");
				else {
					if (tamper == T_BESTOW)
						Player.p_gold -= floor(temp1);
					if (!Wizard && (tamper == T_HEAL || tamper == T_MONSTER ||
						tamper == T_RELOCATE || tamper == T_BLESSED))
						Player.p_age += N_AGE;	/* age penalty */
					Other.p_tampered = tamper;
					Other.p_1scratch = floor(temp1);
					Other.p_2scratch = floor(temp2);
					writerecord(&Other, loc);
					mvaddstr(5, 0, "It is done.\n");
				}
				return;
			}
		} else
			/* player not found */
			mvaddstr(5, 0, "There is no one by that name.\n");
	} else
		/* self */
		mvaddstr(5, 0, "You may not do it to yourself!\n");
}
/**/
/************************************************************************
/
/ FUNCTION NAME: writevoid()
/
/ FUNCTION: update energy void entry in energy void file
/
/ AUTHOR: E. A. Estes, 12/4/85
/
/ ARGUMENTS:
/	struct energyvoid *vp - pointer to structure to write to file
/	long loc - location in file to update
/
/ RETURN VALUE: none
/
/ MODULES CALLED: fseek(), fwrite(), fflush()
/
/ GLOBAL INPUTS: *Energyvoidfp
/
/ GLOBAL OUTPUTS: none
/
/ DESCRIPTION:
/	Write out energy void structure at specified location.
/
*************************************************************************/

void
writevoid(struct energyvoid *vp, long loc)
{

	fseek(Energyvoidfp, loc, SEEK_SET);
	fwrite(vp, SZ_VOIDSTRUCT, 1, Energyvoidfp);
	fflush(Energyvoidfp);
	fseek(Energyvoidfp, 0L, SEEK_SET);
}
/**/
/************************************************************************
/
/ FUNCTION NAME: allocvoid()
/
/ FUNCTION: allocate space for a new energy void
/
/ AUTHOR: E. A. Estes, 12/4/85
/
/ ARGUMENTS: none
/
/ RETURN VALUE: location of new energy void space
/
/ MODULES CALLED: fread(), fseek()
/
/ GLOBAL INPUTS: *Energyvoidfp, Enrgyvoid
/
/ GLOBAL OUTPUTS: none
/
/ DESCRIPTION:
/	Search energy void file for an inactive entry and return its
/	location.
/	If no inactive ones are found, return one more than last location.
/
*************************************************************************/

long
allocvoid(void)
{
	long    loc = 0L;	/* location of new energy void */

	fseek(Energyvoidfp, 0L, SEEK_SET);
	while (fread(&Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp) == 1)
		if (Enrgyvoid.ev_active)
			loc += SZ_VOIDSTRUCT;
		else
			break;

	return (loc);
}