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