main.c revision 1.23       1  1.23  dholland /*	$NetBSD: main.c,v 1.23 2009/08/31 08:27:16 dholland Exp $	*/
      2   1.2       cgd 
      3   1.1       jtc /*
      4   1.1       jtc  * Phantasia 3.3.2 -- Interterminal fantasy game
      5   1.1       jtc  *
      6   1.1       jtc  * Edward A. Estes
      7   1.1       jtc  * AT&T, March 12, 1986
      8   1.1       jtc  */
      9   1.1       jtc 
     10   1.1       jtc /* DISCLAIMER:
     11   1.1       jtc  *
     12   1.1       jtc  * This game is distributed for free as is.  It is not guaranteed to work
     13   1.1       jtc  * in every conceivable environment.  It is not even guaranteed to work
     14   1.1       jtc  * in ANY environment.
     15   1.1       jtc  *
     16   1.1       jtc  * This game is distributed without notice of copyright, therefore it
     17   1.1       jtc  * may be used in any manner the recipient sees fit.  However, the
     18   1.1       jtc  * author assumes no responsibility for maintaining or revising this
     19   1.1       jtc  * game, in its original form, or any derivitives thereof.
     20   1.1       jtc  *
     21   1.1       jtc  * The author shall not be responsible for any loss, cost, or damage,
     22   1.1       jtc  * including consequential damage, caused by reliance on this material.
     23   1.1       jtc  *
     24   1.1       jtc  * The author makes no warranties, express or implied, including warranties
     25   1.1       jtc  * of merchantability or fitness for a particular purpose or use.
     26   1.1       jtc  *
     27   1.1       jtc  * AT&T is in no way connected with this game.
     28   1.1       jtc  */
     29   1.1       jtc 
     30  1.23  dholland #include <sys/types.h>
     31  1.15       jmc #include <sys/stat.h>
     32  1.20  dholland #include <err.h>
     33  1.23  dholland #include <math.h>
     34   1.1       jtc #include <pwd.h>
     35  1.23  dholland #include <setjmp.h>
     36  1.23  dholland #include <stdio.h>
     37  1.23  dholland #include <stdlib.h>
     38  1.23  dholland #include <string.h>
     39  1.23  dholland #include <unistd.h>
     40  1.23  dholland 
     41  1.23  dholland #include "macros.h"
     42  1.23  dholland #include "phantdefs.h"
     43  1.23  dholland #include "phantstruct.h"
     44  1.23  dholland #include "phantglobs.h"
     45  1.23  dholland #include "pathnames.h"
     46  1.23  dholland 
     47  1.23  dholland #undef bool
     48  1.23  dholland #include <curses.h>
     49   1.1       jtc 
     50   1.1       jtc /*
     51   1.1       jtc  * The program allocates as much file space as it needs to store characters,
     52   1.1       jtc  * so the possibility exists for the character file to grow without bound.
     53   1.1       jtc  * The file is purged upon normal entry to try to avoid that problem.
     54   1.1       jtc  * A similar problem exists for energy voids.  To alleviate the problem here,
     55   1.1       jtc  * the void file is cleared with every new king, and a limit is placed
     56   1.1       jtc  * on the size of the energy void file.
     57   1.1       jtc  */
     58   1.1       jtc 
     59   1.1       jtc /*
     60   1.1       jtc  * Put one line of text into the file 'motd' for announcements, etc.
     61   1.1       jtc  */
     62   1.1       jtc 
     63   1.1       jtc /*
     64   1.1       jtc  * The scoreboard file is updated when someone dies, and keeps track
     65   1.1       jtc  * of the highest character to date for that login.
     66   1.1       jtc  * Being purged from the character file does not cause the scoreboard
     67   1.1       jtc  * to be updated.
     68   1.1       jtc  */
     69   1.1       jtc 
     70   1.1       jtc 
     71   1.1       jtc /*
     72   1.1       jtc  * main.c	Main routines for Phantasia
     73   1.1       jtc  */
     74   1.1       jtc 
     75  1.22  dholland static void genchar(int);
     76  1.22  dholland static void initialstate(void);
     77  1.22  dholland static void neatstuff(void);
     78  1.22  dholland static void playinit(void);
     79  1.22  dholland static void procmain(void);
     80  1.22  dholland static long recallplayer(void);
     81  1.22  dholland static long rollnewplayer(void);
     82  1.22  dholland static void titlelist(void);
     83  1.22  dholland 
     84  1.11       wiz int	main(int, char **);
     85   1.1       jtc 
     86   1.4     lukem int
     87  1.18  dholland main(int argc, char **argv)
     88   1.1       jtc {
     89   1.4     lukem 	bool    noheader = FALSE;	/* set if don't want header */
     90   1.4     lukem 	bool    headeronly = FALSE;	/* set if only want header */
     91   1.4     lukem 	bool    examine = FALSE;	/* set if examine a character */
     92   1.4     lukem 	time_t  seconds;		/* for time of day */
     93   1.4     lukem 	double  dtemp;			/* for temporary calculations */
     94   1.4     lukem 
     95   1.4     lukem 	initialstate();			/* init globals */
     96   1.4     lukem 
     97   1.4     lukem 	/* process arguments */
     98   1.4     lukem 	while (--argc && (*++argv)[0] == '-')
     99   1.4     lukem 		switch ((*argv)[1]) {
    100   1.4     lukem 		case 's':	/* short */
    101   1.4     lukem 			noheader = TRUE;
    102   1.4     lukem 			break;
    103   1.4     lukem 
    104   1.4     lukem 		case 'H':	/* Header */
    105   1.4     lukem 			headeronly = TRUE;
    106   1.4     lukem 			break;
    107   1.1       jtc 
    108   1.4     lukem 		case 'a':	/* all users */
    109   1.4     lukem 			activelist();
    110   1.4     lukem 			cleanup(TRUE);
    111   1.4     lukem 			/* NOTREACHED */
    112   1.4     lukem 
    113   1.4     lukem 		case 'p':	/* purge old players */
    114   1.4     lukem 			purgeoldplayers();
    115   1.4     lukem 			cleanup(TRUE);
    116   1.4     lukem 			/* NOTREACHED */
    117   1.1       jtc 
    118   1.4     lukem 		case 'S':	/* set 'Wizard' */
    119   1.4     lukem 			Wizard = !getuid();
    120   1.4     lukem 			break;
    121   1.4     lukem 
    122   1.4     lukem 		case 'x':	/* examine */
    123   1.4     lukem 			examine = TRUE;
    124   1.4     lukem 			break;
    125   1.1       jtc 
    126   1.4     lukem 		case 'm':	/* monsters */
    127   1.4     lukem 			monstlist();
    128   1.4     lukem 			cleanup(TRUE);
    129   1.4     lukem 			/* NOTREACHED */
    130   1.1       jtc 
    131   1.4     lukem 		case 'b':	/* scoreboard */
    132   1.4     lukem 			scorelist();
    133   1.4     lukem 			cleanup(TRUE);
    134   1.4     lukem 			/* NOTREACHED */
    135   1.4     lukem 		}
    136   1.1       jtc 
    137   1.4     lukem 	if (!isatty(0))		/* don't let non-tty's play */
    138   1.1       jtc 		cleanup(TRUE);
    139   1.4     lukem 	/* NOTREACHED */
    140   1.1       jtc 
    141   1.4     lukem 	playinit();		/* set up to catch signals, init curses */
    142   1.1       jtc 
    143   1.4     lukem 	if (examine) {
    144   1.4     lukem 		changestats(FALSE);
    145   1.1       jtc 		cleanup(TRUE);
    146   1.4     lukem 		/* NOTREACHED */
    147   1.1       jtc 	}
    148   1.4     lukem 	if (!noheader) {
    149   1.4     lukem 		titlelist();
    150   1.4     lukem 		purgeoldplayers();	/* clean up old characters */
    151   1.1       jtc 	}
    152   1.4     lukem 	if (headeronly)
    153   1.4     lukem 		cleanup(TRUE);
    154   1.4     lukem 	/* NOTREACHED */
    155   1.1       jtc 
    156   1.4     lukem 	do
    157   1.4     lukem 		/* get the player structure filled */
    158   1.1       jtc 	{
    159   1.4     lukem 		Fileloc = -1L;
    160   1.1       jtc 
    161   1.4     lukem 		mvaddstr(22, 17, "Do you have a character to run [Q = Quit] ? ");
    162   1.1       jtc 
    163   1.4     lukem 		switch (getanswer("NYQ", FALSE)) {
    164   1.4     lukem 		case 'Y':
    165   1.4     lukem 			Fileloc = recallplayer();
    166   1.4     lukem 			break;
    167   1.1       jtc 
    168   1.4     lukem 		case 'Q':
    169   1.4     lukem 			cleanup(TRUE);
    170   1.4     lukem 			/* NOTREACHED */
    171   1.1       jtc 
    172   1.4     lukem 		default:
    173   1.4     lukem 			Fileloc = rollnewplayer();
    174   1.4     lukem 			break;
    175   1.4     lukem 		}
    176   1.4     lukem 		clear();
    177   1.1       jtc 	}
    178   1.4     lukem 	while (Fileloc < 0L);
    179   1.1       jtc 
    180   1.4     lukem 	if (Player.p_level > 5.0)
    181   1.4     lukem 		/* low level players have long timeout */
    182   1.4     lukem 		Timeout = TRUE;
    183   1.4     lukem 
    184   1.4     lukem 	/* update some important player statistics */
    185  1.21  dholland 	strlcpy(Player.p_login, Login, sizeof(Player.p_login));
    186   1.4     lukem 	time(&seconds);
    187   1.4     lukem 	Player.p_lastused = localtime(&seconds)->tm_yday;
    188   1.4     lukem 	Player.p_status = S_PLAYING;
    189   1.4     lukem 	writerecord(&Player, Fileloc);
    190   1.1       jtc 
    191   1.4     lukem 	Statptr = &Stattable[Player.p_type];	/* initialize pointer */
    192   1.1       jtc 
    193   1.4     lukem 	/* catch interrupts */
    194   1.1       jtc #ifdef	BSD41
    195   1.4     lukem 	sigset(SIGINT, interrupt);
    196   1.1       jtc #endif
    197   1.1       jtc #ifdef	BSD42
    198   1.4     lukem 	signal(SIGINT, interrupt);
    199   1.1       jtc #endif
    200   1.1       jtc #ifdef	SYS3
    201   1.4     lukem 	signal(SIGINT, interrupt);
    202   1.1       jtc #endif
    203   1.1       jtc #ifdef	SYS5
    204   1.4     lukem 	signal(SIGINT, interrupt);
    205   1.1       jtc #endif
    206   1.1       jtc 
    207   1.4     lukem 	altercoordinates(Player.p_x, Player.p_y, A_FORCED);	/* set some flags */
    208   1.1       jtc 
    209   1.4     lukem 	clear();
    210   1.1       jtc 
    211   1.4     lukem 	for (;;)
    212   1.4     lukem 		/* loop forever, processing input */
    213   1.1       jtc 	{
    214   1.1       jtc 
    215   1.4     lukem 		adjuststats();	/* cleanup stats */
    216   1.4     lukem 
    217   1.4     lukem 		if (Throne && Player.p_crowns == 0 && Player.p_specialtype != SC_KING)
    218   1.4     lukem 			/* not allowed on throne -- move */
    219   1.4     lukem 		{
    220   1.4     lukem 			mvaddstr(5, 0, "You're not allowed in the Lord's Chamber without a crown.\n");
    221   1.4     lukem 			altercoordinates(0.0, 0.0, A_NEAR);
    222   1.4     lukem 		}
    223   1.4     lukem 		checktampered();/* check for energy voids, etc. */
    224   1.1       jtc 
    225   1.4     lukem 		if (Player.p_status != S_CLOAKED
    226   1.4     lukem 		/* not cloaked */
    227   1.4     lukem 		    && (dtemp = fabs(Player.p_x)) == fabs(Player.p_y)
    228   1.4     lukem 		/* |x| = |y| */
    229   1.4     lukem 		    && !Throne)
    230   1.4     lukem 			/* not on throne */
    231   1.1       jtc 		{
    232   1.4     lukem 			dtemp = sqrt(dtemp / 100.0);
    233   1.4     lukem 			if (floor(dtemp) == dtemp)
    234   1.4     lukem 				/* |x| / 100 == n*n; at a trading post */
    235   1.4     lukem 			{
    236   1.4     lukem 				tradingpost();
    237   1.4     lukem 				clear();
    238   1.4     lukem 			}
    239   1.1       jtc 		}
    240   1.4     lukem 		checkbattle();	/* check for player to player battle */
    241   1.4     lukem 		neatstuff();	/* gurus, medics, etc. */
    242   1.1       jtc 
    243   1.5     veego 		if (Player.p_status == S_CLOAKED) {
    244   1.4     lukem 			/* costs 3 mana per turn to be cloaked */
    245   1.4     lukem 			if (Player.p_mana > 3.0)
    246   1.4     lukem 				Player.p_mana -= 3.0;
    247   1.4     lukem 			else
    248   1.4     lukem 				/* ran out of mana, uncloak */
    249   1.4     lukem 			{
    250   1.4     lukem 				Player.p_status = S_PLAYING;
    251   1.4     lukem 				Changed = TRUE;
    252   1.4     lukem 			}
    253   1.5     veego 		}
    254   1.1       jtc 
    255   1.4     lukem 		if (Player.p_status != S_PLAYING && Player.p_status != S_CLOAKED)
    256   1.4     lukem 			/* change status back to S_PLAYING */
    257   1.1       jtc 		{
    258   1.4     lukem 			Player.p_status = S_PLAYING;
    259   1.4     lukem 			Changed = TRUE;
    260   1.1       jtc 		}
    261   1.4     lukem 		if (Changed)
    262   1.4     lukem 			/* update file only if important stuff has changed */
    263   1.4     lukem 		{
    264   1.4     lukem 			writerecord(&Player, Fileloc);
    265   1.4     lukem 			Changed = FALSE;
    266   1.4     lukem 			continue;
    267   1.4     lukem 		}
    268   1.4     lukem 		readmessage();	/* read message, if any */
    269   1.4     lukem 
    270   1.4     lukem 		displaystats();	/* print statistics */
    271   1.1       jtc 
    272   1.4     lukem 		move(6, 0);
    273   1.1       jtc 
    274   1.4     lukem 		if (Throne)
    275   1.4     lukem 			/* maybe make king, print prompt, etc. */
    276   1.4     lukem 			throneroom();
    277   1.4     lukem 
    278   1.4     lukem 		/* print status line */
    279   1.4     lukem 		addstr("1:Move  2:Players  3:Talk  4:Stats  5:Quit  ");
    280   1.4     lukem 		if (Player.p_level >= MEL_CLOAK && Player.p_magiclvl >= ML_CLOAK)
    281   1.4     lukem 			addstr("6:Cloak  ");
    282   1.4     lukem 		if (Player.p_level >= MEL_TELEPORT && Player.p_magiclvl >= ML_TELEPORT)
    283   1.4     lukem 			addstr("7:Teleport  ");
    284   1.4     lukem 		if (Player.p_specialtype >= SC_COUNCIL || Wizard)
    285   1.4     lukem 			addstr("8:Intervene  ");
    286   1.4     lukem 
    287   1.4     lukem 		procmain();	/* process input */
    288   1.1       jtc 	}
    289   1.1       jtc }
    290   1.1       jtc 
    291  1.22  dholland static void
    292  1.18  dholland initialstate(void)
    293   1.1       jtc {
    294  1.15       jmc 	struct stat sb;
    295  1.20  dholland 	struct passwd *pw;
    296  1.15       jmc 
    297   1.4     lukem 	Beyond = FALSE;
    298   1.4     lukem 	Marsh = FALSE;
    299   1.4     lukem 	Throne = FALSE;
    300   1.4     lukem 	Changed = FALSE;
    301   1.4     lukem 	Wizard = FALSE;
    302   1.4     lukem 	Timeout = FALSE;
    303   1.4     lukem 	Users = 0;
    304   1.4     lukem 	Windows = FALSE;
    305   1.4     lukem 	Echo = TRUE;
    306   1.1       jtc 
    307   1.4     lukem 	/* setup login name */
    308  1.20  dholland 	if ((Login = getlogin()) == NULL) {
    309  1.20  dholland 		pw = getpwuid(getuid());
    310  1.20  dholland 		if (pw == NULL) {
    311  1.20  dholland 			errx(1, "Who are you?");
    312  1.20  dholland 		}
    313  1.20  dholland 		Login = pw->pw_name;
    314  1.20  dholland 	}
    315   1.4     lukem 
    316   1.4     lukem 	/* open some files */
    317   1.4     lukem 	if ((Playersfp = fopen(_PATH_PEOPLE, "r+")) == NULL)
    318   1.4     lukem 		error(_PATH_PEOPLE);
    319   1.4     lukem 	/* NOTREACHED */
    320   1.9       jsm 	if (fileno(Playersfp) < 3)
    321   1.9       jsm 		exit(1);
    322   1.4     lukem 
    323   1.4     lukem 	if ((Monstfp = fopen(_PATH_MONST, "r+")) == NULL)
    324   1.4     lukem 		error(_PATH_MONST);
    325   1.4     lukem 	/* NOTREACHED */
    326   1.4     lukem 
    327   1.4     lukem 	if ((Messagefp = fopen(_PATH_MESS, "r")) == NULL)
    328   1.4     lukem 		error(_PATH_MESS);
    329   1.4     lukem 	/* NOTREACHED */
    330   1.4     lukem 
    331   1.4     lukem 	if ((Energyvoidfp = fopen(_PATH_VOID, "r+")) == NULL)
    332   1.4     lukem 		error(_PATH_VOID);
    333  1.15       jmc 	if (fstat(fileno(Energyvoidfp), &sb) == -1)
    334  1.15       jmc 		error("stat");
    335  1.15       jmc 	if (sb.st_size == 0) {
    336  1.15       jmc 		/* initialize grail to new location */
    337  1.15       jmc 		Enrgyvoid.ev_active = TRUE;
    338  1.15       jmc 		Enrgyvoid.ev_x = ROLL(-1.0e6, 2.0e6);
    339  1.15       jmc 		Enrgyvoid.ev_y = ROLL(-1.0e6, 2.0e6);
    340  1.15       jmc 		writevoid(&Enrgyvoid, 0L);
    341  1.15       jmc 	}
    342  1.15       jmc 
    343   1.4     lukem 	/* NOTREACHED */
    344   1.4     lukem 
    345   1.4     lukem 	srandom((unsigned) time(NULL));	/* prime random numbers */
    346   1.1       jtc }
    347   1.1       jtc 
    348  1.22  dholland static long
    349  1.18  dholland rollnewplayer(void)
    350   1.1       jtc {
    351   1.4     lukem 	int     chartype;	/* character type */
    352   1.4     lukem 	int     ch;		/* input */
    353   1.1       jtc 
    354   1.4     lukem 	initplayer(&Player);	/* initialize player structure */
    355   1.1       jtc 
    356   1.4     lukem 	clear();
    357   1.4     lukem 	mvaddstr(4, 21, "Which type of character do you want:");
    358   1.4     lukem 	mvaddstr(8, 4,
    359   1.4     lukem "1:Magic User  2:Fighter  3:Elf  4:Dwarf  5:Halfling  6:Experimento  ");
    360   1.4     lukem 	if (Wizard) {
    361   1.4     lukem 		addstr("7:Super  ? ");
    362   1.4     lukem 		chartype = getanswer("1234567", FALSE);
    363   1.4     lukem 	} else {
    364   1.4     lukem 		addstr("?  ");
    365   1.4     lukem 		chartype = getanswer("123456", FALSE);
    366   1.4     lukem 	}
    367   1.4     lukem 
    368   1.4     lukem 	do {
    369   1.4     lukem 		genchar(chartype);	/* roll up a character */
    370   1.4     lukem 
    371   1.4     lukem 		/* print out results */
    372   1.4     lukem 		mvprintw(12, 14,
    373   1.4     lukem 		    "Strength    :  %2.0f  Quickness:  %2.0f  Mana       :  %2.0f\n",
    374   1.4     lukem 		    Player.p_strength, Player.p_quickness, Player.p_mana);
    375   1.4     lukem 		mvprintw(13, 14,
    376   1.4     lukem 		    "Energy Level:  %2.0f  Brains   :  %2.0f  Magic Level:  %2.0f\n",
    377   1.4     lukem 		    Player.p_energy, Player.p_brains, Player.p_magiclvl);
    378   1.1       jtc 
    379   1.4     lukem 		if (Player.p_type == C_EXPER || Player.p_type == C_SUPER)
    380   1.4     lukem 			break;
    381   1.1       jtc 
    382   1.4     lukem 		mvaddstr(14, 14, "Type '1' to keep >");
    383   1.4     lukem 		ch = getanswer(" ", TRUE);
    384   1.4     lukem 	}
    385   1.4     lukem 	while (ch != '1');
    386   1.1       jtc 
    387   1.1       jtc 	if (Player.p_type == C_EXPER || Player.p_type == C_SUPER)
    388   1.4     lukem 		/* get coordinates for experimento */
    389   1.4     lukem 		for (;;) {
    390   1.4     lukem 			mvaddstr(16, 0, "Enter the X Y coordinates of your experimento ? ");
    391   1.4     lukem 			getstring(Databuf, SZ_DATABUF);
    392   1.4     lukem 			sscanf(Databuf, "%lf %lf", &Player.p_x, &Player.p_y);
    393   1.1       jtc 
    394   1.4     lukem 			if (fabs(Player.p_x) > D_EXPER || fabs(Player.p_y) > D_EXPER)
    395   1.4     lukem 				mvaddstr(17, 0, "Invalid coordinates.  Try again.\n");
    396   1.4     lukem 			else
    397   1.4     lukem 				break;
    398   1.4     lukem 		}
    399   1.1       jtc 
    400   1.1       jtc 	for (;;)
    401   1.4     lukem 		/* name the new character */
    402   1.1       jtc 	{
    403   1.4     lukem 		mvprintw(18, 0,
    404   1.4     lukem 		    "Give your character a name [up to %d characters] ?  ", SZ_NAME - 1);
    405   1.4     lukem 		getstring(Player.p_name, SZ_NAME);
    406   1.4     lukem 		truncstring(Player.p_name);	/* remove trailing blanks */
    407   1.4     lukem 
    408   1.4     lukem 		if (Player.p_name[0] == '\0')
    409   1.4     lukem 			/* no null names */
    410   1.4     lukem 			mvaddstr(19, 0, "Invalid name.");
    411   1.4     lukem 		else
    412   1.4     lukem 			if (findname(Player.p_name, &Other) >= 0L)
    413   1.4     lukem 				/* cannot have duplicate names */
    414   1.4     lukem 				mvaddstr(19, 0, "Name already in use.");
    415   1.4     lukem 			else
    416   1.4     lukem 				/* name is acceptable */
    417   1.4     lukem 				break;
    418   1.1       jtc 
    419   1.4     lukem 		addstr("  Pick another.\n");
    420   1.1       jtc 	}
    421   1.1       jtc 
    422   1.4     lukem 	/* get a password for character */
    423   1.4     lukem 	Echo = FALSE;
    424   1.1       jtc 
    425   1.4     lukem 	do {
    426   1.4     lukem 		mvaddstr(20, 0, "Give your character a password [up to 8 characters] ? ");
    427   1.4     lukem 		getstring(Player.p_password, SZ_PASSWORD);
    428   1.6   hubertf 		mvaddstr(21, 0, "Enter again to verify: ");
    429   1.4     lukem 		getstring(Databuf, SZ_PASSWORD);
    430   1.1       jtc 	}
    431   1.4     lukem 	while (strcmp(Player.p_password, Databuf) != 0);
    432   1.1       jtc 
    433   1.4     lukem 	Echo = TRUE;
    434   1.1       jtc 
    435   1.4     lukem 	return (allocrecord());
    436   1.1       jtc }
    437   1.1       jtc 
    438  1.22  dholland static void
    439  1.18  dholland procmain(void)
    440   1.1       jtc {
    441   1.4     lukem 	int     ch;		/* input */
    442   1.4     lukem 	double  x;		/* desired new x coordinate */
    443   1.4     lukem 	double  y;		/* desired new y coordinate */
    444   1.4     lukem 	double  temp;		/* for temporary calculations */
    445   1.4     lukem 	FILE   *fp;		/* for opening files */
    446   1.4     lukem 	int     loop;		/* a loop counter */
    447   1.4     lukem 	bool    hasmoved = FALSE;	/* set if player has moved */
    448   1.4     lukem 
    449   1.4     lukem 	ch = inputoption();
    450   1.4     lukem 	mvaddstr(4, 0, "\n\n");	/* clear status area */
    451   1.4     lukem 
    452   1.4     lukem 	move(7, 0);
    453   1.4     lukem 	clrtobot();		/* clear data on bottom area of screen */
    454   1.4     lukem 
    455   1.4     lukem 	if (Player.p_specialtype == SC_VALAR && (ch == '1' || ch == '7'))
    456   1.4     lukem 		/* valar cannot move */
    457   1.4     lukem 		ch = ' ';
    458   1.1       jtc 
    459   1.4     lukem 	switch (ch) {
    460   1.1       jtc 	case 'K':		/* move up/north */
    461   1.1       jtc 	case 'N':
    462   1.4     lukem 		x = Player.p_x;
    463   1.4     lukem 		y = Player.p_y + MAXMOVE();
    464   1.4     lukem 		hasmoved = TRUE;
    465   1.4     lukem 		break;
    466   1.1       jtc 
    467   1.1       jtc 	case 'J':		/* move down/south */
    468   1.1       jtc 	case 'S':
    469   1.4     lukem 		x = Player.p_x;
    470   1.4     lukem 		y = Player.p_y - MAXMOVE();
    471   1.4     lukem 		hasmoved = TRUE;
    472   1.4     lukem 		break;
    473   1.1       jtc 
    474   1.1       jtc 	case 'L':		/* move right/east */
    475   1.1       jtc 	case 'E':
    476   1.4     lukem 		x = Player.p_x + MAXMOVE();
    477   1.4     lukem 		y = Player.p_y;
    478   1.4     lukem 		hasmoved = TRUE;
    479   1.4     lukem 		break;
    480   1.1       jtc 
    481   1.1       jtc 	case 'H':		/* move left/west */
    482   1.1       jtc 	case 'W':
    483   1.4     lukem 		x = Player.p_x - MAXMOVE();
    484   1.4     lukem 		y = Player.p_y;
    485   1.4     lukem 		hasmoved = TRUE;
    486   1.4     lukem 		break;
    487   1.1       jtc 
    488   1.4     lukem 	default:		/* rest */
    489   1.4     lukem 		Player.p_energy += (Player.p_maxenergy + Player.p_shield) / 15.0
    490   1.4     lukem 		    + Player.p_level / 3.0 + 2.0;
    491   1.4     lukem 		Player.p_energy =
    492   1.4     lukem 		    MIN(Player.p_energy, Player.p_maxenergy + Player.p_shield);
    493   1.4     lukem 
    494   1.4     lukem 		if (Player.p_status != S_CLOAKED)
    495   1.4     lukem 			/* cannot find mana if cloaked */
    496   1.4     lukem 		{
    497   1.4     lukem 			Player.p_mana += (Circle + Player.p_level) / 4.0;
    498   1.4     lukem 
    499   1.4     lukem 			if (drandom() < 0.2 && Player.p_status == S_PLAYING && !Throne)
    500   1.4     lukem 				/* wandering monster */
    501   1.4     lukem 				encounter(-1);
    502   1.1       jtc 		}
    503   1.4     lukem 		break;
    504   1.1       jtc 
    505   1.1       jtc 	case 'X':		/* change/examine a character */
    506   1.4     lukem 		changestats(TRUE);
    507   1.4     lukem 		break;
    508   1.1       jtc 
    509   1.1       jtc 	case '1':		/* move */
    510   1.4     lukem 		for (loop = 3; loop; --loop) {
    511   1.4     lukem 			mvaddstr(4, 0, "X Y Coordinates ? ");
    512   1.4     lukem 			getstring(Databuf, SZ_DATABUF);
    513   1.1       jtc 
    514   1.4     lukem 			if (sscanf(Databuf, "%lf %lf", &x, &y) != 2)
    515   1.4     lukem 				mvaddstr(5, 0, "Try again\n");
    516   1.4     lukem 			else
    517   1.4     lukem 				if (distance(Player.p_x, x, Player.p_y, y) > MAXMOVE())
    518   1.4     lukem 					ILLMOVE();
    519   1.4     lukem 				else {
    520   1.4     lukem 					hasmoved = TRUE;
    521   1.4     lukem 					break;
    522   1.4     lukem 				}
    523   1.1       jtc 		}
    524   1.4     lukem 		break;
    525   1.1       jtc 
    526   1.1       jtc 	case '2':		/* players */
    527   1.4     lukem 		userlist(TRUE);
    528   1.4     lukem 		break;
    529   1.1       jtc 
    530   1.1       jtc 	case '3':		/* message */
    531   1.4     lukem 		mvaddstr(4, 0, "Message ? ");
    532   1.4     lukem 		getstring(Databuf, SZ_DATABUF);
    533   1.4     lukem 		/* we open the file for writing to erase any data which is
    534   1.4     lukem 		 * already there */
    535   1.4     lukem 		fp = fopen(_PATH_MESS, "w");
    536   1.4     lukem 		if (Databuf[0] != '\0')
    537   1.4     lukem 			fprintf(fp, "%s: %s", Player.p_name, Databuf);
    538   1.4     lukem 		fclose(fp);
    539   1.4     lukem 		break;
    540   1.1       jtc 
    541   1.1       jtc 	case '4':		/* stats */
    542   1.4     lukem 		allstatslist();
    543   1.4     lukem 		break;
    544   1.1       jtc 
    545   1.1       jtc 	case '5':		/* good-bye */
    546   1.4     lukem 		leavegame();
    547   1.4     lukem 		/* NOTREACHED */
    548   1.1       jtc 
    549   1.1       jtc 	case '6':		/* cloak */
    550   1.4     lukem 		if (Player.p_level < MEL_CLOAK || Player.p_magiclvl < ML_CLOAK)
    551   1.4     lukem 			ILLCMD();
    552   1.4     lukem 		else
    553   1.4     lukem 			if (Player.p_status == S_CLOAKED)
    554   1.4     lukem 				Player.p_status = S_PLAYING;
    555   1.1       jtc 			else
    556   1.4     lukem 				if (Player.p_mana < MM_CLOAK)
    557   1.4     lukem 					mvaddstr(5, 0, "No mana left.\n");
    558   1.4     lukem 				else {
    559   1.4     lukem 					Changed = TRUE;
    560   1.4     lukem 					Player.p_mana -= MM_CLOAK;
    561   1.4     lukem 					Player.p_status = S_CLOAKED;
    562   1.4     lukem 				}
    563   1.4     lukem 		break;
    564   1.1       jtc 
    565   1.4     lukem 	case '7':		/* teleport */
    566   1.4     lukem 		/*
    567   1.4     lukem 	         * conditions for teleport
    568   1.4     lukem 	         *	- 20 per (level plus magic level)
    569   1.4     lukem 	         *	- OR council of the wise or valar or ex-valar
    570   1.4     lukem 	         *	- OR transport from throne
    571   1.4     lukem 	         * transports from throne cost no mana
    572   1.4     lukem 	         */
    573   1.4     lukem 		if (Player.p_level < MEL_TELEPORT || Player.p_magiclvl < ML_TELEPORT)
    574   1.4     lukem 			ILLCMD();
    575   1.4     lukem 		else
    576   1.4     lukem 			for (loop = 3; loop; --loop) {
    577   1.4     lukem 				mvaddstr(4, 0, "X Y Coordinates ? ");
    578   1.4     lukem 				getstring(Databuf, SZ_DATABUF);
    579   1.4     lukem 
    580   1.4     lukem 				if (sscanf(Databuf, "%lf %lf", &x, &y) == 2) {
    581   1.4     lukem 					temp = distance(Player.p_x, x, Player.p_y, y);
    582   1.4     lukem 					if (!Throne
    583   1.4     lukem 					/* can transport anywhere from throne */
    584   1.4     lukem 					    && Player.p_specialtype <= SC_COUNCIL
    585   1.4     lukem 					/* council, valar can transport
    586   1.4     lukem 					 * anywhere */
    587   1.4     lukem 					    && temp > (Player.p_level + Player.p_magiclvl) * 20.0)
    588   1.4     lukem 						/* can only move 20 per exp.
    589   1.4     lukem 						 * level + mag. level */
    590   1.4     lukem 						ILLMOVE();
    591   1.4     lukem 					else {
    592   1.4     lukem 						temp = (temp / 75.0 + 1.0) * 20.0;	/* mana used */
    593   1.4     lukem 
    594   1.4     lukem 						if (!Throne && temp > Player.p_mana)
    595   1.4     lukem 							mvaddstr(5, 0, "Not enough power for that distance.\n");
    596   1.4     lukem 						else {
    597   1.4     lukem 							if (!Throne)
    598   1.4     lukem 								Player.p_mana -= temp;
    599   1.4     lukem 							hasmoved = TRUE;
    600   1.4     lukem 							break;
    601   1.4     lukem 						}
    602   1.4     lukem 					}
    603   1.1       jtc 				}
    604   1.1       jtc 			}
    605   1.4     lukem 		break;
    606   1.1       jtc 
    607   1.1       jtc 	case 'C':
    608   1.1       jtc 	case '9':		/* monster */
    609   1.4     lukem 		if (Throne)
    610   1.4     lukem 			/* no monsters while on throne */
    611   1.4     lukem 			mvaddstr(5, 0, "No monsters in the chamber!\n");
    612   1.4     lukem 		else
    613   1.4     lukem 			if (Player.p_specialtype != SC_VALAR)
    614   1.4     lukem 				/* the valar cannot call monsters */
    615   1.4     lukem 			{
    616   1.4     lukem 				Player.p_sin += 1e-6;
    617   1.4     lukem 				encounter(-1);
    618   1.4     lukem 			}
    619   1.4     lukem 		break;
    620   1.1       jtc 
    621   1.1       jtc 	case '0':		/* decree */
    622   1.4     lukem 		if (Wizard || (Player.p_specialtype == SC_KING && Throne))
    623   1.4     lukem 			/* kings must be on throne to decree */
    624   1.4     lukem 			dotampered();
    625   1.4     lukem 		else
    626   1.4     lukem 			ILLCMD();
    627   1.4     lukem 		break;
    628   1.1       jtc 
    629   1.1       jtc 	case '8':		/* intervention */
    630   1.4     lukem 		if (Wizard || Player.p_specialtype >= SC_COUNCIL)
    631   1.4     lukem 			dotampered();
    632   1.4     lukem 		else
    633   1.4     lukem 			ILLCMD();
    634   1.4     lukem 		break;
    635   1.1       jtc 	}
    636   1.1       jtc 
    637   1.4     lukem 	if (hasmoved)
    638   1.4     lukem 		/* player has moved -- alter coordinates, and do random
    639   1.4     lukem 		 * monster */
    640   1.1       jtc 	{
    641   1.4     lukem 		altercoordinates(x, y, A_SPECIFIC);
    642   1.1       jtc 
    643   1.4     lukem 		if (drandom() < 0.2 && Player.p_status == S_PLAYING && !Throne)
    644   1.4     lukem 			encounter(-1);
    645   1.1       jtc 	}
    646   1.1       jtc }
    647   1.1       jtc 
    648  1.22  dholland static void
    649  1.18  dholland titlelist(void)
    650   1.1       jtc {
    651   1.4     lukem 	FILE   *fp;		/* used for opening various files */
    652   1.4     lukem 	bool    councilfound = FALSE;	/* set if we find a member of the
    653   1.4     lukem 					 * council */
    654   1.4     lukem 	bool    kingfound = FALSE;	/* set if we find a king */
    655   1.4     lukem 	double  hiexp, nxtexp;	/* used for finding the two highest players */
    656   1.4     lukem 	double  hilvl, nxtlvl;	/* used for finding the two highest players */
    657   1.4     lukem 	char    hiname[21], nxtname[21];	/* used for finding the two
    658   1.4     lukem 						 * highest players */
    659   1.4     lukem 
    660   1.4     lukem 	nxtexp = 0;
    661   1.4     lukem 	mvaddstr(0, 14,
    662   1.4     lukem 	    "W e l c o m e   t o   P h a n t a s i a (vers. 3.3.2)!");
    663   1.4     lukem 
    664   1.4     lukem 	/* print message of the day */
    665   1.4     lukem 	if ((fp = fopen(_PATH_MOTD, "r")) != NULL
    666   1.4     lukem 	    && fgets(Databuf, SZ_DATABUF, fp) != NULL) {
    667   1.4     lukem 		mvaddstr(2, 40 - strlen(Databuf) / 2, Databuf);
    668   1.4     lukem 		fclose(fp);
    669   1.4     lukem 	}
    670   1.4     lukem 	/* search for king */
    671   1.8       jsm 	fseek(Playersfp, 0L, SEEK_SET);
    672   1.4     lukem 	while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
    673   1.4     lukem 		if (Other.p_specialtype == SC_KING &&
    674   1.4     lukem 		    Other.p_status != S_NOTUSED)
    675   1.4     lukem 			/* found the king */
    676   1.4     lukem 		{
    677  1.19  dholland 			snprintf(Databuf, SZ_DATABUF,
    678  1.19  dholland 			    "The present ruler is %s  Level:%.0f",
    679   1.4     lukem 			    Other.p_name, Other.p_level);
    680   1.4     lukem 			mvaddstr(4, 40 - strlen(Databuf) / 2, Databuf);
    681   1.4     lukem 			kingfound = TRUE;
    682   1.4     lukem 			break;
    683   1.4     lukem 		}
    684   1.4     lukem 	if (!kingfound)
    685   1.4     lukem 		mvaddstr(4, 24, "There is no ruler at this time.");
    686   1.4     lukem 
    687   1.4     lukem 	/* search for valar */
    688   1.8       jsm 	fseek(Playersfp, 0L, SEEK_SET);
    689   1.4     lukem 	while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
    690   1.4     lukem 		if (Other.p_specialtype == SC_VALAR && Other.p_status != S_NOTUSED)
    691   1.4     lukem 			/* found the valar */
    692   1.4     lukem 		{
    693  1.19  dholland 			snprintf(Databuf, SZ_DATABUF,
    694  1.19  dholland 				"The Valar is %s   Login:  %s",
    695  1.19  dholland 				Other.p_name, Other.p_login);
    696   1.4     lukem 			mvaddstr(6, 40 - strlen(Databuf) / 2, Databuf);
    697   1.4     lukem 			break;
    698   1.4     lukem 		}
    699   1.4     lukem 	/* search for council of the wise */
    700   1.8       jsm 	fseek(Playersfp, 0L, SEEK_SET);
    701   1.4     lukem 	Lines = 10;
    702   1.4     lukem 	while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
    703   1.4     lukem 		if (Other.p_specialtype == SC_COUNCIL && Other.p_status != S_NOTUSED)
    704   1.4     lukem 			/* found a member of the council */
    705   1.4     lukem 		{
    706   1.4     lukem 			if (!councilfound) {
    707   1.4     lukem 				mvaddstr(8, 30, "Council of the Wise:");
    708   1.4     lukem 				councilfound = TRUE;
    709   1.4     lukem 			}
    710   1.4     lukem 			/* This assumes a finite (<=5) number of C.O.W.: */
    711  1.19  dholland 			snprintf(Databuf, SZ_DATABUF,
    712  1.19  dholland 				"%s   Login:  %s", Other.p_name, Other.p_login);
    713   1.4     lukem 			mvaddstr(Lines++, 40 - strlen(Databuf) / 2, Databuf);
    714   1.4     lukem 		}
    715   1.4     lukem 	/* search for the two highest players */
    716   1.4     lukem 	nxtname[0] = hiname[0] = '\0';
    717   1.4     lukem 	hiexp = 0.0;
    718   1.4     lukem 	nxtlvl = hilvl = 0;
    719   1.4     lukem 
    720   1.8       jsm 	fseek(Playersfp, 0L, SEEK_SET);
    721   1.4     lukem 	while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
    722   1.4     lukem 		if (Other.p_experience > hiexp && Other.p_specialtype <= SC_KING && Other.p_status != S_NOTUSED)
    723   1.4     lukem 			/* highest found so far */
    724   1.4     lukem 		{
    725   1.4     lukem 			nxtexp = hiexp;
    726   1.4     lukem 			hiexp = Other.p_experience;
    727   1.4     lukem 			nxtlvl = hilvl;
    728   1.4     lukem 			hilvl = Other.p_level;
    729   1.4     lukem 			strcpy(nxtname, hiname);
    730   1.4     lukem 			strcpy(hiname, Other.p_name);
    731   1.4     lukem 		} else
    732   1.4     lukem 			if (Other.p_experience > nxtexp
    733   1.4     lukem 			    && Other.p_specialtype <= SC_KING
    734   1.4     lukem 			    && Other.p_status != S_NOTUSED)
    735   1.4     lukem 				/* next highest found so far */
    736   1.4     lukem 			{
    737   1.4     lukem 				nxtexp = Other.p_experience;
    738   1.4     lukem 				nxtlvl = Other.p_level;
    739   1.4     lukem 				strcpy(nxtname, Other.p_name);
    740   1.4     lukem 			}
    741   1.4     lukem 	mvaddstr(15, 28, "Highest characters are:");
    742  1.19  dholland 	snprintf(Databuf, SZ_DATABUF,
    743  1.19  dholland 	    "%s  Level:%.0f   and   %s  Level:%.0f",
    744   1.4     lukem 	    hiname, hilvl, nxtname, nxtlvl);
    745   1.4     lukem 	mvaddstr(17, 40 - strlen(Databuf) / 2, Databuf);
    746   1.4     lukem 
    747   1.4     lukem 	/* print last to die */
    748   1.4     lukem 	if ((fp = fopen(_PATH_LASTDEAD, "r")) != NULL
    749   1.4     lukem 	    && fgets(Databuf, SZ_DATABUF, fp) != NULL) {
    750   1.4     lukem 		mvaddstr(19, 25, "The last character to die was:");
    751   1.4     lukem 		mvaddstr(20, 40 - strlen(Databuf) / 2, Databuf);
    752  1.16  christos 	}
    753  1.16  christos 	if (fp)
    754   1.4     lukem 		fclose(fp);
    755   1.4     lukem 	refresh();
    756   1.1       jtc }
    757   1.1       jtc 
    758  1.22  dholland static long
    759  1.18  dholland recallplayer(void)
    760   1.1       jtc {
    761   1.4     lukem 	long    loc = 0L;	/* location in player file */
    762   1.4     lukem 	int     loop;		/* loop counter */
    763   1.4     lukem 	int     ch;		/* input */
    764   1.1       jtc 
    765   1.4     lukem 	clear();
    766   1.4     lukem 	mvprintw(10, 0, "What was your character's name ? ");
    767   1.4     lukem 	getstring(Databuf, SZ_NAME);
    768   1.4     lukem 	truncstring(Databuf);
    769   1.4     lukem 
    770   1.4     lukem 	if ((loc = findname(Databuf, &Player)) >= 0L)
    771   1.4     lukem 		/* found character */
    772   1.4     lukem 	{
    773   1.4     lukem 		Echo = FALSE;
    774   1.4     lukem 
    775   1.4     lukem 		for (loop = 0; loop < 2; ++loop) {
    776   1.4     lukem 			/* prompt for password */
    777   1.4     lukem 			mvaddstr(11, 0, "Password ? ");
    778   1.4     lukem 			getstring(Databuf, SZ_PASSWORD);
    779   1.4     lukem 			if (strcmp(Databuf, Player.p_password) == 0)
    780   1.4     lukem 				/* password good */
    781   1.4     lukem 			{
    782   1.4     lukem 				Echo = TRUE;
    783   1.1       jtc 
    784   1.4     lukem 				if (Player.p_status != S_OFF)
    785   1.4     lukem 					/* player did not exit normally last
    786   1.4     lukem 					 * time */
    787   1.4     lukem 				{
    788   1.4     lukem 					clear();
    789   1.4     lukem 					addstr("Your character did not exit normally last time.\n");
    790   1.4     lukem 					addstr("If you think you have good cause to have your character saved,\n");
    791   1.4     lukem 					printw("you may quit and mail your reason to 'root'.\n");
    792   1.4     lukem 					addstr("Otherwise, continuing spells certain death.\n");
    793   1.4     lukem 					addstr("Do you want to quit ? ");
    794   1.4     lukem 					ch = getanswer("YN", FALSE);
    795   1.4     lukem 					if (ch == 'Y') {
    796   1.4     lukem 						Player.p_status = S_HUNGUP;
    797   1.4     lukem 						writerecord(&Player, loc);
    798   1.4     lukem 						cleanup(TRUE);
    799   1.4     lukem 						/* NOTREACHED */
    800   1.4     lukem 					}
    801   1.4     lukem 					death("Stupidity");
    802   1.4     lukem 					/* NOTREACHED */
    803   1.4     lukem 				}
    804   1.4     lukem 				return (loc);
    805   1.4     lukem 			} else
    806   1.4     lukem 				mvaddstr(12, 0, "No good.\n");
    807   1.1       jtc 		}
    808   1.1       jtc 
    809   1.4     lukem 		Echo = TRUE;
    810   1.4     lukem 	} else
    811   1.4     lukem 		mvaddstr(11, 0, "Not found.\n");
    812   1.1       jtc 
    813   1.4     lukem 	more(13);
    814   1.4     lukem 	return (-1L);
    815   1.1       jtc }
    816   1.1       jtc 
    817  1.22  dholland static void
    818  1.18  dholland neatstuff(void)
    819   1.1       jtc {
    820   1.4     lukem 	double  temp;		/* for temporary calculations */
    821   1.4     lukem 	int     ch;		/* input */
    822   1.1       jtc 
    823   1.4     lukem 	switch ((int) ROLL(0.0, 100.0)) {
    824   1.1       jtc 	case 1:
    825   1.1       jtc 	case 2:
    826   1.4     lukem 		if (Player.p_poison > 0.0) {
    827   1.4     lukem 			mvaddstr(4, 0, "You've found a medic!  How much will you offer to be cured ? ");
    828   1.4     lukem 			temp = floor(infloat());
    829   1.4     lukem 			if (temp < 0.0 || temp > Player.p_gold)
    830   1.4     lukem 				/* negative gold, or more than available */
    831   1.4     lukem 			{
    832   1.4     lukem 				mvaddstr(6, 0, "He was not amused, and made you worse.\n");
    833   1.4     lukem 				Player.p_poison += 1.0;
    834   1.4     lukem 			} else
    835   1.4     lukem 				if (drandom() / 2.0 > (temp + 1.0) / MAX(Player.p_gold, 1))
    836   1.4     lukem 					/* medic wants 1/2 of available gold */
    837   1.4     lukem 					mvaddstr(5, 0, "Sorry, he wasn't interested.\n");
    838   1.4     lukem 				else {
    839   1.4     lukem 					mvaddstr(5, 0, "He accepted.");
    840   1.4     lukem 					Player.p_poison = MAX(0.0, Player.p_poison - 1.0);
    841   1.4     lukem 					Player.p_gold -= temp;
    842   1.4     lukem 				}
    843   1.1       jtc 		}
    844   1.4     lukem 		break;
    845   1.1       jtc 
    846   1.1       jtc 	case 3:
    847   1.4     lukem 		mvaddstr(4, 0, "You've been caught raping and pillaging!\n");
    848   1.4     lukem 		Player.p_experience += 4000.0;
    849   1.4     lukem 		Player.p_sin += 0.5;
    850   1.4     lukem 		break;
    851   1.1       jtc 
    852   1.1       jtc 	case 4:
    853   1.4     lukem 		temp = ROLL(10.0, 75.0);
    854   1.4     lukem 		mvprintw(4, 0, "You've found %.0f gold pieces, want them ? ", temp);
    855   1.4     lukem 		ch = getanswer("NY", FALSE);
    856   1.4     lukem 
    857   1.4     lukem 		if (ch == 'Y')
    858   1.4     lukem 			collecttaxes(temp, 0.0);
    859   1.4     lukem 		break;
    860   1.1       jtc 
    861   1.1       jtc 	case 5:
    862   1.4     lukem 		if (Player.p_sin > 1.0) {
    863   1.4     lukem 			mvaddstr(4, 0, "You've found a Holy Orb!\n");
    864   1.4     lukem 			Player.p_sin -= 0.25;
    865   1.1       jtc 		}
    866   1.4     lukem 		break;
    867   1.1       jtc 
    868   1.1       jtc 	case 6:
    869   1.4     lukem 		if (Player.p_poison < 1.0) {
    870   1.4     lukem 			mvaddstr(4, 0, "You've been hit with a plague!\n");
    871   1.4     lukem 			Player.p_poison += 1.0;
    872   1.1       jtc 		}
    873   1.4     lukem 		break;
    874   1.1       jtc 
    875   1.1       jtc 	case 7:
    876   1.4     lukem 		mvaddstr(4, 0, "You've found some holy water.\n");
    877   1.4     lukem 		++Player.p_holywater;
    878   1.4     lukem 		break;
    879   1.1       jtc 
    880   1.1       jtc 	case 8:
    881   1.4     lukem 		mvaddstr(4, 0, "You've met a Guru. . .");
    882   1.4     lukem 		if (drandom() * Player.p_sin > 1.0)
    883   1.4     lukem 			addstr("You disgusted him with your sins!\n");
    884   1.4     lukem 		else
    885   1.4     lukem 			if (Player.p_poison > 0.0) {
    886   1.4     lukem 				addstr("He looked kindly upon you, and cured you.\n");
    887   1.4     lukem 				Player.p_poison = 0.0;
    888   1.4     lukem 			} else {
    889   1.4     lukem 				addstr("He rewarded you for your virtue.\n");
    890   1.4     lukem 				Player.p_mana += 50.0;
    891   1.4     lukem 				Player.p_shield += 2.0;
    892   1.4     lukem 			}
    893   1.4     lukem 		break;
    894   1.1       jtc 
    895   1.1       jtc 	case 9:
    896   1.4     lukem 		mvaddstr(4, 0, "You've found an amulet.\n");
    897   1.4     lukem 		++Player.p_amulets;
    898   1.4     lukem 		break;
    899   1.1       jtc 
    900   1.1       jtc 	case 10:
    901   1.4     lukem 		if (Player.p_blindness) {
    902   1.4     lukem 			mvaddstr(4, 0, "You've regained your sight!\n");
    903   1.4     lukem 			Player.p_blindness = FALSE;
    904   1.1       jtc 		}
    905   1.4     lukem 		break;
    906   1.1       jtc 
    907   1.4     lukem 	default:		/* deal with poison */
    908   1.4     lukem 		if (Player.p_poison > 0.0) {
    909   1.4     lukem 			temp = Player.p_poison * Statptr->c_weakness
    910   1.4     lukem 			    * Player.p_maxenergy / 600.0;
    911   1.4     lukem 			if (Player.p_energy > Player.p_maxenergy / 10.0
    912   1.4     lukem 			    && temp + 5.0 < Player.p_energy)
    913   1.4     lukem 				Player.p_energy -= temp;
    914   1.1       jtc 		}
    915   1.4     lukem 		break;
    916   1.1       jtc 	}
    917   1.1       jtc }
    918   1.1       jtc 
    919  1.22  dholland static void
    920  1.18  dholland genchar(int type)
    921   1.1       jtc {
    922   1.4     lukem 	int     subscript;	/* used for subscripting into Stattable */
    923   1.7       jsm 	const struct charstats *statptr; /* for pointing into Stattable */
    924   1.1       jtc 
    925   1.4     lukem 	subscript = type - '1';
    926   1.1       jtc 
    927   1.4     lukem 	if (subscript < C_MAGIC || subscript > C_EXPER)
    928   1.4     lukem 		if (subscript != C_SUPER || !Wizard)
    929   1.4     lukem 			/* fighter is default */
    930   1.4     lukem 			subscript = C_FIGHTER;
    931   1.4     lukem 
    932   1.4     lukem 	statptr = &Stattable[subscript];
    933   1.4     lukem 
    934   1.4     lukem 	Player.p_quickness =
    935   1.4     lukem 	    ROLL(statptr->c_quickness.base, statptr->c_quickness.interval);
    936   1.4     lukem 	Player.p_strength =
    937   1.4     lukem 	    ROLL(statptr->c_strength.base, statptr->c_strength.interval);
    938   1.4     lukem 	Player.p_mana =
    939   1.4     lukem 	    ROLL(statptr->c_mana.base, statptr->c_mana.interval);
    940   1.4     lukem 	Player.p_maxenergy =
    941   1.4     lukem 	    Player.p_energy =
    942   1.4     lukem 	    ROLL(statptr->c_energy.base, statptr->c_energy.interval);
    943   1.4     lukem 	Player.p_brains =
    944   1.4     lukem 	    ROLL(statptr->c_brains.base, statptr->c_brains.interval);
    945   1.4     lukem 	Player.p_magiclvl =
    946   1.4     lukem 	    ROLL(statptr->c_magiclvl.base, statptr->c_magiclvl.interval);
    947   1.4     lukem 
    948   1.4     lukem 	Player.p_type = subscript;
    949   1.4     lukem 
    950   1.4     lukem 	if (Player.p_type == C_HALFLING)
    951   1.4     lukem 		/* give halfling some experience */
    952   1.4     lukem 		Player.p_experience = ROLL(600.0, 200.0);
    953   1.1       jtc }
    954   1.1       jtc 
    955  1.22  dholland static void
    956  1.18  dholland playinit(void)
    957   1.1       jtc {
    958   1.4     lukem 	/* catch/ingnore signals */
    959   1.1       jtc 
    960   1.1       jtc #ifdef	BSD41
    961   1.4     lukem 	sigignore(SIGQUIT);
    962   1.4     lukem 	sigignore(SIGALRM);
    963   1.4     lukem 	sigignore(SIGTERM);
    964   1.4     lukem 	sigignore(SIGTSTP);
    965   1.4     lukem 	sigignore(SIGTTIN);
    966   1.4     lukem 	sigignore(SIGTTOU);
    967   1.4     lukem 	sighold(SIGINT);
    968   1.4     lukem 	sigset(SIGHUP, ill_sig);
    969   1.4     lukem 	sigset(SIGTRAP, ill_sig);
    970   1.4     lukem 	sigset(SIGIOT, ill_sig);
    971   1.4     lukem 	sigset(SIGEMT, ill_sig);
    972   1.4     lukem 	sigset(SIGFPE, ill_sig);
    973   1.4     lukem 	sigset(SIGBUS, ill_sig);
    974   1.4     lukem 	sigset(SIGSEGV, ill_sig);
    975   1.4     lukem 	sigset(SIGSYS, ill_sig);
    976   1.4     lukem 	sigset(SIGPIPE, ill_sig);
    977   1.1       jtc #endif
    978   1.1       jtc #ifdef	BSD42
    979   1.4     lukem 	signal(SIGQUIT, ill_sig);
    980   1.4     lukem 	signal(SIGALRM, SIG_IGN);
    981   1.4     lukem 	signal(SIGTERM, SIG_IGN);
    982   1.4     lukem 	signal(SIGTSTP, SIG_IGN);
    983   1.4     lukem 	signal(SIGTTIN, SIG_IGN);
    984   1.4     lukem 	signal(SIGTTOU, SIG_IGN);
    985   1.4     lukem 	signal(SIGINT, ill_sig);
    986   1.4     lukem 	signal(SIGHUP, SIG_DFL);
    987   1.4     lukem 	signal(SIGTRAP, ill_sig);
    988   1.4     lukem 	signal(SIGIOT, ill_sig);
    989   1.4     lukem 	signal(SIGEMT, ill_sig);
    990   1.4     lukem 	signal(SIGFPE, ill_sig);
    991   1.4     lukem 	signal(SIGBUS, ill_sig);
    992   1.4     lukem 	signal(SIGSEGV, ill_sig);
    993   1.4     lukem 	signal(SIGSYS, ill_sig);
    994   1.4     lukem 	signal(SIGPIPE, ill_sig);
    995   1.1       jtc #endif
    996   1.1       jtc #ifdef	SYS3
    997   1.4     lukem 	signal(SIGINT, SIG_IGN);
    998   1.4     lukem 	signal(SIGQUIT, SIG_IGN);
    999   1.4     lukem 	signal(SIGTERM, SIG_IGN);
   1000   1.4     lukem 	signal(SIGALRM, SIG_IGN);
   1001   1.4     lukem 	signal(SIGHUP, ill_sig);
   1002   1.4     lukem 	signal(SIGTRAP, ill_sig);
   1003   1.4     lukem 	signal(SIGIOT, ill_sig);
   1004   1.4     lukem 	signal(SIGEMT, ill_sig);
   1005   1.4     lukem 	signal(SIGFPE, ill_sig);
   1006   1.4     lukem 	signal(SIGBUS, ill_sig);
   1007   1.4     lukem 	signal(SIGSEGV, ill_sig);
   1008   1.4     lukem 	signal(SIGSYS, ill_sig);
   1009   1.4     lukem 	signal(SIGPIPE, ill_sig);
   1010   1.1       jtc #endif
   1011   1.1       jtc #ifdef	SYS5
   1012   1.4     lukem 	signal(SIGINT, SIG_IGN);
   1013   1.4     lukem 	signal(SIGQUIT, SIG_IGN);
   1014   1.4     lukem 	signal(SIGTERM, SIG_IGN);
   1015   1.4     lukem 	signal(SIGALRM, SIG_IGN);
   1016   1.4     lukem 	signal(SIGHUP, ill_sig);
   1017   1.4     lukem 	signal(SIGTRAP, ill_sig);
   1018   1.4     lukem 	signal(SIGIOT, ill_sig);
   1019   1.4     lukem 	signal(SIGEMT, ill_sig);
   1020   1.4     lukem 	signal(SIGFPE, ill_sig);
   1021   1.4     lukem 	signal(SIGBUS, ill_sig);
   1022   1.4     lukem 	signal(SIGSEGV, ill_sig);
   1023   1.4     lukem 	signal(SIGSYS, ill_sig);
   1024   1.4     lukem 	signal(SIGPIPE, ill_sig);
   1025   1.1       jtc #endif
   1026   1.1       jtc 
   1027  1.17  drochner 	if (!initscr()) {	/* turn on curses */
   1028  1.17  drochner 		fprintf(stderr, "couldn't initialize screen\n");
   1029  1.17  drochner 		exit (0);
   1030  1.17  drochner 	}
   1031   1.4     lukem 	noecho();		/* do not echo input */
   1032  1.10     blymn 	cbreak();		/* do not process erase, kill */
   1033   1.4     lukem 	clear();
   1034   1.4     lukem 	refresh();
   1035   1.4     lukem 	Windows = TRUE;		/* mark the state */
   1036   1.1       jtc }
   1037   1.1       jtc 
   1038   1.4     lukem void
   1039  1.18  dholland cleanup(int doexit)
   1040   1.1       jtc {
   1041   1.4     lukem 	if (Windows) {
   1042   1.4     lukem 		move(LINES - 2, 0);
   1043   1.4     lukem 		refresh();
   1044  1.10     blymn 		nocbreak();
   1045   1.4     lukem 		endwin();
   1046   1.4     lukem 	}
   1047  1.12       jsm 	if (Playersfp)
   1048  1.12       jsm 		fclose(Playersfp);
   1049  1.12       jsm 	if (Monstfp)
   1050  1.12       jsm 		fclose(Monstfp);
   1051  1.12       jsm 	if (Messagefp)
   1052  1.12       jsm 		fclose(Messagefp);
   1053  1.12       jsm 	if (Energyvoidfp)
   1054  1.12       jsm 		fclose(Energyvoidfp);
   1055   1.4     lukem 
   1056   1.4     lukem 	if (doexit)
   1057   1.4     lukem 		exit(0);
   1058   1.4     lukem 	/* NOTREACHED */
   1059   1.1       jtc }
   1060