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