xref: /csrg-svn/games/phantasia/misc.c (revision 56571)
134606Sbostic /*
234606Sbostic  * misc.c  Phantasia miscellaneous support routines
334606Sbostic  */
434606Sbostic 
534606Sbostic #include "include.h"
634606Sbostic 
756101Selan 
834606Sbostic /************************************************************************
934606Sbostic /
1034606Sbostic / FUNCTION NAME: movelevel()
1134606Sbostic /
1234606Sbostic / FUNCTION: move player to new level
1334606Sbostic /
1434606Sbostic / AUTHOR: E. A. Estes, 12/4/85
1534606Sbostic /
1634606Sbostic / ARGUMENTS: none
1734606Sbostic /
1834606Sbostic / RETURN VALUE: none
1934606Sbostic /
2034606Sbostic / MODULES CALLED: death(), floor(), wmove(), drandom(), waddstr(), explevel()
2134606Sbostic /
2234606Sbostic / GLOBAL INPUTS: Player, *stdscr, *Statptr, Stattable[]
2334606Sbostic /
2434606Sbostic / GLOBAL OUTPUTS: Player, Changed
2534606Sbostic /
2634606Sbostic / DESCRIPTION:
2734606Sbostic /	Use lookup table to increment important statistics when
2834606Sbostic /	progressing to new experience level.
2934606Sbostic /	Players are rested to maximum as a bonus for making a new
3034606Sbostic /	level.
3134606Sbostic /	Check for council of wise, and being too big to be king.
3234606Sbostic /
3334606Sbostic /************************************************************************/
3434606Sbostic 
movelevel()3534606Sbostic movelevel()
3634606Sbostic {
3734606Sbostic register struct charstats	*statptr;	/* for pointing into Stattable */
3834606Sbostic double	new;			/* new level */
3934606Sbostic double	inc;			/* increment between new and old levels */
4034606Sbostic 
4134606Sbostic     Changed = TRUE;
4234606Sbostic 
4334606Sbostic     if (Player.p_type == C_EXPER)
4434606Sbostic 	/* roll a type to use for increment */
4534606Sbostic 	statptr = &Stattable[(int) ROLL(C_MAGIC, C_HALFLING - C_MAGIC + 1)];
4634606Sbostic     else
4734606Sbostic 	statptr = Statptr;
4834606Sbostic 
4934606Sbostic     new = explevel(Player.p_experience);
5034606Sbostic     inc = new - Player.p_level;
5134606Sbostic     Player.p_level = new;
5234606Sbostic 
5334606Sbostic     /* add increments to statistics */
5434606Sbostic     Player.p_strength += statptr->c_strength.increase * inc;
5534606Sbostic     Player.p_mana += statptr->c_mana.increase * inc;
5634606Sbostic     Player.p_brains += statptr->c_brains.increase * inc;
5734606Sbostic     Player.p_magiclvl += statptr->c_magiclvl.increase * inc;
5834606Sbostic     Player.p_maxenergy += statptr->c_energy.increase * inc;
5934606Sbostic 
6034606Sbostic     /* rest to maximum upon reaching new level */
6134606Sbostic     Player.p_energy = Player.p_maxenergy + Player.p_shield;
6234606Sbostic 
6334606Sbostic     if (Player.p_crowns > 0 && Player.p_level >= 1000.0)
6434606Sbostic 	/* no longer able to be king -- turn crowns into cash */
6534606Sbostic 	{
6634606Sbostic 	Player.p_gold += ((double) Player.p_crowns) * 5000.0;
6734606Sbostic 	Player.p_crowns = 0;
6834606Sbostic 	}
6934606Sbostic 
7034606Sbostic     if (Player.p_level >= 3000.0 && Player.p_specialtype < SC_COUNCIL)
7134606Sbostic 	/* make a member of the council */
7234606Sbostic 	{
7334606Sbostic 	mvaddstr(6, 0, "You have made it to the Council of the Wise.\n");
7434606Sbostic 	addstr("Good Luck on your search for the Holy Grail.\n");
7534606Sbostic 
7634606Sbostic 	Player.p_specialtype = SC_COUNCIL;
7734606Sbostic 
7834606Sbostic 	/* no rings for council and above */
7934606Sbostic 	Player.p_ring.ring_type = R_NONE;
8034606Sbostic 	Player.p_ring.ring_duration = 0;
8134606Sbostic 
8234606Sbostic 	Player.p_lives = 3;		/* three extra lives */
8334606Sbostic 	}
8434606Sbostic 
8534606Sbostic     if (Player.p_level > 9999.0 && Player.p_specialtype != SC_VALAR)
8634606Sbostic 	death("Old age");
8734606Sbostic }
8834606Sbostic /**/
8934606Sbostic /************************************************************************
9034606Sbostic /
9134606Sbostic / FUNCTION NAME: descrlocation()
9234606Sbostic /
9334606Sbostic / FUNCTION: return a formatted description of location
9434606Sbostic /
9534606Sbostic / AUTHOR: E. A. Estes, 12/4/85
9634606Sbostic /
9734606Sbostic / ARGUMENTS:
9834606Sbostic /	struct player playerp - pointer to player structure
9934606Sbostic /	bool shortflag - set if short form is desired
10034606Sbostic /
10134606Sbostic / RETURN VALUE: pointer to string containing result
10234606Sbostic /
10334606Sbostic / MODULES CALLED: fabs(), floor(), sprintf(), distance()
10434606Sbostic /
10534606Sbostic / GLOBAL INPUTS: Databuf[]
10634606Sbostic /
10734606Sbostic / GLOBAL OUTPUTS: none
10834606Sbostic /
10934606Sbostic / DESCRIPTION:
11034606Sbostic /	Look at coordinates and return an appropriately formatted
11134606Sbostic /	string.
11234606Sbostic /
11334606Sbostic /************************************************************************/
11434606Sbostic 
11534606Sbostic char	*
descrlocation(playerp,shortflag)11634606Sbostic descrlocation(playerp, shortflag)
11734606Sbostic struct player	*playerp;
11834606Sbostic bool	shortflag;
11934606Sbostic {
12034606Sbostic double	circle;			/* corresponding circle for coordinates */
12134606Sbostic register int	quadrant;	/* quandrant of grid */
12234606Sbostic register char	*label;		/* pointer to place name */
12334606Sbostic static char	*nametable[4][4] =   /* names of places */
12434606Sbostic 	{
12534606Sbostic 	"Anorien",	"Ithilien",	"Rohan",	"Lorien",
12634606Sbostic 	"Gondor",	"Mordor",	"Dunland",	"Rovanion",
12734606Sbostic 	"South Gondor", "Khand",	"Eriador",	"The Iron Hills",
12834606Sbostic 	"Far Harad",	"Near Harad",	"The Northern Waste", "Rhun"
12934606Sbostic 	};
13034606Sbostic 
13134606Sbostic     if (playerp->p_specialtype == SC_VALAR)
13234606Sbostic 	return(" is in Valhala");
13334606Sbostic     else if ((circle = CIRCLE(playerp->p_x, playerp->p_y)) >= 1000.0)
13434606Sbostic 	{
13534606Sbostic 	if (MAX(fabs(playerp->p_x), fabs(playerp->p_y)) > D_BEYOND)
13634606Sbostic 	    label = "The Point of No Return";
13734606Sbostic 	else
13834606Sbostic 	    label = "The Ashen Mountains";
13934606Sbostic 	}
14034606Sbostic     else if (circle >= 55)
14134606Sbostic 	label = "Morannon";
14234606Sbostic     else if (circle >= 35)
14334606Sbostic 	label = "Kennaquahair";
14434606Sbostic     else if (circle >= 20)
14534606Sbostic 	label = "The Dead Marshes";
14634606Sbostic     else if (circle >= 9)
14734606Sbostic 	label = "The Outer Waste";
14834606Sbostic     else if (circle >= 5)
14934606Sbostic 	label = "The Moors Adventurous";
15034606Sbostic     else
15134606Sbostic 	{
15234606Sbostic 	if (playerp->p_x == 0.0 && playerp->p_y == 0.0)
15334606Sbostic 	    label = "The Lord's Chamber";
15434606Sbostic 	else
15534606Sbostic 	    {
15634606Sbostic 	    /* this expression is split to prevent compiler loop with some compilers */
15734606Sbostic 	    quadrant = ((playerp->p_x > 0.0) ? 1 : 0);
15834606Sbostic 	    quadrant += ((playerp->p_y >= 0.0) ? 2 : 0);
15934606Sbostic 	    label = nametable[((int) circle) - 1][quadrant];
16034606Sbostic 	    }
16134606Sbostic 	}
16234606Sbostic 
16334606Sbostic     if (shortflag)
16434606Sbostic 	sprintf(Databuf, "%.29s", label);
16534606Sbostic     else
16634606Sbostic 	sprintf(Databuf, " is in %s  (%.0f,%.0f)", label, playerp->p_x, playerp->p_y);
16734606Sbostic 
16834606Sbostic     return(Databuf);
16934606Sbostic }
17034606Sbostic /**/
17134606Sbostic /************************************************************************
17234606Sbostic /
17334606Sbostic / FUNCTION NAME: tradingpost()
17434606Sbostic /
17534606Sbostic / FUNCTION: do trading post stuff
17634606Sbostic /
17734606Sbostic / AUTHOR: E. A. Estes, 12/4/85
17834606Sbostic /
17934606Sbostic / ARGUMENTS: none
18034606Sbostic /
18134606Sbostic / RETURN VALUE: none
18234606Sbostic /
18334606Sbostic / MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
18434606Sbostic /	sleep(), floor(), wmove(), drandom(), wclear(), printw(),
18534606Sbostic /	altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(),
18634606Sbostic /	wclrtoeol(), wclrtobot()
18734606Sbostic /
18834606Sbostic / GLOBAL INPUTS: Menu[], Circle, Player, *stdscr, Fileloc, Nobetter[]
18934606Sbostic /
19034606Sbostic / GLOBAL OUTPUTS: Player
19134606Sbostic /
19234606Sbostic / DESCRIPTION:
19334606Sbostic /	Different trading posts have different items.
19434606Sbostic /	Merchants cannot be cheated, but they can be dishonest
19534606Sbostic /	themselves.
19634606Sbostic /
19734606Sbostic /	Shields, swords, and quicksilver are not cumulative.  This is
19834606Sbostic /	one major area of complaint, but there are two reasons for this:
19934606Sbostic /		1) It becomes MUCH too easy to make very large versions
20034606Sbostic /		   of these items.
20134606Sbostic /		2) In the real world, one cannot simply weld two swords
20234606Sbostic /		   together to make a bigger one.
20334606Sbostic /
20434606Sbostic /	At one time, it was possible to sell old weapons at half the purchase
20534606Sbostic /	price.  This resulted in huge amounts of gold floating around,
20634606Sbostic /	and the game lost much of its challenge.
20734606Sbostic /
20834606Sbostic /	Also, purchasing gems defeats the whole purpose of gold.  Gold
20934606Sbostic /	is small change for lower level players.  They really shouldn't
21034606Sbostic /	be able to accumulate more than enough gold for a small sword or
21134606Sbostic /	a few books.  Higher level players shouldn't even bother to pick
21234606Sbostic /	up gold, except maybe to buy mana once in a while.
21334606Sbostic /
21434606Sbostic /************************************************************************/
21534606Sbostic 
tradingpost()21634606Sbostic tradingpost()
21734606Sbostic {
21834606Sbostic double	numitems;	/* number of items to purchase */
21934606Sbostic double	cost;		/* cost of purchase */
22034606Sbostic double	blessingcost;	/* cost of blessing */
22134606Sbostic int	ch;		/* input */
22234606Sbostic register int	size;	/* size of the trading post */
22334606Sbostic register int	loop;	/* loop counter */
22434606Sbostic int	cheat = 0;	/* number of times player has tried to cheat */
22534606Sbostic bool	dishonest = FALSE;/* set when merchant is dishonest */
22634606Sbostic 
22734606Sbostic     Player.p_status = S_TRADING;
22834606Sbostic     writerecord(&Player, Fileloc);
22934606Sbostic 
23034606Sbostic     clear();
23134606Sbostic     addstr("You are at a trading post. All purchases must be made with gold.");
23234606Sbostic 
23334606Sbostic     size = sqrt(fabs(Player.p_x / 100)) + 1;
23434606Sbostic     size = MIN(7, size);
23534606Sbostic 
23634606Sbostic     /* set up cost of blessing */
23734606Sbostic     blessingcost = 1000.0 * (Player.p_level + 5.0);
23834606Sbostic 
23934606Sbostic     /* print Menu */
24034606Sbostic     move(7, 0);
24134606Sbostic     for (loop = 0; loop < size; ++loop)
24234606Sbostic 	/* print Menu */
24334606Sbostic 	{
24434606Sbostic 	if (loop == 6)
24534606Sbostic 	    cost = blessingcost;
24634606Sbostic 	else
24734606Sbostic 	    cost = Menu[loop].cost;
24834606Sbostic 	printw("(%d) %-12s: %6.0f\n", loop + 1, Menu[loop].item, cost);
24934606Sbostic 	}
25034606Sbostic 
25134606Sbostic     mvprintw(5, 0, "L:Leave  P:Purchase  S:Sell Gems ? ");
25234606Sbostic 
25334606Sbostic     for (;;)
25434606Sbostic 	{
25534606Sbostic 	adjuststats();	/* truncate any bad values */
25634606Sbostic 
25734606Sbostic 	/* print some important statistics */
25834606Sbostic 	mvprintw(1, 0, "Gold:   %9.0f  Gems:  %9.0f  Level:   %6.0f  Charms: %6d\n",
25934606Sbostic 	    Player.p_gold, Player.p_gems, Player.p_level, Player.p_charms);
26034606Sbostic 	printw("Shield: %9.0f  Sword: %9.0f  Quicksilver:%3.0f  Blessed: %s\n",
26134606Sbostic 	    Player.p_shield, Player.p_sword, Player.p_quksilver,
26234606Sbostic 	    (Player.p_blessing ? " True" : "False"));
26334606Sbostic 	printw("Brains: %9.0f  Mana:  %9.0f", Player.p_brains, Player.p_mana);
26434606Sbostic 
26534606Sbostic 	move(5, 36);
26634606Sbostic 	ch = getanswer("LPS", FALSE);
26734606Sbostic 	move(15, 0);
26834606Sbostic 	clrtobot();
26934606Sbostic 	switch(ch)
27034606Sbostic 	    {
27134606Sbostic 	    case 'L':		/* leave */
27234606Sbostic 	    case '\n':
27334606Sbostic 		altercoordinates(0.0, 0.0, A_NEAR);
27434606Sbostic 		return;
27534606Sbostic 
27634606Sbostic 	    case 'P':		/* make purchase */
27734606Sbostic 		mvaddstr(15, 0, "What what would you like to buy ? ");
27834606Sbostic 		ch = getanswer(" 1234567", FALSE);
27934606Sbostic 		move(15, 0);
28034606Sbostic 		clrtoeol();
28134606Sbostic 
28234606Sbostic 		if (ch - '0' > size)
28334606Sbostic 		    addstr("Sorry, this merchant doesn't have that.");
28434606Sbostic 		else
28534606Sbostic 		    switch (ch)
28634606Sbostic 			{
28734606Sbostic 			case '1':
28834606Sbostic 			    printw("Mana is one per %.0f gold piece.  How many do you want (%.0f max) ? ",
28934606Sbostic 				Menu[0].cost, floor(Player.p_gold / Menu[0].cost));
29034606Sbostic 			    cost = (numitems = floor(infloat())) * Menu[0].cost;
29134606Sbostic 
29234606Sbostic 			    if (cost > Player.p_gold || numitems < 0)
29334606Sbostic 				++cheat;
29434606Sbostic 			    else
29534606Sbostic 				{
29634606Sbostic 				cheat = 0;
29734606Sbostic 				Player.p_gold -= cost;
29834606Sbostic 				if (drandom() < 0.02)
29934606Sbostic 				    dishonest = TRUE;
30034606Sbostic 				else
30134606Sbostic 				    Player.p_mana += numitems;
30234606Sbostic 				}
30334606Sbostic 			    break;
30434606Sbostic 
30534606Sbostic 			case '2':
30634606Sbostic 			    printw("Shields are %.0f per +1.  How many do you want (%.0f max) ? ",
30734606Sbostic 				Menu[1].cost, floor(Player.p_gold / Menu[1].cost));
30834606Sbostic 			    cost = (numitems = floor(infloat())) * Menu[1].cost;
30934606Sbostic 
31034606Sbostic 			    if (numitems == 0.0)
31134606Sbostic 				break;
31234606Sbostic 			    else if (cost > Player.p_gold || numitems < 0)
31334606Sbostic 				++cheat;
31434606Sbostic 			    else if (numitems < Player.p_shield)
31534606Sbostic 				NOBETTER();
31634606Sbostic 			    else
31734606Sbostic 				{
31834606Sbostic 				cheat = 0;
31934606Sbostic 				Player.p_gold -= cost;
32034606Sbostic 				if (drandom() < 0.02)
32134606Sbostic 				    dishonest = TRUE;
32234606Sbostic 				else
32334606Sbostic 				    Player.p_shield = numitems;
32434606Sbostic 				}
32534606Sbostic 			    break;
32634606Sbostic 
32734606Sbostic 			case '3':
32834606Sbostic 			    printw("A book costs %.0f gp.  How many do you want (%.0f max) ? ",
32934606Sbostic 				Menu[2].cost, floor(Player.p_gold / Menu[2].cost));
33034606Sbostic 			    cost = (numitems = floor(infloat())) * Menu[2].cost;
33134606Sbostic 
33234606Sbostic 			    if (cost > Player.p_gold || numitems < 0)
33334606Sbostic 				++cheat;
33434606Sbostic 			    else
33534606Sbostic 				{
33634606Sbostic 				cheat = 0;
33734606Sbostic 				Player.p_gold -= cost;
33834606Sbostic 				if (drandom() < 0.02)
33934606Sbostic 				    dishonest = TRUE;
34034606Sbostic 				else if (drandom() * numitems > Player.p_level / 10.0
34134606Sbostic 				    && numitems != 1)
34234606Sbostic 				    {
34334606Sbostic 				    printw("\nYou blew your mind!\n");
34434606Sbostic 				    Player.p_brains /= 5;
34534606Sbostic 				    }
34634606Sbostic 				else
34734606Sbostic 				    {
34834606Sbostic 				    Player.p_brains += floor(numitems) * ROLL(20, 8);
34934606Sbostic 				    }
35034606Sbostic 				}
35134606Sbostic 			    break;
35234606Sbostic 
35334606Sbostic 			case '4':
35434606Sbostic 			    printw("Swords are %.0f gp per +1.  How many + do you want (%.0f max) ? ",
35534606Sbostic 				Menu[3].cost, floor(Player.p_gold / Menu[3].cost));
35634606Sbostic 			    cost = (numitems = floor(infloat())) * Menu[3].cost;
35734606Sbostic 
35834606Sbostic 			    if (numitems == 0.0)
35934606Sbostic 				break;
36034606Sbostic 			    else if (cost > Player.p_gold || numitems < 0)
36134606Sbostic 				++cheat;
36234606Sbostic 			    else if (numitems < Player.p_sword)
36334606Sbostic 				NOBETTER();
36434606Sbostic 			    else
36534606Sbostic 				{
36634606Sbostic 				cheat = 0;
36734606Sbostic 				Player.p_gold -= cost;
36834606Sbostic 				if (drandom() < 0.02)
36934606Sbostic 				    dishonest = TRUE;
37034606Sbostic 				else
37134606Sbostic 				    Player.p_sword = numitems;
37234606Sbostic 				}
37334606Sbostic 			    break;
37434606Sbostic 
37534606Sbostic 			case '5':
37634606Sbostic 			    printw("A charm costs %.0f gp.  How many do you want (%.0f max) ? ",
37734606Sbostic 				Menu[4].cost, floor(Player.p_gold / Menu[4].cost));
37834606Sbostic 			    cost = (numitems = floor(infloat())) * Menu[4].cost;
37934606Sbostic 
38034606Sbostic 			    if (cost > Player.p_gold || numitems < 0)
38134606Sbostic 				++cheat;
38234606Sbostic 			    else
38334606Sbostic 				{
38434606Sbostic 				cheat = 0;
38534606Sbostic 				Player.p_gold -= cost;
38634606Sbostic 				if (drandom() < 0.02)
38734606Sbostic 				    dishonest = TRUE;
38834606Sbostic 				else
38934606Sbostic 				    Player.p_charms += numitems;
39034606Sbostic 				}
39134606Sbostic 			    break;
39234606Sbostic 
39334606Sbostic 			case '6':
39434606Sbostic 			    printw("Quicksilver is %.0f gp per +1.  How many + do you want (%.0f max) ? ",
39534606Sbostic 				Menu[5].cost, floor(Player.p_gold / Menu[5].cost));
39634606Sbostic 			    cost = (numitems = floor(infloat())) * Menu[5].cost;
39734606Sbostic 
39834606Sbostic 			    if (numitems == 0.0)
39934606Sbostic 				break;
40034606Sbostic 			    else if (cost > Player.p_gold || numitems < 0)
40134606Sbostic 				++cheat;
40234606Sbostic 			    else if (numitems < Player.p_quksilver)
40334606Sbostic 				NOBETTER();
40434606Sbostic 			    else
40534606Sbostic 				{
40634606Sbostic 				cheat = 0;
40734606Sbostic 				Player.p_gold -= cost;
40834606Sbostic 				if (drandom() < 0.02)
40934606Sbostic 				    dishonest = TRUE;
41034606Sbostic 				else
41134606Sbostic 				    Player.p_quksilver = numitems;
41234606Sbostic 				}
41334606Sbostic 			    break;
41434606Sbostic 
41534606Sbostic 			case '7':
41634606Sbostic 			    if (Player.p_blessing)
41734606Sbostic 				{
41834606Sbostic 				addstr("You already have a blessing.");
41934606Sbostic 				break;
42034606Sbostic 				}
42134606Sbostic 
42234606Sbostic 			    printw("A blessing requires a %.0f gp donation.  Still want one ? ", blessingcost);
42334606Sbostic 			    ch = getanswer("NY", FALSE);
42434606Sbostic 
42534606Sbostic 			    if (ch == 'Y')
42634606Sbostic 				if (Player.p_gold < blessingcost)
42734606Sbostic 				    ++cheat;
42834606Sbostic 				else
42934606Sbostic 				    {
43034606Sbostic 				    cheat = 0;
43134606Sbostic 				    Player.p_gold -= blessingcost;
43234606Sbostic 				    if (drandom() < 0.02)
43334606Sbostic 					dishonest = TRUE;
43434606Sbostic 				    else
43534606Sbostic 					Player.p_blessing = TRUE;
43634606Sbostic 				    }
43734606Sbostic 			    break;
43834606Sbostic 			}
43934606Sbostic 	    break;
44034606Sbostic 
44134606Sbostic 	    case 'S':		/* sell gems */
44234606Sbostic 		mvprintw(15, 0, "A gem is worth %.0f gp.  How many do you want to sell (%.0f max) ? ",
44334606Sbostic 		    (double) N_GEMVALUE, Player.p_gems);
44434606Sbostic 		numitems = floor(infloat());
44534606Sbostic 
44634606Sbostic 		if (numitems > Player.p_gems || numitems < 0)
44734606Sbostic 		    ++cheat;
44834606Sbostic 		else
44934606Sbostic 		    {
45034606Sbostic 		    cheat = 0;
45134606Sbostic 		    Player.p_gems -= numitems;
45234606Sbostic 		    Player.p_gold += numitems * N_GEMVALUE;
45334606Sbostic 		    }
45434606Sbostic 	    }
45534606Sbostic 
45634606Sbostic 	if (cheat == 1)
45734606Sbostic 	    mvaddstr(17, 0, "Come on, merchants aren't stupid.  Stop cheating.\n");
45834606Sbostic 	else if (cheat == 2)
45934606Sbostic 	    {
46034606Sbostic 	    mvaddstr(17, 0, "You had your chance.  This merchant happens to be\n");
46134606Sbostic 	    printw("a %.0f level magic user, and you made %s mad!\n",
46234606Sbostic 		ROLL(Circle * 20.0, 40.0), (drandom() < 0.5) ? "him" : "her");
46334606Sbostic 	    altercoordinates(0.0, 0.0, A_FAR);
46434606Sbostic 	    Player.p_energy /= 2.0;
46534606Sbostic 	    ++Player.p_sin;
46634606Sbostic 	    more(23);
46734606Sbostic 	    return;
46834606Sbostic 	    }
46934606Sbostic 	else if (dishonest)
47034606Sbostic 	    {
47134606Sbostic 	    mvaddstr(17, 0, "The merchant stole your money!");
47234606Sbostic 	    refresh();
47334606Sbostic 	    altercoordinates(Player.p_x - Player.p_x / 10.0,
47434606Sbostic 		Player.p_y - Player.p_y / 10.0, A_SPECIFIC);
47534606Sbostic 	    sleep(2);
47634606Sbostic 	    return;
47734606Sbostic 	    }
47834606Sbostic 	}
47934606Sbostic }
48034606Sbostic /**/
48134606Sbostic /************************************************************************
48234606Sbostic /
48334606Sbostic / FUNCTION NAME: displaystats()
48434606Sbostic /
48534606Sbostic / FUNCTION: print out important player statistics
48634606Sbostic /
48734606Sbostic / AUTHOR: E. A. Estes, 12/4/85
48834606Sbostic /
48934606Sbostic / ARGUMENTS: none
49034606Sbostic /
49134606Sbostic / RETURN VALUE: none
49234606Sbostic /
49334606Sbostic / MODULES CALLED: descrstatus(), descrlocation(), mvprintw()
49434606Sbostic /
49534606Sbostic / GLOBAL INPUTS: Users, Player
49634606Sbostic /
49734606Sbostic / GLOBAL OUTPUTS: none
49834606Sbostic /
49934606Sbostic / DESCRIPTION:
50034606Sbostic /	Important player statistics are printed on the screen.
50134606Sbostic /
50234606Sbostic /************************************************************************/
50334606Sbostic 
displaystats()50434606Sbostic displaystats()
50534606Sbostic {
50634606Sbostic     mvprintw(0, 0, "%s%s\n", Player.p_name, descrlocation(&Player, FALSE));
50734606Sbostic     mvprintw(1, 0, "Level :%7.0f   Energy  :%9.0f(%9.0f)  Mana :%9.0f  Users:%3d\n",
50834606Sbostic 	Player.p_level, Player.p_energy, Player.p_maxenergy + Player.p_shield,
50934606Sbostic 	Player.p_mana, Users);
51034606Sbostic     mvprintw(2, 0, "Quick :%3.0f(%3.0f)  Strength:%9.0f(%9.0f)  Gold :%9.0f  %s\n",
51134606Sbostic 	Player.p_speed, Player.p_quickness + Player.p_quksilver, Player.p_might,
51234606Sbostic 	Player.p_strength + Player.p_sword, Player.p_gold, descrstatus(&Player));
51334606Sbostic }
51434606Sbostic /**/
51534606Sbostic /************************************************************************
51634606Sbostic /
51734606Sbostic / FUNCTION NAME: allstatslist()
51834606Sbostic /
51934606Sbostic / FUNCTION: show player items
52034606Sbostic /
52134606Sbostic / AUTHOR: E. A. Estes, 12/4/85
52234606Sbostic /
52334606Sbostic / ARGUMENTS: none
52434606Sbostic /
52534606Sbostic / RETURN VALUE: none
52634606Sbostic /
52734606Sbostic / MODULES CALLED: mvprintw(), descrtype()
52834606Sbostic /
52934606Sbostic / GLOBAL INPUTS: Player
53034606Sbostic /
53134606Sbostic / GLOBAL OUTPUTS: none
53234606Sbostic /
53334606Sbostic / DESCRIPTION:
53434606Sbostic /	Print out some player statistics of lesser importance.
53534606Sbostic /
53634606Sbostic /************************************************************************/
53734606Sbostic 
allstatslist()53834606Sbostic allstatslist()
53934606Sbostic {
54034606Sbostic static	char	*flags[] =	/* to print value of some bools */
54134606Sbostic 	    {
54234606Sbostic 	    "False",
54334606Sbostic 	    " True"
54434606Sbostic 	    };
54534606Sbostic 
54634606Sbostic     mvprintw( 8,  0, "Type: %s\n",  descrtype(&Player,  FALSE));
54734606Sbostic 
54834606Sbostic     mvprintw(10,  0, "Experience: %9.0f", Player.p_experience);
54934606Sbostic     mvprintw(11,  0, "Brains    : %9.0f", Player.p_brains);
55034606Sbostic     mvprintw(12,  0, "Magic Lvl : %9.0f", Player.p_magiclvl);
55134606Sbostic     mvprintw(13,  0, "Sin       : %9.5f", Player.p_sin);
55234606Sbostic     mvprintw(14,  0, "Poison    : %9.5f", Player.p_poison);
55334606Sbostic     mvprintw(15,  0, "Gems      : %9.0f", Player.p_gems);
55434606Sbostic     mvprintw(16,  0, "Age       : %9d", Player.p_age);
55534606Sbostic     mvprintw(10, 40, "Holy Water: %9d", Player.p_holywater);
55634606Sbostic     mvprintw(11, 40, "Amulets   : %9d", Player.p_amulets);
55734606Sbostic     mvprintw(12, 40, "Charms    : %9d", Player.p_charms);
55834606Sbostic     mvprintw(13, 40, "Crowns    : %9d", Player.p_crowns);
55934606Sbostic     mvprintw(14, 40, "Shield    : %9.0f", Player.p_shield);
56034606Sbostic     mvprintw(15, 40, "Sword     : %9.0f", Player.p_sword);
56134606Sbostic     mvprintw(16, 40, "Quickslver: %9.0f", Player.p_quksilver);
56234606Sbostic 
56334606Sbostic     mvprintw(18,  0, "Blessing: %s   Ring: %s   Virgin: %s   Palantir: %s",
56434606Sbostic 	flags[Player.p_blessing], flags[Player.p_ring.ring_type != R_NONE],
56534606Sbostic 	flags[Player.p_virgin], flags[Player.p_palantir]);
56634606Sbostic }
56734606Sbostic /**/
56834606Sbostic /************************************************************************
56934606Sbostic /
57034606Sbostic / FUNCTION NAME: descrtype()
57134606Sbostic /
57234606Sbostic / FUNCTION: return a string specifying player type
57334606Sbostic /
57434606Sbostic / AUTHOR: E. A. Estes, 12/4/85
57534606Sbostic /
57634606Sbostic / ARGUMENTS:
57734606Sbostic /	struct player playerp - pointer to structure for player
57834606Sbostic /	bool shortflag - set if short form is desired
57934606Sbostic /
58034606Sbostic / RETURN VALUE: pointer to string describing player type
58134606Sbostic /
58234606Sbostic / MODULES CALLED: strcpy()
58334606Sbostic /
58434606Sbostic / GLOBAL INPUTS: Databuf[]
58534606Sbostic /
58634606Sbostic / GLOBAL OUTPUTS: Databuf[]
58734606Sbostic /
58834606Sbostic / DESCRIPTION:
58934606Sbostic /	Return a string describing the player type.
59034606Sbostic /	King, council, valar, supercedes other types.
59134606Sbostic /	The first character of the string is '*' if the player
59234606Sbostic /	has a crown.
59334606Sbostic /	If 'shortflag' is TRUE, return a 3 character string.
59434606Sbostic /
59534606Sbostic /************************************************************************/
59634606Sbostic 
59734606Sbostic char	*
descrtype(playerp,shortflag)59834606Sbostic descrtype(playerp, shortflag)
59934606Sbostic struct player *playerp;
60034606Sbostic bool	shortflag;
60134606Sbostic {
60234606Sbostic register int type;	/* for caluculating result subscript */
60334606Sbostic static char	*results[] =	/* description table */
60434606Sbostic 			{
60534606Sbostic 			" Magic User", " MU",
60634606Sbostic 			" Fighter", " F ",
60734606Sbostic 			" Elf", " E ",
60834606Sbostic 			" Dwarf", " D ",
60934606Sbostic 			" Halfling", " H ",
61034606Sbostic 			" Experimento", " EX",
61134606Sbostic 			" Super", " S ",
61234606Sbostic 			" King", " K ",
61334606Sbostic 			" Council of Wise", " CW",
61434606Sbostic 			" Ex-Valar", " EV",
61534606Sbostic 			" Valar", " V ",
61634606Sbostic 			" ? ", " ? "
61734606Sbostic 			};
61834606Sbostic 
61934606Sbostic     type = playerp->p_type;
62034606Sbostic 
62134606Sbostic     switch (playerp->p_specialtype)
62234606Sbostic 	{
62334606Sbostic 	case SC_NONE:
62434606Sbostic 	    type = playerp->p_type;
62534606Sbostic 	    break;
62634606Sbostic 
62734606Sbostic 	case SC_KING:
62834606Sbostic 	    type = 7;
62934606Sbostic 	    break;
63034606Sbostic 
63134606Sbostic 	case SC_COUNCIL:
63234606Sbostic 	    type = 8;
63334606Sbostic 	    break;
63434606Sbostic 
63534606Sbostic 	case SC_EXVALAR:
63634606Sbostic 	    type = 9;
63734606Sbostic 	    break;
63834606Sbostic 
63934606Sbostic 	case SC_VALAR:
64034606Sbostic 	    type = 10;
64134606Sbostic 	    break;
64234606Sbostic 	}
64334606Sbostic 
64434606Sbostic     type *= 2;		/* calculate offset */
64534606Sbostic 
64634606Sbostic     if (type > 20)
64734606Sbostic 	/* error */
64834606Sbostic 	type = 22;
64934606Sbostic 
65034606Sbostic     if (shortflag)
65134606Sbostic 	/* use short descriptions */
65234606Sbostic 	++type;
65334606Sbostic 
65434606Sbostic     if (playerp->p_crowns > 0)
65534606Sbostic 	{
65634606Sbostic 	strcpy(Databuf, results[type]);
65734606Sbostic 	Databuf[0] = '*';
65834606Sbostic 	return(Databuf);
65934606Sbostic 	}
66034606Sbostic     else
66134606Sbostic 	return(results[type]);
66234606Sbostic }
66334606Sbostic /**/
66434606Sbostic /************************************************************************
66534606Sbostic /
66634606Sbostic / FUNCTION NAME: findname()
66734606Sbostic /
66834606Sbostic / FUNCTION: find location in player file of given name
66934606Sbostic /
67034606Sbostic / AUTHOR: E. A. Estes, 12/4/85
67134606Sbostic /
67234606Sbostic / ARGUMENTS:
67334606Sbostic /	char *name - name of character to look for
67434606Sbostic /	struct player *playerp - pointer of structure to fill
67534606Sbostic /
67634606Sbostic / RETURN VALUE: location of player if found, -1 otherwise
67734606Sbostic /
67834606Sbostic / MODULES CALLED: fread(), fseek(), strcmp()
67934606Sbostic /
68034606Sbostic / GLOBAL INPUTS: Wizard, *Playersfp
68134606Sbostic /
68234606Sbostic / GLOBAL OUTPUTS: none
68334606Sbostic /
68434606Sbostic / DESCRIPTION:
68534606Sbostic /	Search the player file for the player of the given name.
68634606Sbostic /	If player is found, fill structure with player data.
68734606Sbostic /
68834606Sbostic /************************************************************************/
68934606Sbostic 
69034606Sbostic long
findname(name,playerp)69134606Sbostic findname(name, playerp)
69234606Sbostic register char	*name;
69334606Sbostic register struct player *playerp;
69434606Sbostic {
69534606Sbostic long	loc = 0;			/* location in the file */
69634606Sbostic 
69734606Sbostic     fseek(Playersfp, 0L, 0);
69834606Sbostic     while (fread((char *) playerp, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
69934606Sbostic 	{
70034606Sbostic 	if (strcmp(playerp->p_name, name) == 0)
70134606Sbostic 	    {
70234606Sbostic 	    if (playerp->p_status != S_NOTUSED || Wizard)
70334606Sbostic 		/* found it */
70434606Sbostic 		return(loc);
70534606Sbostic 	    }
70634606Sbostic 	loc += SZ_PLAYERSTRUCT;
70734606Sbostic 	}
70834606Sbostic 
70934606Sbostic     return(-1);
71034606Sbostic }
71134606Sbostic /**/
71234606Sbostic /************************************************************************
71334606Sbostic /
71434606Sbostic / FUNCTION NAME: allocrecord()
71534606Sbostic /
71634606Sbostic / FUNCTION: find space in the player file for a new character
71734606Sbostic /
71834606Sbostic / AUTHOR: E. A. Estes, 12/4/85
71934606Sbostic /
72034606Sbostic / ARGUMENTS: none
72134606Sbostic /
72234606Sbostic / RETURN VALUE: location of free space in file
72334606Sbostic /
72434606Sbostic / MODULES CALLED: initplayer(), writerecord(), fread(), fseek()
72534606Sbostic /
72634606Sbostic / GLOBAL INPUTS: Other, *Playersfp
72734606Sbostic /
72834606Sbostic / GLOBAL OUTPUTS: Player
72934606Sbostic /
73034606Sbostic / DESCRIPTION:
73134606Sbostic /	Search the player file for an unused entry.  If none are found,
73234606Sbostic /	make one at the end of the file.
73334606Sbostic /
73434606Sbostic /************************************************************************/
73534606Sbostic 
73634606Sbostic long
allocrecord()73734606Sbostic allocrecord()
73834606Sbostic {
73934606Sbostic long	loc = 0L;		/* location in file */
74034606Sbostic 
74134606Sbostic     fseek(Playersfp, 0L, 0);
74234606Sbostic     while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
74334606Sbostic 	{
74434606Sbostic 	if (Other.p_status == S_NOTUSED)
74534606Sbostic 	    /* found an empty record */
74634606Sbostic 	    return(loc);
74734606Sbostic 	else
74834606Sbostic 	    loc += SZ_PLAYERSTRUCT;
74934606Sbostic 	}
75034606Sbostic 
75134606Sbostic     /* make a new record */
75234606Sbostic     initplayer(&Other);
75334606Sbostic     Player.p_status = S_OFF;
75434606Sbostic     writerecord(&Other, loc);
75534606Sbostic 
75634606Sbostic     return(loc);
75734606Sbostic }
75834606Sbostic /**/
75934606Sbostic /************************************************************************
76034606Sbostic /
76134606Sbostic / FUNCTION NAME: freerecord()
76234606Sbostic /
76334606Sbostic / FUNCTION: free up a record on the player file
76434606Sbostic /
76534606Sbostic / AUTHOR: E. A. Estes, 2/7/86
76634606Sbostic /
76734606Sbostic / ARGUMENTS:
76834606Sbostic /	struct player playerp - pointer to structure to free
76934606Sbostic /	long loc - location in file to free
77034606Sbostic /
77134606Sbostic / RETURN VALUE: none
77234606Sbostic /
77334606Sbostic / MODULES CALLED: writerecord()
77434606Sbostic /
77534606Sbostic / GLOBAL INPUTS: none
77634606Sbostic /
77734606Sbostic / GLOBAL OUTPUTS: none
77834606Sbostic /
77934606Sbostic / DESCRIPTION:
78034606Sbostic /	Mark structure as not used, and update player file.
78134606Sbostic /
78234606Sbostic /************************************************************************/
78334606Sbostic 
78434606Sbostic freerecord(playerp, loc)
78534606Sbostic struct player	*playerp;
78634606Sbostic long	loc;
78734606Sbostic {
78834606Sbostic     playerp->p_name[0] = CH_MARKDELETE;
78934606Sbostic     playerp->p_status = S_NOTUSED;
79034606Sbostic     writerecord(playerp, loc);
79134606Sbostic }
79234606Sbostic /**/
79334606Sbostic /************************************************************************
79434606Sbostic /
79534606Sbostic / FUNCTION NAME: leavegame()
79634606Sbostic /
79734606Sbostic / FUNCTION: leave game
79834606Sbostic /
79934606Sbostic / AUTHOR: E. A. Estes, 12/4/85
80034606Sbostic /
80134606Sbostic / ARGUMENTS: none
80234606Sbostic /
80334606Sbostic / RETURN VALUE: none
80434606Sbostic /
80534606Sbostic / MODULES CALLED: freerecord(), writerecord(), cleanup()
80634606Sbostic /
80734606Sbostic / GLOBAL INPUTS: Player, Fileloc
80834606Sbostic /
80934606Sbostic / GLOBAL OUTPUTS: Player
81034606Sbostic /
81134606Sbostic / DESCRIPTION:
81234606Sbostic /	Mark player as inactive, and cleanup.
81334606Sbostic /	Do not save players below level 1.
81434606Sbostic /
81534606Sbostic /************************************************************************/
81634606Sbostic 
leavegame()81734606Sbostic leavegame()
81834606Sbostic {
81934606Sbostic 
82034606Sbostic     if (Player.p_level < 1.0)
82134606Sbostic 	/* delete character */
82234606Sbostic 	freerecord(&Player, Fileloc);
82334606Sbostic     else
82434606Sbostic 	{
82534606Sbostic 	Player.p_status = S_OFF;
82634606Sbostic 	writerecord(&Player, Fileloc);
82734606Sbostic 	}
82834606Sbostic 
82934606Sbostic     cleanup(TRUE);
83034606Sbostic     /*NOTREACHED*/
83134606Sbostic }
83234606Sbostic /**/
83334606Sbostic /************************************************************************
83434606Sbostic /
83534606Sbostic / FUNCTION NAME: death()
83634606Sbostic /
83734606Sbostic / FUNCTION: death routine
83834606Sbostic /
83934606Sbostic / AUTHOR: E. A. Estes, 12/4/85
84034606Sbostic /
84134606Sbostic / ARGUMENTS:
84234606Sbostic /	char *how - pointer to string describing cause of death
84334606Sbostic /
84434606Sbostic / RETURN VALUE: none
84534606Sbostic /
84634606Sbostic / MODULES CALLED: freerecord(), enterscore(), more(), exit(), fread(),
84734606Sbostic /	fseek(), execl(), fopen(), floor(), wmove(), drandom(), wclear(), strcmp(),
84834606Sbostic /	fwrite(), fflush(), printw(), strcpy(), fclose(), waddstr(), cleanup(),
84934606Sbostic /	fprintf(), wrefresh(), getanswer(), descrtype()
85034606Sbostic /
85140279Sbostic / GLOBAL INPUTS: Curmonster, Wizard, Player, *stdscr, Fileloc, *Monstfp
85234606Sbostic /
85334606Sbostic / GLOBAL OUTPUTS: Player
85434606Sbostic /
85534606Sbostic / DESCRIPTION:
85634606Sbostic /	Kill off current player.
85734606Sbostic /	Handle rings, and multiple lives.
85834606Sbostic /	Print an appropriate message.
85934606Sbostic /	Update scoreboard, lastdead, and let other players know about
86034606Sbostic /	the demise of their comrade.
86134606Sbostic /
86234606Sbostic /************************************************************************/
86334606Sbostic 
death(how)86434606Sbostic death(how)
86534606Sbostic char	*how;
86634606Sbostic {
86734606Sbostic FILE	*fp;		/* for updating various files */
86834606Sbostic int	ch;		/* input */
86934606Sbostic static	char	*deathmesg[] =
87034606Sbostic 	/* add more messages here, if desired */
87134606Sbostic 	{
87234606Sbostic 	"You have been wounded beyond repair.  ",
87334606Sbostic 	"You have been disemboweled.  ",
87434606Sbostic 	"You've been mashed, mauled, and spit upon.  (You're dead.)\n",
87534606Sbostic 	"You died!  ",
87634606Sbostic 	"You're a complete failure -- you've died!!\n",
87734606Sbostic 	"You have been dealt a fatal blow!  "
87834606Sbostic 	};
87934606Sbostic 
88034606Sbostic     clear();
88134606Sbostic 
88234606Sbostic     if (strcmp(how, "Stupidity") != 0)
88334606Sbostic 	{
88434606Sbostic 	if (Player.p_level > 9999.0)
88534606Sbostic 	    /* old age */
88634606Sbostic 	    addstr("Characters must be retired upon reaching level 10000.  Sorry.");
88734606Sbostic 	else if (Player.p_lives > 0)
88834606Sbostic 	    /* extra lives */
88934606Sbostic 	    {
89034606Sbostic 	    addstr("You should be more cautious.  You've been killed.\n");
89134606Sbostic 	    printw("You only have %d more chance(s).\n", --Player.p_lives);
89234606Sbostic 	    more(3);
89334606Sbostic 	    Player.p_energy = Player.p_maxenergy;
89434606Sbostic 	    return;
89534606Sbostic 	    }
89634606Sbostic 	else if (Player.p_specialtype == SC_VALAR)
89734606Sbostic 	    {
89834606Sbostic 	    addstr("You had your chances, but Valar aren't totally\n");
89934606Sbostic 	    addstr("immortal.  You are now left to wither and die . . .\n");
90034606Sbostic 	    more(3);
90134606Sbostic 	    Player.p_brains = Player.p_level / 25.0;
90234606Sbostic 	    Player.p_energy = Player.p_maxenergy /= 5.0;
90334606Sbostic 	    Player.p_quksilver = Player.p_sword = 0.0;
90434606Sbostic 	    Player.p_specialtype = SC_COUNCIL;
90534606Sbostic 	    return;
90634606Sbostic 	    }
90734606Sbostic 	else if (Player.p_ring.ring_inuse &&
90834606Sbostic 	    (Player.p_ring.ring_type == R_DLREG || Player.p_ring.ring_type == R_NAZREG))
90934606Sbostic 	    /* good ring in use - saved from death */
91034606Sbostic 	    {
91134606Sbostic 	    mvaddstr(4, 0, "Your ring saved you from death!\n");
91234606Sbostic 	    refresh();
91334606Sbostic 	    Player.p_ring.ring_type = R_NONE;
91434606Sbostic 	    Player.p_energy = Player.p_maxenergy / 12.0 + 1.0;
91534606Sbostic 	    if (Player.p_crowns > 0)
91634606Sbostic 		--Player.p_crowns;
91734606Sbostic 	    return;
91834606Sbostic 	    }
91934606Sbostic 	else if (Player.p_ring.ring_type == R_BAD
92034606Sbostic 	    || Player.p_ring.ring_type == R_SPOILED)
92134606Sbostic 	    /* bad ring in possession; name idiot after player */
92234606Sbostic 	    {
92334606Sbostic 	    mvaddstr(4, 0,
92434606Sbostic 		"Your ring has taken control of you and turned you into a monster!\n");
92534606Sbostic 	    fseek(Monstfp, 13L * SZ_MONSTERSTRUCT, 0);
92634606Sbostic 	    fread((char *) &Curmonster, SZ_MONSTERSTRUCT, 1, Monstfp);
92734606Sbostic 	    strcpy(Curmonster.m_name, Player.p_name);
92834606Sbostic 	    fseek(Monstfp, 13L * SZ_MONSTERSTRUCT, 0);
92934606Sbostic 	    fwrite((char *) &Curmonster, SZ_MONSTERSTRUCT, 1, Monstfp);
93034606Sbostic 	    fflush(Monstfp);
93134606Sbostic 	    }
93234606Sbostic 	}
93334606Sbostic 
93434606Sbostic     enterscore();		/* update score board */
93534606Sbostic 
93634606Sbostic     /* put info in last dead file */
93740279Sbostic     fp = fopen(_PATH_LASTDEAD, "w");
93834606Sbostic     fprintf(fp,"%s (%s, run by %s, level %.0f, killed by %s)",
93934606Sbostic 	Player.p_name, descrtype(&Player, TRUE),
94034606Sbostic 	Player.p_login, Player.p_level, how);
94134606Sbostic     fclose(fp);
94234606Sbostic 
94334606Sbostic     /* let other players know */
94440279Sbostic     fp = fopen(_PATH_MESS, "w");
94534606Sbostic     fprintf(fp, "%s was killed by %s.", Player.p_name, how);
94634606Sbostic     fclose(fp);
94734606Sbostic 
94834606Sbostic     freerecord(&Player, Fileloc);
94934606Sbostic 
95034606Sbostic     clear();
95134606Sbostic     move(10, 0);
95234606Sbostic     addstr(deathmesg[(int) ROLL(0.0, (double) sizeof(deathmesg) / sizeof(char *))]);
95334606Sbostic     addstr("Care to give it another try ? ");
95434606Sbostic     ch = getanswer("NY", FALSE);
95534606Sbostic 
95634606Sbostic     if (ch == 'Y')
95734606Sbostic 	{
95834606Sbostic 	cleanup(FALSE);
95940279Sbostic 	execl(_PATH_GAMEPROG, "phantasia", "-s",
96040279Sbostic 	    (Wizard ? "-S": (char *) NULL), 0);
96134606Sbostic 	exit(0);
96234606Sbostic 	/*NOTREACHED*/
96334606Sbostic 	}
96434606Sbostic 
96534606Sbostic     cleanup(TRUE);
96634606Sbostic     /*NOTREACHED*/
96734606Sbostic }
96834606Sbostic /**/
96934606Sbostic /************************************************************************
97034606Sbostic /
97134606Sbostic / FUNCTION NAME: writerecord()
97234606Sbostic /
97334606Sbostic / FUNCTION: update structure in player file
97434606Sbostic /
97534606Sbostic / AUTHOR: E. A. Estes, 12/4/85
97634606Sbostic /
97734606Sbostic / ARGUMENTS:
97834606Sbostic /	struct player *playerp - pointer to structure to write out
97934606Sbostic /	long place - location in file to updata
98034606Sbostic /
98134606Sbostic / RETURN VALUE: none
98234606Sbostic /
98334606Sbostic / MODULES CALLED: fseek(), fwrite(), fflush()
98434606Sbostic /
98534606Sbostic / GLOBAL INPUTS: *Playersfp
98634606Sbostic /
98734606Sbostic / GLOBAL OUTPUTS: none
98834606Sbostic /
98934606Sbostic / DESCRIPTION:
99034606Sbostic /	Update location in player file with given structure.
99134606Sbostic /
99234606Sbostic /************************************************************************/
99334606Sbostic 
writerecord(playerp,place)99434606Sbostic writerecord(playerp, place)
99534606Sbostic register struct player	*playerp;
99634606Sbostic long	place;
99734606Sbostic {
99834606Sbostic     fseek(Playersfp, place, 0);
99934606Sbostic     fwrite((char *) playerp, SZ_PLAYERSTRUCT, 1, Playersfp);
100034606Sbostic     fflush(Playersfp);
100134606Sbostic }
100234606Sbostic /**/
100334606Sbostic /************************************************************************
100434606Sbostic /
100534606Sbostic / FUNCTION NAME: explevel()
100634606Sbostic /
100734606Sbostic / FUNCTION: calculate level based upon experience
100834606Sbostic /
100934606Sbostic / AUTHOR: E. A. Estes, 12/4/85
101034606Sbostic /
101134606Sbostic / ARGUMENTS:
101234606Sbostic /	double experience - experience to calculate experience level from
101334606Sbostic /
101434606Sbostic / RETURN VALUE: experience level
101534606Sbostic /
101634606Sbostic / MODULES CALLED: pow(), floor()
101734606Sbostic /
101834606Sbostic / GLOBAL INPUTS: none
101934606Sbostic /
102034606Sbostic / GLOBAL OUTPUTS: none
102134606Sbostic /
102234606Sbostic / DESCRIPTION:
102334606Sbostic /	Experience level is a geometric progression.  This has been finely
102434606Sbostic /	tuned over the years, and probably should not be changed.
102534606Sbostic /
102634606Sbostic /************************************************************************/
102734606Sbostic 
102834606Sbostic double
explevel(experience)102934606Sbostic explevel(experience)
103034606Sbostic double	experience;
103134606Sbostic {
103234606Sbostic     if (experience < 1.1e7)
103334606Sbostic 	return(floor(pow((experience / 1000.0), 0.4875)));
103434606Sbostic     else
103534606Sbostic 	return(floor(pow((experience / 1250.0), 0.4865)));
103634606Sbostic }
103734606Sbostic /**/
103834606Sbostic /************************************************************************
103934606Sbostic /
104034606Sbostic / FUNCTION NAME: truncstring()
104134606Sbostic /
104234606Sbostic / FUNCTION: truncate trailing blanks off a string
104334606Sbostic /
104434606Sbostic / AUTHOR: E. A. Estes, 12/4/85
104534606Sbostic /
104634606Sbostic / ARGUMENTS:
104734606Sbostic /	char *string - pointer to null terminated string
104834606Sbostic /
104934606Sbostic / RETURN VALUE: none
105034606Sbostic /
105134606Sbostic / MODULES CALLED: strlen()
105234606Sbostic /
105334606Sbostic / GLOBAL INPUTS: none
105434606Sbostic /
105534606Sbostic / GLOBAL OUTPUTS: none
105634606Sbostic /
105734606Sbostic / DESCRIPTION:
105834606Sbostic /	Put nul characters in place of spaces at the end of the string.
105934606Sbostic /
106034606Sbostic /************************************************************************/
106134606Sbostic 
truncstring(string)106234606Sbostic truncstring(string)
106334606Sbostic register char	*string;
106434606Sbostic {
106534606Sbostic register int	length;		/* length of string */
106634606Sbostic 
106734606Sbostic     length = strlen(string);
106834606Sbostic     while (string[--length] == ' ')
106934606Sbostic 	string[length] = '\0';
107034606Sbostic }
107134606Sbostic /**/
107234606Sbostic /************************************************************************
107334606Sbostic /
107434606Sbostic / FUNCTION NAME: altercoordinates()
107534606Sbostic /
107634606Sbostic / FUNCTION: Alter x, y coordinates and set/check location flags
107734606Sbostic /
107834606Sbostic / AUTHOR: E. A. Estes, 12/16/85
107934606Sbostic /
108034606Sbostic / ARGUMENTS:
108134606Sbostic /	double xnew, ynew - new x, y coordinates
108234606Sbostic /	int operation - operation to perform with coordinates
108334606Sbostic /
108434606Sbostic / RETURN VALUE: none
108534606Sbostic /
108634606Sbostic / MODULES CALLED: fabs(), floor(), drandom(), distance()
108734606Sbostic /
108834606Sbostic / GLOBAL INPUTS: Circle, Beyond, Player
108934606Sbostic /
109034606Sbostic / GLOBAL OUTPUTS: Marsh, Circle, Beyond, Throne, Player, Changed
109134606Sbostic /
109234606Sbostic / DESCRIPTION:
109334606Sbostic /	This module is called whenever the player's coordinates are altered.
109434606Sbostic /	If the player is beyond the point of no return, he/she is forced
109534606Sbostic /	to stay there.
109634606Sbostic /
109734606Sbostic /************************************************************************/
109834606Sbostic 
altercoordinates(xnew,ynew,operation)109934606Sbostic altercoordinates(xnew, ynew, operation)
110034606Sbostic double	xnew;
110134606Sbostic double	ynew;
110234606Sbostic int	operation;
110334606Sbostic {
110434606Sbostic     switch (operation)
110534606Sbostic 	{
110634606Sbostic 	case A_FORCED:	/* move with no checks */
110734606Sbostic 	    break;
110834606Sbostic 
110934606Sbostic 	case A_NEAR:	/* pick random coordinates near */
111034606Sbostic 	    xnew = Player.p_x + ROLL(1.0, 5.0);
111134606Sbostic 	    ynew = Player.p_y - ROLL(1.0, 5.0);
111234606Sbostic 	    /* fall through for check */
111334606Sbostic 
111434606Sbostic 	case A_SPECIFIC:	/* just move player */
111534606Sbostic 	    if (Beyond && fabs(xnew) < D_BEYOND && fabs(ynew) < D_BEYOND)
111634606Sbostic 		/*
111734606Sbostic 		 * cannot move back from point of no return
111834606Sbostic 		 * pick the largest coordinate to remain unchanged
111934606Sbostic 		 */
112034606Sbostic 		{
112134606Sbostic 		if (fabs(xnew) > fabs(ynew))
112234606Sbostic 		    xnew = SGN(Player.p_x) * MAX(fabs(Player.p_x), D_BEYOND);
112334606Sbostic 		else
112434606Sbostic 		    ynew = SGN(Player.p_y) * MAX(fabs(Player.p_y), D_BEYOND);
112534606Sbostic 		}
112634606Sbostic 	    break;
112734606Sbostic 
112834606Sbostic 	case A_FAR:	/* pick random coordinates far */
112934606Sbostic 	    xnew = Player.p_x + SGN(Player.p_x) * ROLL(50 * Circle, 250 * Circle);
113034606Sbostic 	    ynew = Player.p_y + SGN(Player.p_y) * ROLL(50 * Circle, 250 * Circle);
113134606Sbostic 	    break;
113234606Sbostic 	}
113334606Sbostic 
113434606Sbostic     /* now set location flags and adjust coordinates */
113534606Sbostic     Circle = CIRCLE(Player.p_x = floor(xnew), Player.p_y = floor(ynew));
113634606Sbostic 
113734606Sbostic     /* set up flags based upon location */
113834606Sbostic     Throne = Marsh = Beyond = FALSE;
113934606Sbostic 
114034606Sbostic     if (Player.p_x == 0.0 && Player.p_y == 0.0)
114134606Sbostic 	Throne = TRUE;
114234606Sbostic     else if (Circle < 35 && Circle >= 20)
114334606Sbostic 	Marsh = TRUE;
114434606Sbostic     else if (MAX(fabs(Player.p_x), fabs(Player.p_y)) >= D_BEYOND)
114534606Sbostic 	Beyond = TRUE;
114634606Sbostic 
114734606Sbostic     Changed = TRUE;
114834606Sbostic }
114934606Sbostic /**/
115034606Sbostic /************************************************************************
115134606Sbostic /
115234606Sbostic / FUNCTION NAME: readrecord()
115334606Sbostic /
115434606Sbostic / FUNCTION: read a player structure from file
115534606Sbostic /
115634606Sbostic / AUTHOR: E. A. Estes, 12/4/85
115734606Sbostic /
115834606Sbostic / ARGUMENTS:
115934606Sbostic /	struct player *playerp - pointer to structure to fill
116034606Sbostic /	int loc - location of record to read
116134606Sbostic /
116234606Sbostic / RETURN VALUE: none
116334606Sbostic /
116434606Sbostic / MODULES CALLED: fread(), fseek()
116534606Sbostic /
116634606Sbostic / GLOBAL INPUTS: *Playersfp
116734606Sbostic /
116834606Sbostic / GLOBAL OUTPUTS: none
116934606Sbostic /
117034606Sbostic / DESCRIPTION:
117134606Sbostic /	Read structure information from player file.
117234606Sbostic /
117334606Sbostic /************************************************************************/
117434606Sbostic 
readrecord(playerp,loc)117534606Sbostic readrecord(playerp, loc)
117634606Sbostic register struct player	*playerp;
117734606Sbostic long	loc;
117834606Sbostic {
117934606Sbostic     fseek(Playersfp, loc, 0);
118034606Sbostic     fread((char *) playerp, SZ_PLAYERSTRUCT, 1, Playersfp);
118134606Sbostic }
118234606Sbostic /**/
118334606Sbostic /************************************************************************
118434606Sbostic /
118534606Sbostic / FUNCTION NAME: adjuststats()
118634606Sbostic /
118734606Sbostic / FUNCTION: adjust player statistics
118834606Sbostic /
118934606Sbostic / AUTHOR: E. A. Estes, 12/4/85
119034606Sbostic /
119134606Sbostic / ARGUMENTS: none
119234606Sbostic /
119334606Sbostic / RETURN VALUE: none
119434606Sbostic /
119534606Sbostic / MODULES CALLED: death(), floor(), drandom(), explevel(), movelevel()
119634606Sbostic /
119734606Sbostic / GLOBAL INPUTS: Player, *Statptr
119834606Sbostic /
119934606Sbostic / GLOBAL OUTPUTS: Circle, Player, Timeout
120034606Sbostic /
120134606Sbostic / DESCRIPTION:
120234606Sbostic /	Handle adjustment and maximums on various player characteristics.
120334606Sbostic /
120434606Sbostic /************************************************************************/
120534606Sbostic 
adjuststats()120634606Sbostic adjuststats()
120734606Sbostic {
120834606Sbostic double	dtemp;				/* for temporary calculations */
120934606Sbostic 
121034606Sbostic     if (explevel(Player.p_experience) > Player.p_level)
121134606Sbostic 	/* move one or more levels */
121234606Sbostic 	{
121334606Sbostic 	movelevel();
121434606Sbostic 	if (Player.p_level > 5.0)
121534606Sbostic 	    Timeout = TRUE;
121634606Sbostic 	}
121734606Sbostic 
121834606Sbostic     if (Player.p_specialtype == SC_VALAR)
121934606Sbostic 	/* valar */
122034606Sbostic 	Circle = Player.p_level / 5.0;
122134606Sbostic 
122234606Sbostic     /* calculate effective quickness */
122334606Sbostic     dtemp = ((Player.p_gold + Player.p_gems / 2.0) - 1000.0) / Statptr->c_goldtote
122434606Sbostic 	- Player.p_level;;
122534606Sbostic     dtemp = MAX(0.0, dtemp);		/* gold slows player down */
122634606Sbostic     Player.p_speed = Player.p_quickness + Player.p_quksilver - dtemp;
122734606Sbostic 
122834606Sbostic     /* calculate effective strength */
122934606Sbostic     if (Player.p_poison > 0.0)
123034606Sbostic 	/* poison makes player weaker */
123134606Sbostic 	{
123234606Sbostic 	dtemp = 1.0 - Player.p_poison * Statptr->c_weakness / 800.0;
123334606Sbostic 	dtemp = MAX(0.1, dtemp);
123434606Sbostic 	}
123534606Sbostic     else
123634606Sbostic 	dtemp = 1.0;
123734606Sbostic     Player.p_might = dtemp *  Player.p_strength + Player.p_sword;
123834606Sbostic 
123934606Sbostic     /* insure that important things are within limits */
124034606Sbostic     Player.p_quksilver = MIN(99.0, Player.p_quksilver);
124134606Sbostic     Player.p_mana = MIN(Player.p_mana,
124234606Sbostic 	Player.p_level * Statptr->c_maxmana + 1000.0);
124334606Sbostic     Player.p_brains = MIN(Player.p_brains,
124434606Sbostic 	Player.p_level * Statptr->c_maxbrains + 200.0);
124534606Sbostic     Player.p_charms = MIN(Player.p_charms, Player.p_level + 10.0);
124634606Sbostic 
124734606Sbostic     /*
124834606Sbostic      * some implementations have problems with floating point compare
124934606Sbostic      * we work around it with this stuff
125034606Sbostic      */
125134606Sbostic     Player.p_gold = floor(Player.p_gold) + 0.1;
125234606Sbostic     Player.p_gems = floor(Player.p_gems) + 0.1;
125334606Sbostic     Player.p_mana = floor(Player.p_mana) + 0.1;
125434606Sbostic 
125534606Sbostic     if (Player.p_ring.ring_type != R_NONE)
125634606Sbostic 	/* do ring things */
125734606Sbostic 	{
125834606Sbostic 	/* rest to max */
125934606Sbostic 	Player.p_energy = Player.p_maxenergy + Player.p_shield;
126034606Sbostic 
126134606Sbostic         if (Player.p_ring.ring_duration <= 0)
126234606Sbostic 	    /* clean up expired rings */
126334606Sbostic 	    switch (Player.p_ring.ring_type)
126434606Sbostic 		{
126534606Sbostic 		case R_BAD:	/* ring drives player crazy */
126634606Sbostic 		    Player.p_ring.ring_type = R_SPOILED;
126734606Sbostic 		    Player.p_ring.ring_duration = (short) ROLL(10.0, 25.0);
126834606Sbostic 		    break;
126934606Sbostic 
127034606Sbostic 		case R_NAZREG:	/* ring disappears */
127134606Sbostic 		    Player.p_ring.ring_type = R_NONE;
127234606Sbostic 		    break;
127334606Sbostic 
127434606Sbostic 		case R_SPOILED:	/* ring kills player */
127534606Sbostic 		    death("A cursed ring");
127634606Sbostic 		    break;
127734606Sbostic 
127834606Sbostic 		case R_DLREG:	/* this ring doesn't expire */
127934606Sbostic 		    Player.p_ring.ring_duration = 0;
128034606Sbostic 		    break;
128134606Sbostic 		}
128234606Sbostic 	}
128334606Sbostic 
128434606Sbostic     if (Player.p_age / N_AGE > Player.p_degenerated)
128534606Sbostic 	/* age player slightly */
128634606Sbostic 	{
128734606Sbostic 	++Player.p_degenerated;
128834606Sbostic 	if (Player.p_quickness > 23.0)
128934606Sbostic 	    Player.p_quickness *= 0.99;
129034606Sbostic 	Player.p_strength *= 0.97;
129134606Sbostic 	Player.p_brains *= 0.95;
129234606Sbostic 	Player.p_magiclvl *= 0.97;
129334606Sbostic 	Player.p_maxenergy *= 0.95;
129434606Sbostic 	Player.p_quksilver *= 0.95;
129534606Sbostic 	Player.p_sword *= 0.93;
129634606Sbostic 	Player.p_shield *= 0.93;
129734606Sbostic 	}
129834606Sbostic }
129934606Sbostic /**/
130034606Sbostic /************************************************************************
130134606Sbostic /
130234606Sbostic / FUNCTION NAME: initplayer()
130334606Sbostic /
130434606Sbostic / FUNCTION: initialize a character
130534606Sbostic /
130634606Sbostic / AUTHOR: E. A. Estes, 12/4/85
130734606Sbostic /
130834606Sbostic / ARGUMENTS:
130934606Sbostic /	struct player *playerp - pointer to structure to init
131034606Sbostic /
131134606Sbostic / RETURN VALUE: none
131234606Sbostic /
131334606Sbostic / MODULES CALLED: floor(), drandom()
131434606Sbostic /
131534606Sbostic / GLOBAL INPUTS: none
131634606Sbostic /
131734606Sbostic / GLOBAL OUTPUTS: none
131834606Sbostic /
131934606Sbostic / DESCRIPTION:
132034606Sbostic /	Put a bunch of default values in the given structure.
132134606Sbostic /
132234606Sbostic /************************************************************************/
132334606Sbostic 
initplayer(playerp)132434606Sbostic initplayer(playerp)
132534606Sbostic register struct  player   *playerp;
132634606Sbostic {
132734606Sbostic     playerp->p_experience =
132834606Sbostic     playerp->p_level =
132934606Sbostic     playerp->p_strength =
133034606Sbostic     playerp->p_sword =
133134606Sbostic     playerp->p_might =
133234606Sbostic     playerp->p_energy =
133334606Sbostic     playerp->p_maxenergy =
133434606Sbostic     playerp->p_shield =
133534606Sbostic     playerp->p_quickness =
133634606Sbostic     playerp->p_quksilver =
133734606Sbostic     playerp->p_speed =
133834606Sbostic     playerp->p_magiclvl =
133934606Sbostic     playerp->p_mana =
134034606Sbostic     playerp->p_brains =
134134606Sbostic     playerp->p_poison =
134234606Sbostic     playerp->p_gems =
134334606Sbostic     playerp->p_sin =
134434606Sbostic     playerp->p_1scratch =
134534606Sbostic     playerp->p_2scratch = 0.0;
134634606Sbostic 
134734606Sbostic     playerp->p_gold = ROLL(50.0, 75.0) + 0.1;	/* give some gold */
134834606Sbostic 
134934606Sbostic     playerp->p_x = ROLL(-125.0, 251.0);
135034606Sbostic     playerp->p_y = ROLL(-125.0, 251.0);		/* give random x, y */
135134606Sbostic 
135234606Sbostic     /* clear ring */
135334606Sbostic     playerp->p_ring.ring_type = R_NONE;
135434606Sbostic     playerp->p_ring.ring_duration = 0;
135534606Sbostic     playerp->p_ring.ring_inuse = FALSE;
135634606Sbostic 
135734606Sbostic     playerp->p_age = 0L;
135834606Sbostic 
135934606Sbostic     playerp->p_degenerated = 1;			/* don't degenerate initially */
136034606Sbostic 
136134606Sbostic     playerp->p_type = C_FIGHTER;		/* default */
136234606Sbostic     playerp->p_specialtype = SC_NONE;
136334606Sbostic     playerp->p_lives =
136434606Sbostic     playerp->p_crowns =
136534606Sbostic     playerp->p_charms =
136634606Sbostic     playerp->p_amulets =
136734606Sbostic     playerp->p_holywater =
136834606Sbostic     playerp->p_lastused = 0;
136934606Sbostic     playerp->p_status = S_NOTUSED;
137034606Sbostic     playerp->p_tampered = T_OFF;
137134606Sbostic     playerp->p_istat = I_OFF;
137234606Sbostic 
137334606Sbostic     playerp->p_palantir =
137434606Sbostic     playerp->p_blessing =
137534606Sbostic     playerp->p_virgin =
137634606Sbostic     playerp->p_blindness = FALSE;
137734606Sbostic 
137834606Sbostic     playerp->p_name[0] =
137934606Sbostic     playerp->p_password[0] =
138034606Sbostic     playerp->p_login[0] = '\0';
138134606Sbostic }
138234606Sbostic /**/
138334606Sbostic /************************************************************************
138434606Sbostic /
138534606Sbostic / FUNCTION NAME: readmessage()
138634606Sbostic /
138734606Sbostic / FUNCTION: read message from other players
138834606Sbostic /
138934606Sbostic / AUTHOR: E. A. Estes, 12/4/85
139034606Sbostic /
139134606Sbostic / ARGUMENTS: none
139234606Sbostic /
139334606Sbostic / RETURN VALUE: none
139434606Sbostic /
139534606Sbostic / MODULES CALLED: fseek(), fgets(), wmove(), waddstr(), wclrtoeol()
139634606Sbostic /
139734606Sbostic / GLOBAL INPUTS: *stdscr, Databuf[], *Messagefp
139834606Sbostic /
139934606Sbostic / GLOBAL OUTPUTS: none
140034606Sbostic /
140134606Sbostic / DESCRIPTION:
140234606Sbostic /	If there is a message from other players, print it.
140334606Sbostic /
140434606Sbostic /************************************************************************/
140534606Sbostic 
readmessage()140634606Sbostic readmessage()
140734606Sbostic {
140834606Sbostic     move(3, 0);
140934606Sbostic     clrtoeol();
141034606Sbostic     fseek(Messagefp, 0L, 0);
141134606Sbostic     if (fgets(Databuf, SZ_DATABUF, Messagefp) != NULL)
141234606Sbostic 	addstr(Databuf);
141334606Sbostic }
141434606Sbostic /**/
141534606Sbostic /************************************************************************
141634606Sbostic /
141734606Sbostic / FUNCTION NAME: error()
141834606Sbostic /
141934606Sbostic / FUNCTION: process evironment error
142034606Sbostic /
142134606Sbostic / AUTHOR: E. A. Estes, 12/4/85
142234606Sbostic /
142334606Sbostic / ARGUMENTS:
142434606Sbostic /	char *whichfile - pointer to name of file which caused error
142534606Sbostic /
142634606Sbostic / RETURN VALUE: none
142734606Sbostic /
142834606Sbostic / MODULES CALLED: wclear(), cleanup()
142934606Sbostic /
143034606Sbostic / GLOBAL INPUTS: errno, *stdscr, printw(), printf(), Windows
143134606Sbostic /
143234606Sbostic / GLOBAL OUTPUTS: none
143334606Sbostic /
143434606Sbostic / DESCRIPTION:
143534606Sbostic /	Print message about offending file, and exit.
143634606Sbostic /
143734606Sbostic /************************************************************************/
143834606Sbostic 
error(whichfile)143934606Sbostic error(whichfile)
144056101Selan 	char	*whichfile;
144134606Sbostic {
1442*56571Sbostic 	int	(*funcp) __P((const char *, ...));
144334606Sbostic 
144434606Sbostic     if (Windows)
144534606Sbostic 	{
144634606Sbostic 	funcp = printw;
144734606Sbostic 	clear();
144834606Sbostic 	}
144934606Sbostic     else
145034606Sbostic 	funcp = printf;
145134606Sbostic 
145234606Sbostic     (*funcp)("An unrecoverable error has occurred reading %s.  (errno = %d)\n", whichfile, errno);
145334606Sbostic     (*funcp)("Please run 'setup' to determine the problem.\n");
145434606Sbostic     cleanup(TRUE);
145534606Sbostic     /*NOTREACHED*/
145634606Sbostic }
145734606Sbostic /**/
145834606Sbostic /************************************************************************
145934606Sbostic /
146034606Sbostic / FUNCTION NAME: distance()
146134606Sbostic /
146234606Sbostic / FUNCTION: calculate distance between two points
146334606Sbostic /
146434606Sbostic / AUTHOR: E. A. Estes, 12/4/85
146534606Sbostic /
146634606Sbostic / ARGUMENTS:
146734606Sbostic /	double x1, y1 - x, y coordinates of first point
146834606Sbostic /	double x2, y2 - x, y coordinates of second point
146934606Sbostic /
147034606Sbostic / RETURN VALUE: distance between the two points
147134606Sbostic /
147234606Sbostic / MODULES CALLED: sqrt()
147334606Sbostic /
147434606Sbostic / GLOBAL INPUTS: none
147534606Sbostic /
147634606Sbostic / GLOBAL OUTPUTS: none
147734606Sbostic /
147834606Sbostic / DESCRIPTION:
147934606Sbostic /	This function is provided because someone's hypot() library function
148034606Sbostic /	fails if x1 == x2 && y1 == y2.
148134606Sbostic /
148234606Sbostic /************************************************************************/
148334606Sbostic 
148434606Sbostic double
distance(x1,x2,y1,y2)148534606Sbostic distance(x1, x2, y1, y2)
148634606Sbostic double	x1, x2, y1, y2;
148734606Sbostic {
148834606Sbostic double	deltax, deltay;
148934606Sbostic 
149034606Sbostic     deltax = x1 - x2;
149134606Sbostic     deltay = y1 - y2;
149234606Sbostic     return(sqrt(deltax * deltax + deltay * deltay));
149334606Sbostic }
149434606Sbostic 
149534606Sbostic /**/
149634606Sbostic /************************************************************************
149734606Sbostic /
149834606Sbostic / FUNCTION NAME: ill_sig()
149934606Sbostic /
150034606Sbostic / FUNCTION: exit upon trapping an illegal signal
150134606Sbostic /
150234606Sbostic / AUTHOR: E. A. Estes, 12/4/85
150334606Sbostic /
150434606Sbostic / ARGUMENTS:
150534606Sbostic /	int whichsig - signal which occured to cause jump to here
150634606Sbostic /
150734606Sbostic / RETURN VALUE: none
150834606Sbostic /
150934606Sbostic / MODULES CALLED: wclear(), printw(), cleanup()
151034606Sbostic /
151134606Sbostic / GLOBAL INPUTS: *stdscr
151234606Sbostic /
151334606Sbostic / GLOBAL OUTPUTS: none
151434606Sbostic /
151534606Sbostic / DESCRIPTION:
151634606Sbostic /	When an illegal signal is caught, print a message, and cleanup.
151734606Sbostic /
151834606Sbostic /************************************************************************/
151934606Sbostic 
ill_sig(whichsig)152034606Sbostic ill_sig(whichsig)
152134606Sbostic int whichsig;
152234606Sbostic {
152334606Sbostic     clear();
152434606Sbostic     if (!(whichsig == SIGINT || whichsig == SIGQUIT))
152534606Sbostic 	printw("Error: caught signal # %d.\n", whichsig);
152634606Sbostic     cleanup(TRUE);
152734606Sbostic     /*NOTREACHED*/
152834606Sbostic }
152934606Sbostic /**/
153034606Sbostic /************************************************************************
153134606Sbostic /
153234606Sbostic / FUNCTION NAME: descrstatus()
153334606Sbostic /
153434606Sbostic / FUNCTION: return a string describing the player status
153534606Sbostic /
153634606Sbostic / AUTHOR: E. A. Estes, 3/3/86
153734606Sbostic /
153834606Sbostic / ARGUMENTS:
153934606Sbostic /	struct player playerp - pointer to player structure to describe
154034606Sbostic /
154134606Sbostic / RETURN VALUE: string describing player's status
154234606Sbostic /
154334606Sbostic / MODULES CALLED: none
154434606Sbostic /
154534606Sbostic / GLOBAL INPUTS: none
154634606Sbostic /
154734606Sbostic / GLOBAL OUTPUTS: none
154834606Sbostic /
154934606Sbostic / DESCRIPTION:
155034606Sbostic /	Return verbal description of player status.
155134606Sbostic /	If player status is S_PLAYING, check for low energy and blindness.
155234606Sbostic /
155334606Sbostic /************************************************************************/
155434606Sbostic 
155534606Sbostic char	*
descrstatus(playerp)155634606Sbostic descrstatus(playerp)
155734606Sbostic register struct player	*playerp;
155834606Sbostic {
155934606Sbostic     switch (playerp->p_status)
156034606Sbostic 	{
156134606Sbostic 	case S_PLAYING:
156234606Sbostic 	    if (playerp->p_energy < 0.2 * (playerp->p_maxenergy + playerp->p_shield))
156334606Sbostic 		return("Low Energy");
156434606Sbostic 	    else if (playerp->p_blindness)
156534606Sbostic 		return("Blind");
156634606Sbostic 	    else
156734606Sbostic 		return("In game");
156834606Sbostic 
156934606Sbostic 	case S_CLOAKED:
157034606Sbostic 	    return("Cloaked");
157134606Sbostic 
157234606Sbostic 	case S_INBATTLE:
157334606Sbostic 	    return("In Battle");
157434606Sbostic 
157534606Sbostic 	case S_MONSTER:
157634606Sbostic 	    return("Encounter");
157734606Sbostic 
157834606Sbostic 	case S_TRADING:
157934606Sbostic 	    return("Trading");
158034606Sbostic 
158134606Sbostic 	case S_OFF:
158234606Sbostic 	    return("Off");
158334606Sbostic 
158434606Sbostic 	case S_HUNGUP:
158534606Sbostic 	    return("Hung up");
158634606Sbostic 
158734606Sbostic 	default:
158834606Sbostic 	    return("");
158934606Sbostic 	}
159034606Sbostic }
159134606Sbostic /**/
159234606Sbostic /************************************************************************
159334606Sbostic /
159434606Sbostic / FUNCTION NAME: drandom()
159534606Sbostic /
159634606Sbostic / FUNCTION: return a random floating point number from 0.0 < 1.0
159734606Sbostic /
159834606Sbostic / AUTHOR: E. A. Estes, 2/7/86
159934606Sbostic /
160034606Sbostic / ARGUMENTS: none
160134606Sbostic /
160234606Sbostic / RETURN VALUE: none
160334606Sbostic /
160434606Sbostic / MODULES CALLED: random()
160534606Sbostic /
160634606Sbostic / GLOBAL INPUTS: none
160734606Sbostic /
160834606Sbostic / GLOBAL OUTPUTS: none
160934606Sbostic /
161034606Sbostic / DESCRIPTION:
161134606Sbostic /	Convert random integer from library routine into a floating
161234606Sbostic /	point number, and divide by the largest possible random number.
161334606Sbostic /	We mask large integers with 32767 to handle sites that return
161434606Sbostic /	31 bit random integers.
161534606Sbostic /
161634606Sbostic /************************************************************************/
161734606Sbostic 
161834606Sbostic double
drandom()161934606Sbostic drandom()
162034606Sbostic {
162134606Sbostic     if (sizeof(int) != 2)
162234606Sbostic 	/* use only low bits */
162334606Sbostic 	return((double) (random() & 0x7fff) / 32768.0);
162434606Sbostic     else
162534606Sbostic 	return((double) random() / 32768.0);
162634606Sbostic }
162734606Sbostic /**/
162834606Sbostic /************************************************************************
162934606Sbostic /
163034606Sbostic / FUNCTION NAME: collecttaxes()
163134606Sbostic /
163234606Sbostic / FUNCTION: collect taxes from current player
163334606Sbostic /
163434606Sbostic / AUTHOR: E. A. Estes, 2/7/86
163534606Sbostic /
163634606Sbostic / ARGUMENTS:
163734606Sbostic /	double gold - amount of gold to tax
163834606Sbostic /	double gems - amount of gems to tax
163934606Sbostic /
164034606Sbostic / RETURN VALUE: none
164134606Sbostic /
164234606Sbostic / MODULES CALLED: fread(), fseek(), fopen(), floor(), fwrite(), fclose()
164334606Sbostic /
164440279Sbostic / GLOBAL INPUTS: Player
164534606Sbostic /
164634606Sbostic / GLOBAL OUTPUTS: Player
164734606Sbostic /
164834606Sbostic / DESCRIPTION:
164934606Sbostic /	Pay taxes on gold and gems.  If the player does not have enough
165034606Sbostic /	gold to pay taxes on the added gems, convert some gems to gold.
165134606Sbostic /	Add taxes to tax data base; add remaining gold and gems to
165234606Sbostic /	player's cache.
165334606Sbostic /
165434606Sbostic /************************************************************************/
165534606Sbostic 
collecttaxes(gold,gems)165634606Sbostic collecttaxes(gold, gems)
165734606Sbostic double	gold;
165834606Sbostic double	gems;
165934606Sbostic {
166034606Sbostic FILE	*fp;		/* to update Goldfile */
166134606Sbostic double	dtemp;		/* for temporary calculations */
166234606Sbostic double	taxes;		/* tax liability */
166334606Sbostic 
166434606Sbostic     /* add to cache */
166534606Sbostic     Player.p_gold += gold;
166634606Sbostic     Player.p_gems += gems;
166734606Sbostic 
166834606Sbostic     /* calculate tax liability */
166934606Sbostic     taxes = N_TAXAMOUNT / 100.0 * (N_GEMVALUE * gems + gold);
167034606Sbostic 
167134606Sbostic     if (Player.p_gold < taxes)
167234606Sbostic 	/* not enough gold to pay taxes, must convert some gems to gold */
167334606Sbostic 	{
167434606Sbostic 	dtemp = floor(taxes / N_GEMVALUE + 1.0); /* number of gems to convert */
167534606Sbostic 
167634606Sbostic 	if (Player.p_gems >= dtemp)
167734606Sbostic 	    /* player has enough to convert */
167834606Sbostic 	    {
167934606Sbostic 	    Player.p_gems -= dtemp;
168034606Sbostic 	    Player.p_gold += dtemp * N_GEMVALUE;
168134606Sbostic 	    }
168234606Sbostic 	else
168334606Sbostic 	    /* take everything; this should never happen */
168434606Sbostic 	    {
168534606Sbostic 	    Player.p_gold += Player.p_gems * N_GEMVALUE;
168634606Sbostic 	    Player.p_gems = 0.0;
168734606Sbostic 	    taxes = Player.p_gold;
168834606Sbostic 	    }
168934606Sbostic 	}
169034606Sbostic 
169134606Sbostic     Player.p_gold -= taxes;
169234606Sbostic 
169340279Sbostic     if ((fp = fopen(_PATH_GOLD, "r+")) != NULL)
169434606Sbostic 	/* update taxes */
169534606Sbostic 	{
169634606Sbostic 	dtemp = 0.0;
169734606Sbostic 	fread((char *) &dtemp, sizeof(double), 1, fp);
169834606Sbostic 	dtemp += floor(taxes);
169934606Sbostic 	fseek(fp, 0L, 0);
170034606Sbostic 	fwrite((char *) &dtemp, sizeof(double), 1, fp);
170134606Sbostic 	fclose(fp);
170234606Sbostic 	}
170334606Sbostic }
1704