Home | History | Annotate | Line # | Download | only in phantasia
misc.c revision 1.2
      1  1.2  cgd /*	$NetBSD: misc.c,v 1.2 1995/03/24 03:59:03 cgd Exp $	*/
      2  1.2  cgd 
      3  1.1  jtc /*
      4  1.1  jtc  * misc.c  Phantasia miscellaneous support routines
      5  1.1  jtc  */
      6  1.1  jtc 
      7  1.1  jtc #include "include.h"
      8  1.1  jtc 
      9  1.1  jtc 
     10  1.1  jtc /************************************************************************
     11  1.1  jtc /
     12  1.1  jtc / FUNCTION NAME: movelevel()
     13  1.1  jtc /
     14  1.1  jtc / FUNCTION: move player to new level
     15  1.1  jtc /
     16  1.1  jtc / AUTHOR: E. A. Estes, 12/4/85
     17  1.1  jtc /
     18  1.1  jtc / ARGUMENTS: none
     19  1.1  jtc /
     20  1.1  jtc / RETURN VALUE: none
     21  1.1  jtc /
     22  1.1  jtc / MODULES CALLED: death(), floor(), wmove(), drandom(), waddstr(), explevel()
     23  1.1  jtc /
     24  1.1  jtc / GLOBAL INPUTS: Player, *stdscr, *Statptr, Stattable[]
     25  1.1  jtc /
     26  1.1  jtc / GLOBAL OUTPUTS: Player, Changed
     27  1.1  jtc /
     28  1.1  jtc / DESCRIPTION:
     29  1.1  jtc /	Use lookup table to increment important statistics when
     30  1.1  jtc /	progressing to new experience level.
     31  1.1  jtc /	Players are rested to maximum as a bonus for making a new
     32  1.1  jtc /	level.
     33  1.1  jtc /	Check for council of wise, and being too big to be king.
     34  1.1  jtc /
     35  1.1  jtc /************************************************************************/
     36  1.1  jtc 
     37  1.1  jtc movelevel()
     38  1.1  jtc {
     39  1.1  jtc register struct charstats	*statptr;	/* for pointing into Stattable */
     40  1.1  jtc double	new;			/* new level */
     41  1.1  jtc double	inc;			/* increment between new and old levels */
     42  1.1  jtc 
     43  1.1  jtc     Changed = TRUE;
     44  1.1  jtc 
     45  1.1  jtc     if (Player.p_type == C_EXPER)
     46  1.1  jtc 	/* roll a type to use for increment */
     47  1.1  jtc 	statptr = &Stattable[(int) ROLL(C_MAGIC, C_HALFLING - C_MAGIC + 1)];
     48  1.1  jtc     else
     49  1.1  jtc 	statptr = Statptr;
     50  1.1  jtc 
     51  1.1  jtc     new = explevel(Player.p_experience);
     52  1.1  jtc     inc = new - Player.p_level;
     53  1.1  jtc     Player.p_level = new;
     54  1.1  jtc 
     55  1.1  jtc     /* add increments to statistics */
     56  1.1  jtc     Player.p_strength += statptr->c_strength.increase * inc;
     57  1.1  jtc     Player.p_mana += statptr->c_mana.increase * inc;
     58  1.1  jtc     Player.p_brains += statptr->c_brains.increase * inc;
     59  1.1  jtc     Player.p_magiclvl += statptr->c_magiclvl.increase * inc;
     60  1.1  jtc     Player.p_maxenergy += statptr->c_energy.increase * inc;
     61  1.1  jtc 
     62  1.1  jtc     /* rest to maximum upon reaching new level */
     63  1.1  jtc     Player.p_energy = Player.p_maxenergy + Player.p_shield;
     64  1.1  jtc 
     65  1.1  jtc     if (Player.p_crowns > 0 && Player.p_level >= 1000.0)
     66  1.1  jtc 	/* no longer able to be king -- turn crowns into cash */
     67  1.1  jtc 	{
     68  1.1  jtc 	Player.p_gold += ((double) Player.p_crowns) * 5000.0;
     69  1.1  jtc 	Player.p_crowns = 0;
     70  1.1  jtc 	}
     71  1.1  jtc 
     72  1.1  jtc     if (Player.p_level >= 3000.0 && Player.p_specialtype < SC_COUNCIL)
     73  1.1  jtc 	/* make a member of the council */
     74  1.1  jtc 	{
     75  1.1  jtc 	mvaddstr(6, 0, "You have made it to the Council of the Wise.\n");
     76  1.1  jtc 	addstr("Good Luck on your search for the Holy Grail.\n");
     77  1.1  jtc 
     78  1.1  jtc 	Player.p_specialtype = SC_COUNCIL;
     79  1.1  jtc 
     80  1.1  jtc 	/* no rings for council and above */
     81  1.1  jtc 	Player.p_ring.ring_type = R_NONE;
     82  1.1  jtc 	Player.p_ring.ring_duration = 0;
     83  1.1  jtc 
     84  1.1  jtc 	Player.p_lives = 3;		/* three extra lives */
     85  1.1  jtc 	}
     86  1.1  jtc 
     87  1.1  jtc     if (Player.p_level > 9999.0 && Player.p_specialtype != SC_VALAR)
     88  1.1  jtc 	death("Old age");
     89  1.1  jtc }
     90  1.1  jtc /**/
     92  1.1  jtc /************************************************************************
     93  1.1  jtc /
     94  1.1  jtc / FUNCTION NAME: descrlocation()
     95  1.1  jtc /
     96  1.1  jtc / FUNCTION: return a formatted description of location
     97  1.1  jtc /
     98  1.1  jtc / AUTHOR: E. A. Estes, 12/4/85
     99  1.1  jtc /
    100  1.1  jtc / ARGUMENTS:
    101  1.1  jtc /	struct player playerp - pointer to player structure
    102  1.1  jtc /	bool shortflag - set if short form is desired
    103  1.1  jtc /
    104  1.1  jtc / RETURN VALUE: pointer to string containing result
    105  1.1  jtc /
    106  1.1  jtc / MODULES CALLED: fabs(), floor(), sprintf(), distance()
    107  1.1  jtc /
    108  1.1  jtc / GLOBAL INPUTS: Databuf[]
    109  1.1  jtc /
    110  1.1  jtc / GLOBAL OUTPUTS: none
    111  1.1  jtc /
    112  1.1  jtc / DESCRIPTION:
    113  1.1  jtc /	Look at coordinates and return an appropriately formatted
    114  1.1  jtc /	string.
    115  1.1  jtc /
    116  1.1  jtc /************************************************************************/
    117  1.1  jtc 
    118  1.1  jtc char	*
    119  1.1  jtc descrlocation(playerp, shortflag)
    120  1.1  jtc struct player	*playerp;
    121  1.1  jtc bool	shortflag;
    122  1.1  jtc {
    123  1.1  jtc double	circle;			/* corresponding circle for coordinates */
    124  1.1  jtc register int	quadrant;	/* quandrant of grid */
    125  1.1  jtc register char	*label;		/* pointer to place name */
    126  1.1  jtc static char	*nametable[4][4] =   /* names of places */
    127  1.1  jtc 	{
    128  1.1  jtc 	"Anorien",	"Ithilien",	"Rohan",	"Lorien",
    129  1.1  jtc 	"Gondor",	"Mordor",	"Dunland",	"Rovanion",
    130  1.1  jtc 	"South Gondor", "Khand",	"Eriador",	"The Iron Hills",
    131  1.1  jtc 	"Far Harad",	"Near Harad",	"The Northern Waste", "Rhun"
    132  1.1  jtc 	};
    133  1.1  jtc 
    134  1.1  jtc     if (playerp->p_specialtype == SC_VALAR)
    135  1.1  jtc 	return(" is in Valhala");
    136  1.1  jtc     else if ((circle = CIRCLE(playerp->p_x, playerp->p_y)) >= 1000.0)
    137  1.1  jtc 	{
    138  1.1  jtc 	if (MAX(fabs(playerp->p_x), fabs(playerp->p_y)) > D_BEYOND)
    139  1.1  jtc 	    label = "The Point of No Return";
    140  1.1  jtc 	else
    141  1.1  jtc 	    label = "The Ashen Mountains";
    142  1.1  jtc 	}
    143  1.1  jtc     else if (circle >= 55)
    144  1.1  jtc 	label = "Morannon";
    145  1.1  jtc     else if (circle >= 35)
    146  1.1  jtc 	label = "Kennaquahair";
    147  1.1  jtc     else if (circle >= 20)
    148  1.1  jtc 	label = "The Dead Marshes";
    149  1.1  jtc     else if (circle >= 9)
    150  1.1  jtc 	label = "The Outer Waste";
    151  1.1  jtc     else if (circle >= 5)
    152  1.1  jtc 	label = "The Moors Adventurous";
    153  1.1  jtc     else
    154  1.1  jtc 	{
    155  1.1  jtc 	if (playerp->p_x == 0.0 && playerp->p_y == 0.0)
    156  1.1  jtc 	    label = "The Lord's Chamber";
    157  1.1  jtc 	else
    158  1.1  jtc 	    {
    159  1.1  jtc 	    /* this expression is split to prevent compiler loop with some compilers */
    160  1.1  jtc 	    quadrant = ((playerp->p_x > 0.0) ? 1 : 0);
    161  1.1  jtc 	    quadrant += ((playerp->p_y >= 0.0) ? 2 : 0);
    162  1.1  jtc 	    label = nametable[((int) circle) - 1][quadrant];
    163  1.1  jtc 	    }
    164  1.1  jtc 	}
    165  1.1  jtc 
    166  1.1  jtc     if (shortflag)
    167  1.1  jtc 	sprintf(Databuf, "%.29s", label);
    168  1.1  jtc     else
    169  1.1  jtc 	sprintf(Databuf, " is in %s  (%.0f,%.0f)", label, playerp->p_x, playerp->p_y);
    170  1.1  jtc 
    171  1.1  jtc     return(Databuf);
    172  1.1  jtc }
    173  1.1  jtc /**/
    175  1.1  jtc /************************************************************************
    176  1.1  jtc /
    177  1.1  jtc / FUNCTION NAME: tradingpost()
    178  1.1  jtc /
    179  1.1  jtc / FUNCTION: do trading post stuff
    180  1.1  jtc /
    181  1.1  jtc / AUTHOR: E. A. Estes, 12/4/85
    182  1.1  jtc /
    183  1.1  jtc / ARGUMENTS: none
    184  1.1  jtc /
    185  1.1  jtc / RETURN VALUE: none
    186  1.1  jtc /
    187  1.1  jtc / MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
    188  1.1  jtc /	sleep(), floor(), wmove(), drandom(), wclear(), printw(),
    189  1.1  jtc /	altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(),
    190  1.1  jtc /	wclrtoeol(), wclrtobot()
    191  1.1  jtc /
    192  1.1  jtc / GLOBAL INPUTS: Menu[], Circle, Player, *stdscr, Fileloc, Nobetter[]
    193  1.1  jtc /
    194  1.1  jtc / GLOBAL OUTPUTS: Player
    195  1.1  jtc /
    196  1.1  jtc / DESCRIPTION:
    197  1.1  jtc /	Different trading posts have different items.
    198  1.1  jtc /	Merchants cannot be cheated, but they can be dishonest
    199  1.1  jtc /	themselves.
    200  1.1  jtc /
    201  1.1  jtc /	Shields, swords, and quicksilver are not cumulative.  This is
    202  1.1  jtc /	one major area of complaint, but there are two reasons for this:
    203  1.1  jtc /		1) It becomes MUCH too easy to make very large versions
    204  1.1  jtc /		   of these items.
    205  1.1  jtc /		2) In the real world, one cannot simply weld two swords
    206  1.1  jtc /		   together to make a bigger one.
    207  1.1  jtc /
    208  1.1  jtc /	At one time, it was possible to sell old weapons at half the purchase
    209  1.1  jtc /	price.  This resulted in huge amounts of gold floating around,
    210  1.1  jtc /	and the game lost much of its challenge.
    211  1.1  jtc /
    212  1.1  jtc /	Also, purchasing gems defeats the whole purpose of gold.  Gold
    213  1.1  jtc /	is small change for lower level players.  They really shouldn't
    214  1.1  jtc /	be able to accumulate more than enough gold for a small sword or
    215  1.1  jtc /	a few books.  Higher level players shouldn't even bother to pick
    216  1.1  jtc /	up gold, except maybe to buy mana once in a while.
    217  1.1  jtc /
    218  1.1  jtc /************************************************************************/
    219  1.1  jtc 
    220  1.1  jtc tradingpost()
    221  1.1  jtc {
    222  1.1  jtc double	numitems;	/* number of items to purchase */
    223  1.1  jtc double	cost;		/* cost of purchase */
    224  1.1  jtc double	blessingcost;	/* cost of blessing */
    225  1.1  jtc int	ch;		/* input */
    226  1.1  jtc register int	size;	/* size of the trading post */
    227  1.1  jtc register int	loop;	/* loop counter */
    228  1.1  jtc int	cheat = 0;	/* number of times player has tried to cheat */
    229  1.1  jtc bool	dishonest = FALSE;/* set when merchant is dishonest */
    230  1.1  jtc 
    231  1.1  jtc     Player.p_status = S_TRADING;
    232  1.1  jtc     writerecord(&Player, Fileloc);
    233  1.1  jtc 
    234  1.1  jtc     clear();
    235  1.1  jtc     addstr("You are at a trading post. All purchases must be made with gold.");
    236  1.1  jtc 
    237  1.1  jtc     size = sqrt(fabs(Player.p_x / 100)) + 1;
    238  1.1  jtc     size = MIN(7, size);
    239  1.1  jtc 
    240  1.1  jtc     /* set up cost of blessing */
    241  1.1  jtc     blessingcost = 1000.0 * (Player.p_level + 5.0);
    242  1.1  jtc 
    243  1.1  jtc     /* print Menu */
    244  1.1  jtc     move(7, 0);
    245  1.1  jtc     for (loop = 0; loop < size; ++loop)
    246  1.1  jtc 	/* print Menu */
    247  1.1  jtc 	{
    248  1.1  jtc 	if (loop == 6)
    249  1.1  jtc 	    cost = blessingcost;
    250  1.1  jtc 	else
    251  1.1  jtc 	    cost = Menu[loop].cost;
    252  1.1  jtc 	printw("(%d) %-12s: %6.0f\n", loop + 1, Menu[loop].item, cost);
    253  1.1  jtc 	}
    254  1.1  jtc 
    255  1.1  jtc     mvprintw(5, 0, "L:Leave  P:Purchase  S:Sell Gems ? ");
    256  1.1  jtc 
    257  1.1  jtc     for (;;)
    258  1.1  jtc 	{
    259  1.1  jtc 	adjuststats();	/* truncate any bad values */
    260  1.1  jtc 
    261  1.1  jtc 	/* print some important statistics */
    262  1.1  jtc 	mvprintw(1, 0, "Gold:   %9.0f  Gems:  %9.0f  Level:   %6.0f  Charms: %6d\n",
    263  1.1  jtc 	    Player.p_gold, Player.p_gems, Player.p_level, Player.p_charms);
    264  1.1  jtc 	printw("Shield: %9.0f  Sword: %9.0f  Quicksilver:%3.0f  Blessed: %s\n",
    265  1.1  jtc 	    Player.p_shield, Player.p_sword, Player.p_quksilver,
    266  1.1  jtc 	    (Player.p_blessing ? " True" : "False"));
    267  1.1  jtc 	printw("Brains: %9.0f  Mana:  %9.0f", Player.p_brains, Player.p_mana);
    268  1.1  jtc 
    269  1.1  jtc 	move(5, 36);
    270  1.1  jtc 	ch = getanswer("LPS", FALSE);
    271  1.1  jtc 	move(15, 0);
    272  1.1  jtc 	clrtobot();
    273  1.1  jtc 	switch(ch)
    274  1.1  jtc 	    {
    275  1.1  jtc 	    case 'L':		/* leave */
    276  1.1  jtc 	    case '\n':
    277  1.1  jtc 		altercoordinates(0.0, 0.0, A_NEAR);
    278  1.1  jtc 		return;
    279  1.1  jtc 
    280  1.1  jtc 	    case 'P':		/* make purchase */
    281  1.1  jtc 		mvaddstr(15, 0, "What what would you like to buy ? ");
    282  1.1  jtc 		ch = getanswer(" 1234567", FALSE);
    283  1.1  jtc 		move(15, 0);
    284  1.1  jtc 		clrtoeol();
    285  1.1  jtc 
    286  1.1  jtc 		if (ch - '0' > size)
    287  1.1  jtc 		    addstr("Sorry, this merchant doesn't have that.");
    288  1.1  jtc 		else
    289  1.1  jtc 		    switch (ch)
    290  1.1  jtc 			{
    291  1.1  jtc 			case '1':
    292  1.1  jtc 			    printw("Mana is one per %.0f gold piece.  How many do you want (%.0f max) ? ",
    293  1.1  jtc 				Menu[0].cost, floor(Player.p_gold / Menu[0].cost));
    294  1.1  jtc 			    cost = (numitems = floor(infloat())) * Menu[0].cost;
    295  1.1  jtc 
    296  1.1  jtc 			    if (cost > Player.p_gold || numitems < 0)
    297  1.1  jtc 				++cheat;
    298  1.1  jtc 			    else
    299  1.1  jtc 				{
    300  1.1  jtc 				cheat = 0;
    301  1.1  jtc 				Player.p_gold -= cost;
    302  1.1  jtc 				if (drandom() < 0.02)
    303  1.1  jtc 				    dishonest = TRUE;
    304  1.1  jtc 				else
    305  1.1  jtc 				    Player.p_mana += numitems;
    306  1.1  jtc 				}
    307  1.1  jtc 			    break;
    308  1.1  jtc 
    309  1.1  jtc 			case '2':
    310  1.1  jtc 			    printw("Shields are %.0f per +1.  How many do you want (%.0f max) ? ",
    311  1.1  jtc 				Menu[1].cost, floor(Player.p_gold / Menu[1].cost));
    312  1.1  jtc 			    cost = (numitems = floor(infloat())) * Menu[1].cost;
    313  1.1  jtc 
    314  1.1  jtc 			    if (numitems == 0.0)
    315  1.1  jtc 				break;
    316  1.1  jtc 			    else if (cost > Player.p_gold || numitems < 0)
    317  1.1  jtc 				++cheat;
    318  1.1  jtc 			    else if (numitems < Player.p_shield)
    319  1.1  jtc 				NOBETTER();
    320  1.1  jtc 			    else
    321  1.1  jtc 				{
    322  1.1  jtc 				cheat = 0;
    323  1.1  jtc 				Player.p_gold -= cost;
    324  1.1  jtc 				if (drandom() < 0.02)
    325  1.1  jtc 				    dishonest = TRUE;
    326  1.1  jtc 				else
    327  1.1  jtc 				    Player.p_shield = numitems;
    328  1.1  jtc 				}
    329  1.1  jtc 			    break;
    330  1.1  jtc 
    331  1.1  jtc 			case '3':
    332  1.1  jtc 			    printw("A book costs %.0f gp.  How many do you want (%.0f max) ? ",
    333  1.1  jtc 				Menu[2].cost, floor(Player.p_gold / Menu[2].cost));
    334  1.1  jtc 			    cost = (numitems = floor(infloat())) * Menu[2].cost;
    335  1.1  jtc 
    336  1.1  jtc 			    if (cost > Player.p_gold || numitems < 0)
    337  1.1  jtc 				++cheat;
    338  1.1  jtc 			    else
    339  1.1  jtc 				{
    340  1.1  jtc 				cheat = 0;
    341  1.1  jtc 				Player.p_gold -= cost;
    342  1.1  jtc 				if (drandom() < 0.02)
    343  1.1  jtc 				    dishonest = TRUE;
    344  1.1  jtc 				else if (drandom() * numitems > Player.p_level / 10.0
    345  1.1  jtc 				    && numitems != 1)
    346  1.1  jtc 				    {
    347  1.1  jtc 				    printw("\nYou blew your mind!\n");
    348  1.1  jtc 				    Player.p_brains /= 5;
    349  1.1  jtc 				    }
    350  1.1  jtc 				else
    351  1.1  jtc 				    {
    352  1.1  jtc 				    Player.p_brains += floor(numitems) * ROLL(20, 8);
    353  1.1  jtc 				    }
    354  1.1  jtc 				}
    355  1.1  jtc 			    break;
    356  1.1  jtc 
    357  1.1  jtc 			case '4':
    358  1.1  jtc 			    printw("Swords are %.0f gp per +1.  How many + do you want (%.0f max) ? ",
    359  1.1  jtc 				Menu[3].cost, floor(Player.p_gold / Menu[3].cost));
    360  1.1  jtc 			    cost = (numitems = floor(infloat())) * Menu[3].cost;
    361  1.1  jtc 
    362  1.1  jtc 			    if (numitems == 0.0)
    363  1.1  jtc 				break;
    364  1.1  jtc 			    else if (cost > Player.p_gold || numitems < 0)
    365  1.1  jtc 				++cheat;
    366  1.1  jtc 			    else if (numitems < Player.p_sword)
    367  1.1  jtc 				NOBETTER();
    368  1.1  jtc 			    else
    369  1.1  jtc 				{
    370  1.1  jtc 				cheat = 0;
    371  1.1  jtc 				Player.p_gold -= cost;
    372  1.1  jtc 				if (drandom() < 0.02)
    373  1.1  jtc 				    dishonest = TRUE;
    374  1.1  jtc 				else
    375  1.1  jtc 				    Player.p_sword = numitems;
    376  1.1  jtc 				}
    377  1.1  jtc 			    break;
    378  1.1  jtc 
    379  1.1  jtc 			case '5':
    380  1.1  jtc 			    printw("A charm costs %.0f gp.  How many do you want (%.0f max) ? ",
    381  1.1  jtc 				Menu[4].cost, floor(Player.p_gold / Menu[4].cost));
    382  1.1  jtc 			    cost = (numitems = floor(infloat())) * Menu[4].cost;
    383  1.1  jtc 
    384  1.1  jtc 			    if (cost > Player.p_gold || numitems < 0)
    385  1.1  jtc 				++cheat;
    386  1.1  jtc 			    else
    387  1.1  jtc 				{
    388  1.1  jtc 				cheat = 0;
    389  1.1  jtc 				Player.p_gold -= cost;
    390  1.1  jtc 				if (drandom() < 0.02)
    391  1.1  jtc 				    dishonest = TRUE;
    392  1.1  jtc 				else
    393  1.1  jtc 				    Player.p_charms += numitems;
    394  1.1  jtc 				}
    395  1.1  jtc 			    break;
    396  1.1  jtc 
    397  1.1  jtc 			case '6':
    398  1.1  jtc 			    printw("Quicksilver is %.0f gp per +1.  How many + do you want (%.0f max) ? ",
    399  1.1  jtc 				Menu[5].cost, floor(Player.p_gold / Menu[5].cost));
    400  1.1  jtc 			    cost = (numitems = floor(infloat())) * Menu[5].cost;
    401  1.1  jtc 
    402  1.1  jtc 			    if (numitems == 0.0)
    403  1.1  jtc 				break;
    404  1.1  jtc 			    else if (cost > Player.p_gold || numitems < 0)
    405  1.1  jtc 				++cheat;
    406  1.1  jtc 			    else if (numitems < Player.p_quksilver)
    407  1.1  jtc 				NOBETTER();
    408  1.1  jtc 			    else
    409  1.1  jtc 				{
    410  1.1  jtc 				cheat = 0;
    411  1.1  jtc 				Player.p_gold -= cost;
    412  1.1  jtc 				if (drandom() < 0.02)
    413  1.1  jtc 				    dishonest = TRUE;
    414  1.1  jtc 				else
    415  1.1  jtc 				    Player.p_quksilver = numitems;
    416  1.1  jtc 				}
    417  1.1  jtc 			    break;
    418  1.1  jtc 
    419  1.1  jtc 			case '7':
    420  1.1  jtc 			    if (Player.p_blessing)
    421  1.1  jtc 				{
    422  1.1  jtc 				addstr("You already have a blessing.");
    423  1.1  jtc 				break;
    424  1.1  jtc 				}
    425  1.1  jtc 
    426  1.1  jtc 			    printw("A blessing requires a %.0f gp donation.  Still want one ? ", blessingcost);
    427  1.1  jtc 			    ch = getanswer("NY", FALSE);
    428  1.1  jtc 
    429  1.1  jtc 			    if (ch == 'Y')
    430  1.1  jtc 				if (Player.p_gold < blessingcost)
    431  1.1  jtc 				    ++cheat;
    432  1.1  jtc 				else
    433  1.1  jtc 				    {
    434  1.1  jtc 				    cheat = 0;
    435  1.1  jtc 				    Player.p_gold -= blessingcost;
    436  1.1  jtc 				    if (drandom() < 0.02)
    437  1.1  jtc 					dishonest = TRUE;
    438  1.1  jtc 				    else
    439  1.1  jtc 					Player.p_blessing = TRUE;
    440  1.1  jtc 				    }
    441  1.1  jtc 			    break;
    442  1.1  jtc 			}
    443  1.1  jtc 	    break;
    444  1.1  jtc 
    445  1.1  jtc 	    case 'S':		/* sell gems */
    446  1.1  jtc 		mvprintw(15, 0, "A gem is worth %.0f gp.  How many do you want to sell (%.0f max) ? ",
    447  1.1  jtc 		    (double) N_GEMVALUE, Player.p_gems);
    448  1.1  jtc 		numitems = floor(infloat());
    449  1.1  jtc 
    450  1.1  jtc 		if (numitems > Player.p_gems || numitems < 0)
    451  1.1  jtc 		    ++cheat;
    452  1.1  jtc 		else
    453  1.1  jtc 		    {
    454  1.1  jtc 		    cheat = 0;
    455  1.1  jtc 		    Player.p_gems -= numitems;
    456  1.1  jtc 		    Player.p_gold += numitems * N_GEMVALUE;
    457  1.1  jtc 		    }
    458  1.1  jtc 	    }
    459  1.1  jtc 
    460  1.1  jtc 	if (cheat == 1)
    461  1.1  jtc 	    mvaddstr(17, 0, "Come on, merchants aren't stupid.  Stop cheating.\n");
    462  1.1  jtc 	else if (cheat == 2)
    463  1.1  jtc 	    {
    464  1.1  jtc 	    mvaddstr(17, 0, "You had your chance.  This merchant happens to be\n");
    465  1.1  jtc 	    printw("a %.0f level magic user, and you made %s mad!\n",
    466  1.1  jtc 		ROLL(Circle * 20.0, 40.0), (drandom() < 0.5) ? "him" : "her");
    467  1.1  jtc 	    altercoordinates(0.0, 0.0, A_FAR);
    468  1.1  jtc 	    Player.p_energy /= 2.0;
    469  1.1  jtc 	    ++Player.p_sin;
    470  1.1  jtc 	    more(23);
    471  1.1  jtc 	    return;
    472  1.1  jtc 	    }
    473  1.1  jtc 	else if (dishonest)
    474  1.1  jtc 	    {
    475  1.1  jtc 	    mvaddstr(17, 0, "The merchant stole your money!");
    476  1.1  jtc 	    refresh();
    477  1.1  jtc 	    altercoordinates(Player.p_x - Player.p_x / 10.0,
    478  1.1  jtc 		Player.p_y - Player.p_y / 10.0, A_SPECIFIC);
    479  1.1  jtc 	    sleep(2);
    480  1.1  jtc 	    return;
    481  1.1  jtc 	    }
    482  1.1  jtc 	}
    483  1.1  jtc }
    484  1.1  jtc /**/
    486  1.1  jtc /************************************************************************
    487  1.1  jtc /
    488  1.1  jtc / FUNCTION NAME: displaystats()
    489  1.1  jtc /
    490  1.1  jtc / FUNCTION: print out important player statistics
    491  1.1  jtc /
    492  1.1  jtc / AUTHOR: E. A. Estes, 12/4/85
    493  1.1  jtc /
    494  1.1  jtc / ARGUMENTS: none
    495  1.1  jtc /
    496  1.1  jtc / RETURN VALUE: none
    497  1.1  jtc /
    498  1.1  jtc / MODULES CALLED: descrstatus(), descrlocation(), mvprintw()
    499  1.1  jtc /
    500  1.1  jtc / GLOBAL INPUTS: Users, Player
    501  1.1  jtc /
    502  1.1  jtc / GLOBAL OUTPUTS: none
    503  1.1  jtc /
    504  1.1  jtc / DESCRIPTION:
    505  1.1  jtc /	Important player statistics are printed on the screen.
    506  1.1  jtc /
    507  1.1  jtc /************************************************************************/
    508  1.1  jtc 
    509  1.1  jtc displaystats()
    510  1.1  jtc {
    511  1.1  jtc     mvprintw(0, 0, "%s%s\n", Player.p_name, descrlocation(&Player, FALSE));
    512  1.1  jtc     mvprintw(1, 0, "Level :%7.0f   Energy  :%9.0f(%9.0f)  Mana :%9.0f  Users:%3d\n",
    513  1.1  jtc 	Player.p_level, Player.p_energy, Player.p_maxenergy + Player.p_shield,
    514  1.1  jtc 	Player.p_mana, Users);
    515  1.1  jtc     mvprintw(2, 0, "Quick :%3.0f(%3.0f)  Strength:%9.0f(%9.0f)  Gold :%9.0f  %s\n",
    516  1.1  jtc 	Player.p_speed, Player.p_quickness + Player.p_quksilver, Player.p_might,
    517  1.1  jtc 	Player.p_strength + Player.p_sword, Player.p_gold, descrstatus(&Player));
    518  1.1  jtc }
    519  1.1  jtc /**/
    521  1.1  jtc /************************************************************************
    522  1.1  jtc /
    523  1.1  jtc / FUNCTION NAME: allstatslist()
    524  1.1  jtc /
    525  1.1  jtc / FUNCTION: show player items
    526  1.1  jtc /
    527  1.1  jtc / AUTHOR: E. A. Estes, 12/4/85
    528  1.1  jtc /
    529  1.1  jtc / ARGUMENTS: none
    530  1.1  jtc /
    531  1.1  jtc / RETURN VALUE: none
    532  1.1  jtc /
    533  1.1  jtc / MODULES CALLED: mvprintw(), descrtype()
    534  1.1  jtc /
    535  1.1  jtc / GLOBAL INPUTS: Player
    536  1.1  jtc /
    537  1.1  jtc / GLOBAL OUTPUTS: none
    538  1.1  jtc /
    539  1.1  jtc / DESCRIPTION:
    540  1.1  jtc /	Print out some player statistics of lesser importance.
    541  1.1  jtc /
    542  1.1  jtc /************************************************************************/
    543  1.1  jtc 
    544  1.1  jtc allstatslist()
    545  1.1  jtc {
    546  1.1  jtc static	char	*flags[] =	/* to print value of some bools */
    547  1.1  jtc 	    {
    548  1.1  jtc 	    "False",
    549  1.1  jtc 	    " True"
    550  1.1  jtc 	    };
    551  1.1  jtc 
    552  1.1  jtc     mvprintw( 8,  0, "Type: %s\n",  descrtype(&Player,  FALSE));
    553  1.1  jtc 
    554  1.1  jtc     mvprintw(10,  0, "Experience: %9.0f", Player.p_experience);
    555  1.1  jtc     mvprintw(11,  0, "Brains    : %9.0f", Player.p_brains);
    556  1.1  jtc     mvprintw(12,  0, "Magic Lvl : %9.0f", Player.p_magiclvl);
    557  1.1  jtc     mvprintw(13,  0, "Sin       : %9.5f", Player.p_sin);
    558  1.1  jtc     mvprintw(14,  0, "Poison    : %9.5f", Player.p_poison);
    559  1.1  jtc     mvprintw(15,  0, "Gems      : %9.0f", Player.p_gems);
    560  1.1  jtc     mvprintw(16,  0, "Age       : %9d", Player.p_age);
    561  1.1  jtc     mvprintw(10, 40, "Holy Water: %9d", Player.p_holywater);
    562  1.1  jtc     mvprintw(11, 40, "Amulets   : %9d", Player.p_amulets);
    563  1.1  jtc     mvprintw(12, 40, "Charms    : %9d", Player.p_charms);
    564  1.1  jtc     mvprintw(13, 40, "Crowns    : %9d", Player.p_crowns);
    565  1.1  jtc     mvprintw(14, 40, "Shield    : %9.0f", Player.p_shield);
    566  1.1  jtc     mvprintw(15, 40, "Sword     : %9.0f", Player.p_sword);
    567  1.1  jtc     mvprintw(16, 40, "Quickslver: %9.0f", Player.p_quksilver);
    568  1.1  jtc 
    569  1.1  jtc     mvprintw(18,  0, "Blessing: %s   Ring: %s   Virgin: %s   Palantir: %s",
    570  1.1  jtc 	flags[Player.p_blessing], flags[Player.p_ring.ring_type != R_NONE],
    571  1.1  jtc 	flags[Player.p_virgin], flags[Player.p_palantir]);
    572  1.1  jtc }
    573  1.1  jtc /**/
    575  1.1  jtc /************************************************************************
    576  1.1  jtc /
    577  1.1  jtc / FUNCTION NAME: descrtype()
    578  1.1  jtc /
    579  1.1  jtc / FUNCTION: return a string specifying player type
    580  1.1  jtc /
    581  1.1  jtc / AUTHOR: E. A. Estes, 12/4/85
    582  1.1  jtc /
    583  1.1  jtc / ARGUMENTS:
    584  1.1  jtc /	struct player playerp - pointer to structure for player
    585  1.1  jtc /	bool shortflag - set if short form is desired
    586  1.1  jtc /
    587  1.1  jtc / RETURN VALUE: pointer to string describing player type
    588  1.1  jtc /
    589  1.1  jtc / MODULES CALLED: strcpy()
    590  1.1  jtc /
    591  1.1  jtc / GLOBAL INPUTS: Databuf[]
    592  1.1  jtc /
    593  1.1  jtc / GLOBAL OUTPUTS: Databuf[]
    594  1.1  jtc /
    595  1.1  jtc / DESCRIPTION:
    596  1.1  jtc /	Return a string describing the player type.
    597  1.1  jtc /	King, council, valar, supercedes other types.
    598  1.1  jtc /	The first character of the string is '*' if the player
    599  1.1  jtc /	has a crown.
    600  1.1  jtc /	If 'shortflag' is TRUE, return a 3 character string.
    601  1.1  jtc /
    602  1.1  jtc /************************************************************************/
    603  1.1  jtc 
    604  1.1  jtc char	*
    605  1.1  jtc descrtype(playerp, shortflag)
    606  1.1  jtc struct player *playerp;
    607  1.1  jtc bool	shortflag;
    608  1.1  jtc {
    609  1.1  jtc register int type;	/* for caluculating result subscript */
    610  1.1  jtc static char	*results[] =	/* description table */
    611  1.1  jtc 			{
    612  1.1  jtc 			" Magic User", " MU",
    613  1.1  jtc 			" Fighter", " F ",
    614  1.1  jtc 			" Elf", " E ",
    615  1.1  jtc 			" Dwarf", " D ",
    616  1.1  jtc 			" Halfling", " H ",
    617  1.1  jtc 			" Experimento", " EX",
    618  1.1  jtc 			" Super", " S ",
    619  1.1  jtc 			" King", " K ",
    620  1.1  jtc 			" Council of Wise", " CW",
    621  1.1  jtc 			" Ex-Valar", " EV",
    622  1.1  jtc 			" Valar", " V ",
    623  1.1  jtc 			" ? ", " ? "
    624  1.1  jtc 			};
    625  1.1  jtc 
    626  1.1  jtc     type = playerp->p_type;
    627  1.1  jtc 
    628  1.1  jtc     switch (playerp->p_specialtype)
    629  1.1  jtc 	{
    630  1.1  jtc 	case SC_NONE:
    631  1.1  jtc 	    type = playerp->p_type;
    632  1.1  jtc 	    break;
    633  1.1  jtc 
    634  1.1  jtc 	case SC_KING:
    635  1.1  jtc 	    type = 7;
    636  1.1  jtc 	    break;
    637  1.1  jtc 
    638  1.1  jtc 	case SC_COUNCIL:
    639  1.1  jtc 	    type = 8;
    640  1.1  jtc 	    break;
    641  1.1  jtc 
    642  1.1  jtc 	case SC_EXVALAR:
    643  1.1  jtc 	    type = 9;
    644  1.1  jtc 	    break;
    645  1.1  jtc 
    646  1.1  jtc 	case SC_VALAR:
    647  1.1  jtc 	    type = 10;
    648  1.1  jtc 	    break;
    649  1.1  jtc 	}
    650  1.1  jtc 
    651  1.1  jtc     type *= 2;		/* calculate offset */
    652  1.1  jtc 
    653  1.1  jtc     if (type > 20)
    654  1.1  jtc 	/* error */
    655  1.1  jtc 	type = 22;
    656  1.1  jtc 
    657  1.1  jtc     if (shortflag)
    658  1.1  jtc 	/* use short descriptions */
    659  1.1  jtc 	++type;
    660  1.1  jtc 
    661  1.1  jtc     if (playerp->p_crowns > 0)
    662  1.1  jtc 	{
    663  1.1  jtc 	strcpy(Databuf, results[type]);
    664  1.1  jtc 	Databuf[0] = '*';
    665  1.1  jtc 	return(Databuf);
    666  1.1  jtc 	}
    667  1.1  jtc     else
    668  1.1  jtc 	return(results[type]);
    669  1.1  jtc }
    670  1.1  jtc /**/
    672  1.1  jtc /************************************************************************
    673  1.1  jtc /
    674  1.1  jtc / FUNCTION NAME: findname()
    675  1.1  jtc /
    676  1.1  jtc / FUNCTION: find location in player file of given name
    677  1.1  jtc /
    678  1.1  jtc / AUTHOR: E. A. Estes, 12/4/85
    679  1.1  jtc /
    680  1.1  jtc / ARGUMENTS:
    681  1.1  jtc /	char *name - name of character to look for
    682  1.1  jtc /	struct player *playerp - pointer of structure to fill
    683  1.1  jtc /
    684  1.1  jtc / RETURN VALUE: location of player if found, -1 otherwise
    685  1.1  jtc /
    686  1.1  jtc / MODULES CALLED: fread(), fseek(), strcmp()
    687  1.1  jtc /
    688  1.1  jtc / GLOBAL INPUTS: Wizard, *Playersfp
    689  1.1  jtc /
    690  1.1  jtc / GLOBAL OUTPUTS: none
    691  1.1  jtc /
    692  1.1  jtc / DESCRIPTION:
    693  1.1  jtc /	Search the player file for the player of the given name.
    694  1.1  jtc /	If player is found, fill structure with player data.
    695  1.1  jtc /
    696  1.1  jtc /************************************************************************/
    697  1.1  jtc 
    698  1.1  jtc long
    699  1.1  jtc findname(name, playerp)
    700  1.1  jtc register char	*name;
    701  1.1  jtc register struct player *playerp;
    702  1.1  jtc {
    703  1.1  jtc long	loc = 0;			/* location in the file */
    704  1.1  jtc 
    705  1.1  jtc     fseek(Playersfp, 0L, 0);
    706  1.1  jtc     while (fread((char *) playerp, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
    707  1.1  jtc 	{
    708  1.1  jtc 	if (strcmp(playerp->p_name, name) == 0)
    709  1.1  jtc 	    {
    710  1.1  jtc 	    if (playerp->p_status != S_NOTUSED || Wizard)
    711  1.1  jtc 		/* found it */
    712  1.1  jtc 		return(loc);
    713  1.1  jtc 	    }
    714  1.1  jtc 	loc += SZ_PLAYERSTRUCT;
    715  1.1  jtc 	}
    716  1.1  jtc 
    717  1.1  jtc     return(-1);
    718  1.1  jtc }
    719  1.1  jtc /**/
    721  1.1  jtc /************************************************************************
    722  1.1  jtc /
    723  1.1  jtc / FUNCTION NAME: allocrecord()
    724  1.1  jtc /
    725  1.1  jtc / FUNCTION: find space in the player file for a new character
    726  1.1  jtc /
    727  1.1  jtc / AUTHOR: E. A. Estes, 12/4/85
    728  1.1  jtc /
    729  1.1  jtc / ARGUMENTS: none
    730  1.1  jtc /
    731  1.1  jtc / RETURN VALUE: location of free space in file
    732  1.1  jtc /
    733  1.1  jtc / MODULES CALLED: initplayer(), writerecord(), fread(), fseek()
    734  1.1  jtc /
    735  1.1  jtc / GLOBAL INPUTS: Other, *Playersfp
    736  1.1  jtc /
    737  1.1  jtc / GLOBAL OUTPUTS: Player
    738  1.1  jtc /
    739  1.1  jtc / DESCRIPTION:
    740  1.1  jtc /	Search the player file for an unused entry.  If none are found,
    741  1.1  jtc /	make one at the end of the file.
    742  1.1  jtc /
    743  1.1  jtc /************************************************************************/
    744  1.1  jtc 
    745  1.1  jtc long
    746  1.1  jtc allocrecord()
    747  1.1  jtc {
    748  1.1  jtc long	loc = 0L;		/* location in file */
    749  1.1  jtc 
    750  1.1  jtc     fseek(Playersfp, 0L, 0);
    751  1.1  jtc     while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
    752  1.1  jtc 	{
    753  1.1  jtc 	if (Other.p_status == S_NOTUSED)
    754  1.1  jtc 	    /* found an empty record */
    755  1.1  jtc 	    return(loc);
    756  1.1  jtc 	else
    757  1.1  jtc 	    loc += SZ_PLAYERSTRUCT;
    758  1.1  jtc 	}
    759  1.1  jtc 
    760  1.1  jtc     /* make a new record */
    761  1.1  jtc     initplayer(&Other);
    762  1.1  jtc     Player.p_status = S_OFF;
    763  1.1  jtc     writerecord(&Other, loc);
    764  1.1  jtc 
    765  1.1  jtc     return(loc);
    766  1.1  jtc }
    767  1.1  jtc /**/
    769  1.1  jtc /************************************************************************
    770  1.1  jtc /
    771  1.1  jtc / FUNCTION NAME: freerecord()
    772  1.1  jtc /
    773  1.1  jtc / FUNCTION: free up a record on the player file
    774  1.1  jtc /
    775  1.1  jtc / AUTHOR: E. A. Estes, 2/7/86
    776  1.1  jtc /
    777  1.1  jtc / ARGUMENTS:
    778  1.1  jtc /	struct player playerp - pointer to structure to free
    779  1.1  jtc /	long loc - location in file to free
    780  1.1  jtc /
    781  1.1  jtc / RETURN VALUE: none
    782  1.1  jtc /
    783  1.1  jtc / MODULES CALLED: writerecord()
    784  1.1  jtc /
    785  1.1  jtc / GLOBAL INPUTS: none
    786  1.1  jtc /
    787  1.1  jtc / GLOBAL OUTPUTS: none
    788  1.1  jtc /
    789  1.1  jtc / DESCRIPTION:
    790  1.1  jtc /	Mark structure as not used, and update player file.
    791  1.1  jtc /
    792  1.1  jtc /************************************************************************/
    793  1.1  jtc 
    794  1.1  jtc freerecord(playerp, loc)
    795  1.1  jtc struct player	*playerp;
    796  1.1  jtc long	loc;
    797  1.1  jtc {
    798  1.1  jtc     playerp->p_name[0] = CH_MARKDELETE;
    799  1.1  jtc     playerp->p_status = S_NOTUSED;
    800  1.1  jtc     writerecord(playerp, loc);
    801  1.1  jtc }
    802  1.1  jtc /**/
    804  1.1  jtc /************************************************************************
    805  1.1  jtc /
    806  1.1  jtc / FUNCTION NAME: leavegame()
    807  1.1  jtc /
    808  1.1  jtc / FUNCTION: leave game
    809  1.1  jtc /
    810  1.1  jtc / AUTHOR: E. A. Estes, 12/4/85
    811  1.1  jtc /
    812  1.1  jtc / ARGUMENTS: none
    813  1.1  jtc /
    814  1.1  jtc / RETURN VALUE: none
    815  1.1  jtc /
    816  1.1  jtc / MODULES CALLED: freerecord(), writerecord(), cleanup()
    817  1.1  jtc /
    818  1.1  jtc / GLOBAL INPUTS: Player, Fileloc
    819  1.1  jtc /
    820  1.1  jtc / GLOBAL OUTPUTS: Player
    821  1.1  jtc /
    822  1.1  jtc / DESCRIPTION:
    823  1.1  jtc /	Mark player as inactive, and cleanup.
    824  1.1  jtc /	Do not save players below level 1.
    825  1.1  jtc /
    826  1.1  jtc /************************************************************************/
    827  1.1  jtc 
    828  1.1  jtc leavegame()
    829  1.1  jtc {
    830  1.1  jtc 
    831  1.1  jtc     if (Player.p_level < 1.0)
    832  1.1  jtc 	/* delete character */
    833  1.1  jtc 	freerecord(&Player, Fileloc);
    834  1.1  jtc     else
    835  1.1  jtc 	{
    836  1.1  jtc 	Player.p_status = S_OFF;
    837  1.1  jtc 	writerecord(&Player, Fileloc);
    838  1.1  jtc 	}
    839  1.1  jtc 
    840  1.1  jtc     cleanup(TRUE);
    841  1.1  jtc     /*NOTREACHED*/
    842  1.1  jtc }
    843  1.1  jtc /**/
    845  1.1  jtc /************************************************************************
    846  1.1  jtc /
    847  1.1  jtc / FUNCTION NAME: death()
    848  1.1  jtc /
    849  1.1  jtc / FUNCTION: death routine
    850  1.1  jtc /
    851  1.1  jtc / AUTHOR: E. A. Estes, 12/4/85
    852  1.1  jtc /
    853  1.1  jtc / ARGUMENTS:
    854  1.1  jtc /	char *how - pointer to string describing cause of death
    855  1.1  jtc /
    856  1.1  jtc / RETURN VALUE: none
    857  1.1  jtc /
    858  1.1  jtc / MODULES CALLED: freerecord(), enterscore(), more(), exit(), fread(),
    859  1.1  jtc /	fseek(), execl(), fopen(), floor(), wmove(), drandom(), wclear(), strcmp(),
    860  1.1  jtc /	fwrite(), fflush(), printw(), strcpy(), fclose(), waddstr(), cleanup(),
    861  1.1  jtc /	fprintf(), wrefresh(), getanswer(), descrtype()
    862  1.1  jtc /
    863  1.1  jtc / GLOBAL INPUTS: Curmonster, Wizard, Player, *stdscr, Fileloc, *Monstfp
    864  1.1  jtc /
    865  1.1  jtc / GLOBAL OUTPUTS: Player
    866  1.1  jtc /
    867  1.1  jtc / DESCRIPTION:
    868  1.1  jtc /	Kill off current player.
    869  1.1  jtc /	Handle rings, and multiple lives.
    870  1.1  jtc /	Print an appropriate message.
    871  1.1  jtc /	Update scoreboard, lastdead, and let other players know about
    872  1.1  jtc /	the demise of their comrade.
    873  1.1  jtc /
    874  1.1  jtc /************************************************************************/
    875  1.1  jtc 
    876  1.1  jtc death(how)
    877  1.1  jtc char	*how;
    878  1.1  jtc {
    879  1.1  jtc FILE	*fp;		/* for updating various files */
    880  1.1  jtc int	ch;		/* input */
    881  1.1  jtc static	char	*deathmesg[] =
    882  1.1  jtc 	/* add more messages here, if desired */
    883  1.1  jtc 	{
    884  1.1  jtc 	"You have been wounded beyond repair.  ",
    885  1.1  jtc 	"You have been disemboweled.  ",
    886  1.1  jtc 	"You've been mashed, mauled, and spit upon.  (You're dead.)\n",
    887  1.1  jtc 	"You died!  ",
    888  1.1  jtc 	"You're a complete failure -- you've died!!\n",
    889  1.1  jtc 	"You have been dealt a fatal blow!  "
    890  1.1  jtc 	};
    891  1.1  jtc 
    892  1.1  jtc     clear();
    893  1.1  jtc 
    894  1.1  jtc     if (strcmp(how, "Stupidity") != 0)
    895  1.1  jtc 	{
    896  1.1  jtc 	if (Player.p_level > 9999.0)
    897  1.1  jtc 	    /* old age */
    898  1.1  jtc 	    addstr("Characters must be retired upon reaching level 10000.  Sorry.");
    899  1.1  jtc 	else if (Player.p_lives > 0)
    900  1.1  jtc 	    /* extra lives */
    901  1.1  jtc 	    {
    902  1.1  jtc 	    addstr("You should be more cautious.  You've been killed.\n");
    903  1.1  jtc 	    printw("You only have %d more chance(s).\n", --Player.p_lives);
    904  1.1  jtc 	    more(3);
    905  1.1  jtc 	    Player.p_energy = Player.p_maxenergy;
    906  1.1  jtc 	    return;
    907  1.1  jtc 	    }
    908  1.1  jtc 	else if (Player.p_specialtype == SC_VALAR)
    909  1.1  jtc 	    {
    910  1.1  jtc 	    addstr("You had your chances, but Valar aren't totally\n");
    911  1.1  jtc 	    addstr("immortal.  You are now left to wither and die . . .\n");
    912  1.1  jtc 	    more(3);
    913  1.1  jtc 	    Player.p_brains = Player.p_level / 25.0;
    914  1.1  jtc 	    Player.p_energy = Player.p_maxenergy /= 5.0;
    915  1.1  jtc 	    Player.p_quksilver = Player.p_sword = 0.0;
    916  1.1  jtc 	    Player.p_specialtype = SC_COUNCIL;
    917  1.1  jtc 	    return;
    918  1.1  jtc 	    }
    919  1.1  jtc 	else if (Player.p_ring.ring_inuse &&
    920  1.1  jtc 	    (Player.p_ring.ring_type == R_DLREG || Player.p_ring.ring_type == R_NAZREG))
    921  1.1  jtc 	    /* good ring in use - saved from death */
    922  1.1  jtc 	    {
    923  1.1  jtc 	    mvaddstr(4, 0, "Your ring saved you from death!\n");
    924  1.1  jtc 	    refresh();
    925  1.1  jtc 	    Player.p_ring.ring_type = R_NONE;
    926  1.1  jtc 	    Player.p_energy = Player.p_maxenergy / 12.0 + 1.0;
    927  1.1  jtc 	    if (Player.p_crowns > 0)
    928  1.1  jtc 		--Player.p_crowns;
    929  1.1  jtc 	    return;
    930  1.1  jtc 	    }
    931  1.1  jtc 	else if (Player.p_ring.ring_type == R_BAD
    932  1.1  jtc 	    || Player.p_ring.ring_type == R_SPOILED)
    933  1.1  jtc 	    /* bad ring in possession; name idiot after player */
    934  1.1  jtc 	    {
    935  1.1  jtc 	    mvaddstr(4, 0,
    936  1.1  jtc 		"Your ring has taken control of you and turned you into a monster!\n");
    937  1.1  jtc 	    fseek(Monstfp, 13L * SZ_MONSTERSTRUCT, 0);
    938  1.1  jtc 	    fread((char *) &Curmonster, SZ_MONSTERSTRUCT, 1, Monstfp);
    939  1.1  jtc 	    strcpy(Curmonster.m_name, Player.p_name);
    940  1.1  jtc 	    fseek(Monstfp, 13L * SZ_MONSTERSTRUCT, 0);
    941  1.1  jtc 	    fwrite((char *) &Curmonster, SZ_MONSTERSTRUCT, 1, Monstfp);
    942  1.1  jtc 	    fflush(Monstfp);
    943  1.1  jtc 	    }
    944  1.1  jtc 	}
    945  1.1  jtc 
    946  1.1  jtc     enterscore();		/* update score board */
    947  1.1  jtc 
    948  1.1  jtc     /* put info in last dead file */
    949  1.1  jtc     fp = fopen(_PATH_LASTDEAD, "w");
    950  1.1  jtc     fprintf(fp,"%s (%s, run by %s, level %.0f, killed by %s)",
    951  1.1  jtc 	Player.p_name, descrtype(&Player, TRUE),
    952  1.1  jtc 	Player.p_login, Player.p_level, how);
    953  1.1  jtc     fclose(fp);
    954  1.1  jtc 
    955  1.1  jtc     /* let other players know */
    956  1.1  jtc     fp = fopen(_PATH_MESS, "w");
    957  1.1  jtc     fprintf(fp, "%s was killed by %s.", Player.p_name, how);
    958  1.1  jtc     fclose(fp);
    959  1.1  jtc 
    960  1.1  jtc     freerecord(&Player, Fileloc);
    961  1.1  jtc 
    962  1.1  jtc     clear();
    963  1.1  jtc     move(10, 0);
    964  1.1  jtc     addstr(deathmesg[(int) ROLL(0.0, (double) sizeof(deathmesg) / sizeof(char *))]);
    965  1.1  jtc     addstr("Care to give it another try ? ");
    966  1.1  jtc     ch = getanswer("NY", FALSE);
    967  1.1  jtc 
    968  1.1  jtc     if (ch == 'Y')
    969  1.1  jtc 	{
    970  1.1  jtc 	cleanup(FALSE);
    971  1.1  jtc 	execl(_PATH_GAMEPROG, "phantasia", "-s",
    972  1.1  jtc 	    (Wizard ? "-S": (char *) NULL), 0);
    973  1.1  jtc 	exit(0);
    974  1.1  jtc 	/*NOTREACHED*/
    975  1.1  jtc 	}
    976  1.1  jtc 
    977  1.1  jtc     cleanup(TRUE);
    978  1.1  jtc     /*NOTREACHED*/
    979  1.1  jtc }
    980  1.1  jtc /**/
    982  1.1  jtc /************************************************************************
    983  1.1  jtc /
    984  1.1  jtc / FUNCTION NAME: writerecord()
    985  1.1  jtc /
    986  1.1  jtc / FUNCTION: update structure in player file
    987  1.1  jtc /
    988  1.1  jtc / AUTHOR: E. A. Estes, 12/4/85
    989  1.1  jtc /
    990  1.1  jtc / ARGUMENTS:
    991  1.1  jtc /	struct player *playerp - pointer to structure to write out
    992  1.1  jtc /	long place - location in file to updata
    993  1.1  jtc /
    994  1.1  jtc / RETURN VALUE: none
    995  1.1  jtc /
    996  1.1  jtc / MODULES CALLED: fseek(), fwrite(), fflush()
    997  1.1  jtc /
    998  1.1  jtc / GLOBAL INPUTS: *Playersfp
    999  1.1  jtc /
   1000  1.1  jtc / GLOBAL OUTPUTS: none
   1001  1.1  jtc /
   1002  1.1  jtc / DESCRIPTION:
   1003  1.1  jtc /	Update location in player file with given structure.
   1004  1.1  jtc /
   1005  1.1  jtc /************************************************************************/
   1006  1.1  jtc 
   1007  1.1  jtc writerecord(playerp, place)
   1008  1.1  jtc register struct player	*playerp;
   1009  1.1  jtc long	place;
   1010  1.1  jtc {
   1011  1.1  jtc     fseek(Playersfp, place, 0);
   1012  1.1  jtc     fwrite((char *) playerp, SZ_PLAYERSTRUCT, 1, Playersfp);
   1013  1.1  jtc     fflush(Playersfp);
   1014  1.1  jtc }
   1015  1.1  jtc /**/
   1017  1.1  jtc /************************************************************************
   1018  1.1  jtc /
   1019  1.1  jtc / FUNCTION NAME: explevel()
   1020  1.1  jtc /
   1021  1.1  jtc / FUNCTION: calculate level based upon experience
   1022  1.1  jtc /
   1023  1.1  jtc / AUTHOR: E. A. Estes, 12/4/85
   1024  1.1  jtc /
   1025  1.1  jtc / ARGUMENTS:
   1026  1.1  jtc /	double experience - experience to calculate experience level from
   1027  1.1  jtc /
   1028  1.1  jtc / RETURN VALUE: experience level
   1029  1.1  jtc /
   1030  1.1  jtc / MODULES CALLED: pow(), floor()
   1031  1.1  jtc /
   1032  1.1  jtc / GLOBAL INPUTS: none
   1033  1.1  jtc /
   1034  1.1  jtc / GLOBAL OUTPUTS: none
   1035  1.1  jtc /
   1036  1.1  jtc / DESCRIPTION:
   1037  1.1  jtc /	Experience level is a geometric progression.  This has been finely
   1038  1.1  jtc /	tuned over the years, and probably should not be changed.
   1039  1.1  jtc /
   1040  1.1  jtc /************************************************************************/
   1041  1.1  jtc 
   1042  1.1  jtc double
   1043  1.1  jtc explevel(experience)
   1044  1.1  jtc double	experience;
   1045  1.1  jtc {
   1046  1.1  jtc     if (experience < 1.1e7)
   1047  1.1  jtc 	return(floor(pow((experience / 1000.0), 0.4875)));
   1048  1.1  jtc     else
   1049  1.1  jtc 	return(floor(pow((experience / 1250.0), 0.4865)));
   1050  1.1  jtc }
   1051  1.1  jtc /**/
   1053  1.1  jtc /************************************************************************
   1054  1.1  jtc /
   1055  1.1  jtc / FUNCTION NAME: truncstring()
   1056  1.1  jtc /
   1057  1.1  jtc / FUNCTION: truncate trailing blanks off a string
   1058  1.1  jtc /
   1059  1.1  jtc / AUTHOR: E. A. Estes, 12/4/85
   1060  1.1  jtc /
   1061  1.1  jtc / ARGUMENTS:
   1062  1.1  jtc /	char *string - pointer to null terminated string
   1063  1.1  jtc /
   1064  1.1  jtc / RETURN VALUE: none
   1065  1.1  jtc /
   1066  1.1  jtc / MODULES CALLED: strlen()
   1067  1.1  jtc /
   1068  1.1  jtc / GLOBAL INPUTS: none
   1069  1.1  jtc /
   1070  1.1  jtc / GLOBAL OUTPUTS: none
   1071  1.1  jtc /
   1072  1.1  jtc / DESCRIPTION:
   1073  1.1  jtc /	Put nul characters in place of spaces at the end of the string.
   1074  1.1  jtc /
   1075  1.1  jtc /************************************************************************/
   1076  1.1  jtc 
   1077  1.1  jtc truncstring(string)
   1078  1.1  jtc register char	*string;
   1079  1.1  jtc {
   1080  1.1  jtc register int	length;		/* length of string */
   1081  1.1  jtc 
   1082  1.1  jtc     length = strlen(string);
   1083  1.1  jtc     while (string[--length] == ' ')
   1084  1.1  jtc 	string[length] = '\0';
   1085  1.1  jtc }
   1086  1.1  jtc /**/
   1088  1.1  jtc /************************************************************************
   1089  1.1  jtc /
   1090  1.1  jtc / FUNCTION NAME: altercoordinates()
   1091  1.1  jtc /
   1092  1.1  jtc / FUNCTION: Alter x, y coordinates and set/check location flags
   1093  1.1  jtc /
   1094  1.1  jtc / AUTHOR: E. A. Estes, 12/16/85
   1095  1.1  jtc /
   1096  1.1  jtc / ARGUMENTS:
   1097  1.1  jtc /	double xnew, ynew - new x, y coordinates
   1098  1.1  jtc /	int operation - operation to perform with coordinates
   1099  1.1  jtc /
   1100  1.1  jtc / RETURN VALUE: none
   1101  1.1  jtc /
   1102  1.1  jtc / MODULES CALLED: fabs(), floor(), drandom(), distance()
   1103  1.1  jtc /
   1104  1.1  jtc / GLOBAL INPUTS: Circle, Beyond, Player
   1105  1.1  jtc /
   1106  1.1  jtc / GLOBAL OUTPUTS: Marsh, Circle, Beyond, Throne, Player, Changed
   1107  1.1  jtc /
   1108  1.1  jtc / DESCRIPTION:
   1109  1.1  jtc /	This module is called whenever the player's coordinates are altered.
   1110  1.1  jtc /	If the player is beyond the point of no return, he/she is forced
   1111  1.1  jtc /	to stay there.
   1112  1.1  jtc /
   1113  1.1  jtc /************************************************************************/
   1114  1.1  jtc 
   1115  1.1  jtc altercoordinates(xnew, ynew, operation)
   1116  1.1  jtc double	xnew;
   1117  1.1  jtc double	ynew;
   1118  1.1  jtc int	operation;
   1119  1.1  jtc {
   1120  1.1  jtc     switch (operation)
   1121  1.1  jtc 	{
   1122  1.1  jtc 	case A_FORCED:	/* move with no checks */
   1123  1.1  jtc 	    break;
   1124  1.1  jtc 
   1125  1.1  jtc 	case A_NEAR:	/* pick random coordinates near */
   1126  1.1  jtc 	    xnew = Player.p_x + ROLL(1.0, 5.0);
   1127  1.1  jtc 	    ynew = Player.p_y - ROLL(1.0, 5.0);
   1128  1.1  jtc 	    /* fall through for check */
   1129  1.1  jtc 
   1130  1.1  jtc 	case A_SPECIFIC:	/* just move player */
   1131  1.1  jtc 	    if (Beyond && fabs(xnew) < D_BEYOND && fabs(ynew) < D_BEYOND)
   1132  1.1  jtc 		/*
   1133  1.1  jtc 		 * cannot move back from point of no return
   1134  1.1  jtc 		 * pick the largest coordinate to remain unchanged
   1135  1.1  jtc 		 */
   1136  1.1  jtc 		{
   1137  1.1  jtc 		if (fabs(xnew) > fabs(ynew))
   1138  1.1  jtc 		    xnew = SGN(Player.p_x) * MAX(fabs(Player.p_x), D_BEYOND);
   1139  1.1  jtc 		else
   1140  1.1  jtc 		    ynew = SGN(Player.p_y) * MAX(fabs(Player.p_y), D_BEYOND);
   1141  1.1  jtc 		}
   1142  1.1  jtc 	    break;
   1143  1.1  jtc 
   1144  1.1  jtc 	case A_FAR:	/* pick random coordinates far */
   1145  1.1  jtc 	    xnew = Player.p_x + SGN(Player.p_x) * ROLL(50 * Circle, 250 * Circle);
   1146  1.1  jtc 	    ynew = Player.p_y + SGN(Player.p_y) * ROLL(50 * Circle, 250 * Circle);
   1147  1.1  jtc 	    break;
   1148  1.1  jtc 	}
   1149  1.1  jtc 
   1150  1.1  jtc     /* now set location flags and adjust coordinates */
   1151  1.1  jtc     Circle = CIRCLE(Player.p_x = floor(xnew), Player.p_y = floor(ynew));
   1152  1.1  jtc 
   1153  1.1  jtc     /* set up flags based upon location */
   1154  1.1  jtc     Throne = Marsh = Beyond = FALSE;
   1155  1.1  jtc 
   1156  1.1  jtc     if (Player.p_x == 0.0 && Player.p_y == 0.0)
   1157  1.1  jtc 	Throne = TRUE;
   1158  1.1  jtc     else if (Circle < 35 && Circle >= 20)
   1159  1.1  jtc 	Marsh = TRUE;
   1160  1.1  jtc     else if (MAX(fabs(Player.p_x), fabs(Player.p_y)) >= D_BEYOND)
   1161  1.1  jtc 	Beyond = TRUE;
   1162  1.1  jtc 
   1163  1.1  jtc     Changed = TRUE;
   1164  1.1  jtc }
   1165  1.1  jtc /**/
   1167  1.1  jtc /************************************************************************
   1168  1.1  jtc /
   1169  1.1  jtc / FUNCTION NAME: readrecord()
   1170  1.1  jtc /
   1171  1.1  jtc / FUNCTION: read a player structure from file
   1172  1.1  jtc /
   1173  1.1  jtc / AUTHOR: E. A. Estes, 12/4/85
   1174  1.1  jtc /
   1175  1.1  jtc / ARGUMENTS:
   1176  1.1  jtc /	struct player *playerp - pointer to structure to fill
   1177  1.1  jtc /	int loc - location of record to read
   1178  1.1  jtc /
   1179  1.1  jtc / RETURN VALUE: none
   1180  1.1  jtc /
   1181  1.1  jtc / MODULES CALLED: fread(), fseek()
   1182  1.1  jtc /
   1183  1.1  jtc / GLOBAL INPUTS: *Playersfp
   1184  1.1  jtc /
   1185  1.1  jtc / GLOBAL OUTPUTS: none
   1186  1.1  jtc /
   1187  1.1  jtc / DESCRIPTION:
   1188  1.1  jtc /	Read structure information from player file.
   1189  1.1  jtc /
   1190  1.1  jtc /************************************************************************/
   1191  1.1  jtc 
   1192  1.1  jtc readrecord(playerp, loc)
   1193  1.1  jtc register struct player	*playerp;
   1194  1.1  jtc long	loc;
   1195  1.1  jtc {
   1196  1.1  jtc     fseek(Playersfp, loc, 0);
   1197  1.1  jtc     fread((char *) playerp, SZ_PLAYERSTRUCT, 1, Playersfp);
   1198  1.1  jtc }
   1199  1.1  jtc /**/
   1201  1.1  jtc /************************************************************************
   1202  1.1  jtc /
   1203  1.1  jtc / FUNCTION NAME: adjuststats()
   1204  1.1  jtc /
   1205  1.1  jtc / FUNCTION: adjust player statistics
   1206  1.1  jtc /
   1207  1.1  jtc / AUTHOR: E. A. Estes, 12/4/85
   1208  1.1  jtc /
   1209  1.1  jtc / ARGUMENTS: none
   1210  1.1  jtc /
   1211  1.1  jtc / RETURN VALUE: none
   1212  1.1  jtc /
   1213  1.1  jtc / MODULES CALLED: death(), floor(), drandom(), explevel(), movelevel()
   1214  1.1  jtc /
   1215  1.1  jtc / GLOBAL INPUTS: Player, *Statptr
   1216  1.1  jtc /
   1217  1.1  jtc / GLOBAL OUTPUTS: Circle, Player, Timeout
   1218  1.1  jtc /
   1219  1.1  jtc / DESCRIPTION:
   1220  1.1  jtc /	Handle adjustment and maximums on various player characteristics.
   1221  1.1  jtc /
   1222  1.1  jtc /************************************************************************/
   1223  1.1  jtc 
   1224  1.1  jtc adjuststats()
   1225  1.1  jtc {
   1226  1.1  jtc double	dtemp;				/* for temporary calculations */
   1227  1.1  jtc 
   1228  1.1  jtc     if (explevel(Player.p_experience) > Player.p_level)
   1229  1.1  jtc 	/* move one or more levels */
   1230  1.1  jtc 	{
   1231  1.1  jtc 	movelevel();
   1232  1.1  jtc 	if (Player.p_level > 5.0)
   1233  1.1  jtc 	    Timeout = TRUE;
   1234  1.1  jtc 	}
   1235  1.1  jtc 
   1236  1.1  jtc     if (Player.p_specialtype == SC_VALAR)
   1237  1.1  jtc 	/* valar */
   1238  1.1  jtc 	Circle = Player.p_level / 5.0;
   1239  1.1  jtc 
   1240  1.1  jtc     /* calculate effective quickness */
   1241  1.1  jtc     dtemp = ((Player.p_gold + Player.p_gems / 2.0) - 1000.0) / Statptr->c_goldtote
   1242  1.1  jtc 	- Player.p_level;;
   1243  1.1  jtc     dtemp = MAX(0.0, dtemp);		/* gold slows player down */
   1244  1.1  jtc     Player.p_speed = Player.p_quickness + Player.p_quksilver - dtemp;
   1245  1.1  jtc 
   1246  1.1  jtc     /* calculate effective strength */
   1247  1.1  jtc     if (Player.p_poison > 0.0)
   1248  1.1  jtc 	/* poison makes player weaker */
   1249  1.1  jtc 	{
   1250  1.1  jtc 	dtemp = 1.0 - Player.p_poison * Statptr->c_weakness / 800.0;
   1251  1.1  jtc 	dtemp = MAX(0.1, dtemp);
   1252  1.1  jtc 	}
   1253  1.1  jtc     else
   1254  1.1  jtc 	dtemp = 1.0;
   1255  1.1  jtc     Player.p_might = dtemp *  Player.p_strength + Player.p_sword;
   1256  1.1  jtc 
   1257  1.1  jtc     /* insure that important things are within limits */
   1258  1.1  jtc     Player.p_quksilver = MIN(99.0, Player.p_quksilver);
   1259  1.1  jtc     Player.p_mana = MIN(Player.p_mana,
   1260  1.1  jtc 	Player.p_level * Statptr->c_maxmana + 1000.0);
   1261  1.1  jtc     Player.p_brains = MIN(Player.p_brains,
   1262  1.1  jtc 	Player.p_level * Statptr->c_maxbrains + 200.0);
   1263  1.1  jtc     Player.p_charms = MIN(Player.p_charms, Player.p_level + 10.0);
   1264  1.1  jtc 
   1265  1.1  jtc     /*
   1266  1.1  jtc      * some implementations have problems with floating point compare
   1267  1.1  jtc      * we work around it with this stuff
   1268  1.1  jtc      */
   1269  1.1  jtc     Player.p_gold = floor(Player.p_gold) + 0.1;
   1270  1.1  jtc     Player.p_gems = floor(Player.p_gems) + 0.1;
   1271  1.1  jtc     Player.p_mana = floor(Player.p_mana) + 0.1;
   1272  1.1  jtc 
   1273  1.1  jtc     if (Player.p_ring.ring_type != R_NONE)
   1274  1.1  jtc 	/* do ring things */
   1275  1.1  jtc 	{
   1276  1.1  jtc 	/* rest to max */
   1277  1.1  jtc 	Player.p_energy = Player.p_maxenergy + Player.p_shield;
   1278  1.1  jtc 
   1279  1.1  jtc         if (Player.p_ring.ring_duration <= 0)
   1280  1.1  jtc 	    /* clean up expired rings */
   1281  1.1  jtc 	    switch (Player.p_ring.ring_type)
   1282  1.1  jtc 		{
   1283  1.1  jtc 		case R_BAD:	/* ring drives player crazy */
   1284  1.1  jtc 		    Player.p_ring.ring_type = R_SPOILED;
   1285  1.1  jtc 		    Player.p_ring.ring_duration = (short) ROLL(10.0, 25.0);
   1286  1.1  jtc 		    break;
   1287  1.1  jtc 
   1288  1.1  jtc 		case R_NAZREG:	/* ring disappears */
   1289  1.1  jtc 		    Player.p_ring.ring_type = R_NONE;
   1290  1.1  jtc 		    break;
   1291  1.1  jtc 
   1292  1.1  jtc 		case R_SPOILED:	/* ring kills player */
   1293  1.1  jtc 		    death("A cursed ring");
   1294  1.1  jtc 		    break;
   1295  1.1  jtc 
   1296  1.1  jtc 		case R_DLREG:	/* this ring doesn't expire */
   1297  1.1  jtc 		    Player.p_ring.ring_duration = 0;
   1298  1.1  jtc 		    break;
   1299  1.1  jtc 		}
   1300  1.1  jtc 	}
   1301  1.1  jtc 
   1302  1.1  jtc     if (Player.p_age / N_AGE > Player.p_degenerated)
   1303  1.1  jtc 	/* age player slightly */
   1304  1.1  jtc 	{
   1305  1.1  jtc 	++Player.p_degenerated;
   1306  1.1  jtc 	if (Player.p_quickness > 23.0)
   1307  1.1  jtc 	    Player.p_quickness *= 0.99;
   1308  1.1  jtc 	Player.p_strength *= 0.97;
   1309  1.1  jtc 	Player.p_brains *= 0.95;
   1310  1.1  jtc 	Player.p_magiclvl *= 0.97;
   1311  1.1  jtc 	Player.p_maxenergy *= 0.95;
   1312  1.1  jtc 	Player.p_quksilver *= 0.95;
   1313  1.1  jtc 	Player.p_sword *= 0.93;
   1314  1.1  jtc 	Player.p_shield *= 0.93;
   1315  1.1  jtc 	}
   1316  1.1  jtc }
   1317  1.1  jtc /**/
   1319  1.1  jtc /************************************************************************
   1320  1.1  jtc /
   1321  1.1  jtc / FUNCTION NAME: initplayer()
   1322  1.1  jtc /
   1323  1.1  jtc / FUNCTION: initialize a character
   1324  1.1  jtc /
   1325  1.1  jtc / AUTHOR: E. A. Estes, 12/4/85
   1326  1.1  jtc /
   1327  1.1  jtc / ARGUMENTS:
   1328  1.1  jtc /	struct player *playerp - pointer to structure to init
   1329  1.1  jtc /
   1330  1.1  jtc / RETURN VALUE: none
   1331  1.1  jtc /
   1332  1.1  jtc / MODULES CALLED: floor(), drandom()
   1333  1.1  jtc /
   1334  1.1  jtc / GLOBAL INPUTS: none
   1335  1.1  jtc /
   1336  1.1  jtc / GLOBAL OUTPUTS: none
   1337  1.1  jtc /
   1338  1.1  jtc / DESCRIPTION:
   1339  1.1  jtc /	Put a bunch of default values in the given structure.
   1340  1.1  jtc /
   1341  1.1  jtc /************************************************************************/
   1342  1.1  jtc 
   1343  1.1  jtc initplayer(playerp)
   1344  1.1  jtc register struct  player   *playerp;
   1345  1.1  jtc {
   1346  1.1  jtc     playerp->p_experience =
   1347  1.1  jtc     playerp->p_level =
   1348  1.1  jtc     playerp->p_strength =
   1349  1.1  jtc     playerp->p_sword =
   1350  1.1  jtc     playerp->p_might =
   1351  1.1  jtc     playerp->p_energy =
   1352  1.1  jtc     playerp->p_maxenergy =
   1353  1.1  jtc     playerp->p_shield =
   1354  1.1  jtc     playerp->p_quickness =
   1355  1.1  jtc     playerp->p_quksilver =
   1356  1.1  jtc     playerp->p_speed =
   1357  1.1  jtc     playerp->p_magiclvl =
   1358  1.1  jtc     playerp->p_mana =
   1359  1.1  jtc     playerp->p_brains =
   1360  1.1  jtc     playerp->p_poison =
   1361  1.1  jtc     playerp->p_gems =
   1362  1.1  jtc     playerp->p_sin =
   1363  1.1  jtc     playerp->p_1scratch =
   1364  1.1  jtc     playerp->p_2scratch = 0.0;
   1365  1.1  jtc 
   1366  1.1  jtc     playerp->p_gold = ROLL(50.0, 75.0) + 0.1;	/* give some gold */
   1367  1.1  jtc 
   1368  1.1  jtc     playerp->p_x = ROLL(-125.0, 251.0);
   1369  1.1  jtc     playerp->p_y = ROLL(-125.0, 251.0);		/* give random x, y */
   1370  1.1  jtc 
   1371  1.1  jtc     /* clear ring */
   1372  1.1  jtc     playerp->p_ring.ring_type = R_NONE;
   1373  1.1  jtc     playerp->p_ring.ring_duration = 0;
   1374  1.1  jtc     playerp->p_ring.ring_inuse = FALSE;
   1375  1.1  jtc 
   1376  1.1  jtc     playerp->p_age = 0L;
   1377  1.1  jtc 
   1378  1.1  jtc     playerp->p_degenerated = 1;			/* don't degenerate initially */
   1379  1.1  jtc 
   1380  1.1  jtc     playerp->p_type = C_FIGHTER;		/* default */
   1381  1.1  jtc     playerp->p_specialtype = SC_NONE;
   1382  1.1  jtc     playerp->p_lives =
   1383  1.1  jtc     playerp->p_crowns =
   1384  1.1  jtc     playerp->p_charms =
   1385  1.1  jtc     playerp->p_amulets =
   1386  1.1  jtc     playerp->p_holywater =
   1387  1.1  jtc     playerp->p_lastused = 0;
   1388  1.1  jtc     playerp->p_status = S_NOTUSED;
   1389  1.1  jtc     playerp->p_tampered = T_OFF;
   1390  1.1  jtc     playerp->p_istat = I_OFF;
   1391  1.1  jtc 
   1392  1.1  jtc     playerp->p_palantir =
   1393  1.1  jtc     playerp->p_blessing =
   1394  1.1  jtc     playerp->p_virgin =
   1395  1.1  jtc     playerp->p_blindness = FALSE;
   1396  1.1  jtc 
   1397  1.1  jtc     playerp->p_name[0] =
   1398  1.1  jtc     playerp->p_password[0] =
   1399  1.1  jtc     playerp->p_login[0] = '\0';
   1400  1.1  jtc }
   1401  1.1  jtc /**/
   1403  1.1  jtc /************************************************************************
   1404  1.1  jtc /
   1405  1.1  jtc / FUNCTION NAME: readmessage()
   1406  1.1  jtc /
   1407  1.1  jtc / FUNCTION: read message from other players
   1408  1.1  jtc /
   1409  1.1  jtc / AUTHOR: E. A. Estes, 12/4/85
   1410  1.1  jtc /
   1411  1.1  jtc / ARGUMENTS: none
   1412  1.1  jtc /
   1413  1.1  jtc / RETURN VALUE: none
   1414  1.1  jtc /
   1415  1.1  jtc / MODULES CALLED: fseek(), fgets(), wmove(), waddstr(), wclrtoeol()
   1416  1.1  jtc /
   1417  1.1  jtc / GLOBAL INPUTS: *stdscr, Databuf[], *Messagefp
   1418  1.1  jtc /
   1419  1.1  jtc / GLOBAL OUTPUTS: none
   1420  1.1  jtc /
   1421  1.1  jtc / DESCRIPTION:
   1422  1.1  jtc /	If there is a message from other players, print it.
   1423  1.1  jtc /
   1424  1.1  jtc /************************************************************************/
   1425  1.1  jtc 
   1426  1.1  jtc readmessage()
   1427  1.1  jtc {
   1428  1.1  jtc     move(3, 0);
   1429  1.1  jtc     clrtoeol();
   1430  1.1  jtc     fseek(Messagefp, 0L, 0);
   1431  1.1  jtc     if (fgets(Databuf, SZ_DATABUF, Messagefp) != NULL)
   1432  1.1  jtc 	addstr(Databuf);
   1433  1.1  jtc }
   1434  1.1  jtc /**/
   1436  1.1  jtc /************************************************************************
   1437  1.1  jtc /
   1438  1.1  jtc / FUNCTION NAME: error()
   1439  1.1  jtc /
   1440  1.1  jtc / FUNCTION: process evironment error
   1441  1.1  jtc /
   1442  1.1  jtc / AUTHOR: E. A. Estes, 12/4/85
   1443  1.1  jtc /
   1444  1.1  jtc / ARGUMENTS:
   1445  1.1  jtc /	char *whichfile - pointer to name of file which caused error
   1446  1.1  jtc /
   1447  1.1  jtc / RETURN VALUE: none
   1448  1.1  jtc /
   1449  1.1  jtc / MODULES CALLED: wclear(), cleanup()
   1450  1.1  jtc /
   1451  1.1  jtc / GLOBAL INPUTS: errno, *stdscr, printw(), printf(), Windows
   1452  1.1  jtc /
   1453  1.1  jtc / GLOBAL OUTPUTS: none
   1454  1.1  jtc /
   1455  1.1  jtc / DESCRIPTION:
   1456  1.1  jtc /	Print message about offending file, and exit.
   1457  1.1  jtc /
   1458  1.1  jtc /************************************************************************/
   1459  1.1  jtc 
   1460  1.1  jtc error(whichfile)
   1461  1.1  jtc 	char	*whichfile;
   1462  1.1  jtc {
   1463  1.1  jtc 	int	(*funcp) __P((const char *, ...));
   1464  1.1  jtc 
   1465  1.1  jtc     if (Windows)
   1466  1.1  jtc 	{
   1467  1.1  jtc 	funcp = printw;
   1468  1.1  jtc 	clear();
   1469  1.1  jtc 	}
   1470  1.1  jtc     else
   1471  1.1  jtc 	funcp = printf;
   1472  1.1  jtc 
   1473  1.1  jtc     (*funcp)("An unrecoverable error has occurred reading %s.  (errno = %d)\n", whichfile, errno);
   1474  1.1  jtc     (*funcp)("Please run 'setup' to determine the problem.\n");
   1475  1.1  jtc     cleanup(TRUE);
   1476  1.1  jtc     /*NOTREACHED*/
   1477  1.1  jtc }
   1478  1.1  jtc /**/
   1480  1.1  jtc /************************************************************************
   1481  1.1  jtc /
   1482  1.1  jtc / FUNCTION NAME: distance()
   1483  1.1  jtc /
   1484  1.1  jtc / FUNCTION: calculate distance between two points
   1485  1.1  jtc /
   1486  1.1  jtc / AUTHOR: E. A. Estes, 12/4/85
   1487  1.1  jtc /
   1488  1.1  jtc / ARGUMENTS:
   1489  1.1  jtc /	double x1, y1 - x, y coordinates of first point
   1490  1.1  jtc /	double x2, y2 - x, y coordinates of second point
   1491  1.1  jtc /
   1492  1.1  jtc / RETURN VALUE: distance between the two points
   1493  1.1  jtc /
   1494  1.1  jtc / MODULES CALLED: sqrt()
   1495  1.1  jtc /
   1496  1.1  jtc / GLOBAL INPUTS: none
   1497  1.1  jtc /
   1498  1.1  jtc / GLOBAL OUTPUTS: none
   1499  1.1  jtc /
   1500  1.1  jtc / DESCRIPTION:
   1501  1.1  jtc /	This function is provided because someone's hypot() library function
   1502  1.1  jtc /	fails if x1 == x2 && y1 == y2.
   1503  1.1  jtc /
   1504  1.1  jtc /************************************************************************/
   1505  1.1  jtc 
   1506  1.1  jtc double
   1507  1.1  jtc distance(x1, x2, y1, y2)
   1508  1.1  jtc double	x1, x2, y1, y2;
   1509  1.1  jtc {
   1510  1.1  jtc double	deltax, deltay;
   1511  1.1  jtc 
   1512  1.1  jtc     deltax = x1 - x2;
   1513  1.1  jtc     deltay = y1 - y2;
   1514  1.1  jtc     return(sqrt(deltax * deltax + deltay * deltay));
   1515  1.1  jtc }
   1516  1.1  jtc 
   1517  1.1  jtc /**/
   1519  1.1  jtc /************************************************************************
   1520  1.1  jtc /
   1521  1.1  jtc / FUNCTION NAME: ill_sig()
   1522  1.1  jtc /
   1523  1.1  jtc / FUNCTION: exit upon trapping an illegal signal
   1524  1.1  jtc /
   1525  1.1  jtc / AUTHOR: E. A. Estes, 12/4/85
   1526  1.1  jtc /
   1527  1.1  jtc / ARGUMENTS:
   1528  1.1  jtc /	int whichsig - signal which occured to cause jump to here
   1529  1.1  jtc /
   1530  1.1  jtc / RETURN VALUE: none
   1531  1.1  jtc /
   1532  1.1  jtc / MODULES CALLED: wclear(), printw(), cleanup()
   1533  1.1  jtc /
   1534  1.1  jtc / GLOBAL INPUTS: *stdscr
   1535  1.1  jtc /
   1536  1.1  jtc / GLOBAL OUTPUTS: none
   1537  1.1  jtc /
   1538  1.1  jtc / DESCRIPTION:
   1539  1.1  jtc /	When an illegal signal is caught, print a message, and cleanup.
   1540  1.1  jtc /
   1541  1.1  jtc /************************************************************************/
   1542  1.1  jtc 
   1543  1.1  jtc ill_sig(whichsig)
   1544  1.1  jtc int whichsig;
   1545  1.1  jtc {
   1546  1.1  jtc     clear();
   1547  1.1  jtc     if (!(whichsig == SIGINT || whichsig == SIGQUIT))
   1548  1.1  jtc 	printw("Error: caught signal # %d.\n", whichsig);
   1549  1.1  jtc     cleanup(TRUE);
   1550  1.1  jtc     /*NOTREACHED*/
   1551  1.1  jtc }
   1552  1.1  jtc /**/
   1554  1.1  jtc /************************************************************************
   1555  1.1  jtc /
   1556  1.1  jtc / FUNCTION NAME: descrstatus()
   1557  1.1  jtc /
   1558  1.1  jtc / FUNCTION: return a string describing the player status
   1559  1.1  jtc /
   1560  1.1  jtc / AUTHOR: E. A. Estes, 3/3/86
   1561  1.1  jtc /
   1562  1.1  jtc / ARGUMENTS:
   1563  1.1  jtc /	struct player playerp - pointer to player structure to describe
   1564  1.1  jtc /
   1565  1.1  jtc / RETURN VALUE: string describing player's status
   1566  1.1  jtc /
   1567  1.1  jtc / MODULES CALLED: none
   1568  1.1  jtc /
   1569  1.1  jtc / GLOBAL INPUTS: none
   1570  1.1  jtc /
   1571  1.1  jtc / GLOBAL OUTPUTS: none
   1572  1.1  jtc /
   1573  1.1  jtc / DESCRIPTION:
   1574  1.1  jtc /	Return verbal description of player status.
   1575  1.1  jtc /	If player status is S_PLAYING, check for low energy and blindness.
   1576  1.1  jtc /
   1577  1.1  jtc /************************************************************************/
   1578  1.1  jtc 
   1579  1.1  jtc char	*
   1580  1.1  jtc descrstatus(playerp)
   1581  1.1  jtc register struct player	*playerp;
   1582  1.1  jtc {
   1583  1.1  jtc     switch (playerp->p_status)
   1584  1.1  jtc 	{
   1585  1.1  jtc 	case S_PLAYING:
   1586  1.1  jtc 	    if (playerp->p_energy < 0.2 * (playerp->p_maxenergy + playerp->p_shield))
   1587  1.1  jtc 		return("Low Energy");
   1588  1.1  jtc 	    else if (playerp->p_blindness)
   1589  1.1  jtc 		return("Blind");
   1590  1.1  jtc 	    else
   1591  1.1  jtc 		return("In game");
   1592  1.1  jtc 
   1593  1.1  jtc 	case S_CLOAKED:
   1594  1.1  jtc 	    return("Cloaked");
   1595  1.1  jtc 
   1596  1.1  jtc 	case S_INBATTLE:
   1597  1.1  jtc 	    return("In Battle");
   1598  1.1  jtc 
   1599  1.1  jtc 	case S_MONSTER:
   1600  1.1  jtc 	    return("Encounter");
   1601  1.1  jtc 
   1602  1.1  jtc 	case S_TRADING:
   1603  1.1  jtc 	    return("Trading");
   1604  1.1  jtc 
   1605  1.1  jtc 	case S_OFF:
   1606  1.1  jtc 	    return("Off");
   1607  1.1  jtc 
   1608  1.1  jtc 	case S_HUNGUP:
   1609  1.1  jtc 	    return("Hung up");
   1610  1.1  jtc 
   1611  1.1  jtc 	default:
   1612  1.1  jtc 	    return("");
   1613  1.1  jtc 	}
   1614  1.1  jtc }
   1615  1.1  jtc /**/
   1617  1.1  jtc /************************************************************************
   1618  1.1  jtc /
   1619  1.1  jtc / FUNCTION NAME: drandom()
   1620  1.1  jtc /
   1621  1.1  jtc / FUNCTION: return a random floating point number from 0.0 < 1.0
   1622  1.1  jtc /
   1623  1.1  jtc / AUTHOR: E. A. Estes, 2/7/86
   1624  1.1  jtc /
   1625  1.1  jtc / ARGUMENTS: none
   1626  1.1  jtc /
   1627  1.1  jtc / RETURN VALUE: none
   1628  1.1  jtc /
   1629  1.1  jtc / MODULES CALLED: random()
   1630  1.1  jtc /
   1631  1.1  jtc / GLOBAL INPUTS: none
   1632  1.1  jtc /
   1633  1.1  jtc / GLOBAL OUTPUTS: none
   1634  1.1  jtc /
   1635  1.1  jtc / DESCRIPTION:
   1636  1.1  jtc /	Convert random integer from library routine into a floating
   1637  1.1  jtc /	point number, and divide by the largest possible random number.
   1638  1.1  jtc /	We mask large integers with 32767 to handle sites that return
   1639  1.1  jtc /	31 bit random integers.
   1640  1.1  jtc /
   1641  1.1  jtc /************************************************************************/
   1642  1.1  jtc 
   1643  1.1  jtc double
   1644  1.1  jtc drandom()
   1645  1.1  jtc {
   1646  1.1  jtc     if (sizeof(int) != 2)
   1647  1.1  jtc 	/* use only low bits */
   1648  1.1  jtc 	return((double) (random() & 0x7fff) / 32768.0);
   1649  1.1  jtc     else
   1650  1.1  jtc 	return((double) random() / 32768.0);
   1651  1.1  jtc }
   1652  1.1  jtc /**/
   1654  1.1  jtc /************************************************************************
   1655  1.1  jtc /
   1656  1.1  jtc / FUNCTION NAME: collecttaxes()
   1657  1.1  jtc /
   1658  1.1  jtc / FUNCTION: collect taxes from current player
   1659  1.1  jtc /
   1660  1.1  jtc / AUTHOR: E. A. Estes, 2/7/86
   1661  1.1  jtc /
   1662  1.1  jtc / ARGUMENTS:
   1663  1.1  jtc /	double gold - amount of gold to tax
   1664  1.1  jtc /	double gems - amount of gems to tax
   1665  1.1  jtc /
   1666  1.1  jtc / RETURN VALUE: none
   1667  1.1  jtc /
   1668  1.1  jtc / MODULES CALLED: fread(), fseek(), fopen(), floor(), fwrite(), fclose()
   1669  1.1  jtc /
   1670  1.1  jtc / GLOBAL INPUTS: Player
   1671  1.1  jtc /
   1672  1.1  jtc / GLOBAL OUTPUTS: Player
   1673  1.1  jtc /
   1674  1.1  jtc / DESCRIPTION:
   1675  1.1  jtc /	Pay taxes on gold and gems.  If the player does not have enough
   1676  1.1  jtc /	gold to pay taxes on the added gems, convert some gems to gold.
   1677  1.1  jtc /	Add taxes to tax data base; add remaining gold and gems to
   1678  1.1  jtc /	player's cache.
   1679  1.1  jtc /
   1680  1.1  jtc /************************************************************************/
   1681  1.1  jtc 
   1682  1.1  jtc collecttaxes(gold, gems)
   1683  1.1  jtc double	gold;
   1684  1.1  jtc double	gems;
   1685  1.1  jtc {
   1686  1.1  jtc FILE	*fp;		/* to update Goldfile */
   1687  1.1  jtc double	dtemp;		/* for temporary calculations */
   1688  1.1  jtc double	taxes;		/* tax liability */
   1689  1.1  jtc 
   1690  1.1  jtc     /* add to cache */
   1691  1.1  jtc     Player.p_gold += gold;
   1692  1.1  jtc     Player.p_gems += gems;
   1693  1.1  jtc 
   1694  1.1  jtc     /* calculate tax liability */
   1695  1.1  jtc     taxes = N_TAXAMOUNT / 100.0 * (N_GEMVALUE * gems + gold);
   1696  1.1  jtc 
   1697  1.1  jtc     if (Player.p_gold < taxes)
   1698  1.1  jtc 	/* not enough gold to pay taxes, must convert some gems to gold */
   1699  1.1  jtc 	{
   1700  1.1  jtc 	dtemp = floor(taxes / N_GEMVALUE + 1.0); /* number of gems to convert */
   1701  1.1  jtc 
   1702  1.1  jtc 	if (Player.p_gems >= dtemp)
   1703  1.1  jtc 	    /* player has enough to convert */
   1704  1.1  jtc 	    {
   1705  1.1  jtc 	    Player.p_gems -= dtemp;
   1706           	    Player.p_gold += dtemp * N_GEMVALUE;
   1707           	    }
   1708           	else
   1709           	    /* take everything; this should never happen */
   1710           	    {
   1711           	    Player.p_gold += Player.p_gems * N_GEMVALUE;
   1712           	    Player.p_gems = 0.0;
   1713           	    taxes = Player.p_gold;
   1714           	    }
   1715           	}
   1716           
   1717               Player.p_gold -= taxes;
   1718           
   1719               if ((fp = fopen(_PATH_GOLD, "r+")) != NULL)
   1720           	/* update taxes */
   1721           	{
   1722           	dtemp = 0.0;
   1723           	fread((char *) &dtemp, sizeof(double), 1, fp);
   1724           	dtemp += floor(taxes);
   1725           	fseek(fp, 0L, 0);
   1726           	fwrite((char *) &dtemp, sizeof(double), 1, fp);
   1727           	fclose(fp);
   1728           	}
   1729           }
   1730