xref: /netbsd-src/games/phantasia/main.c (revision 0e5bc969e0abbce4bd9dd9fd3dd995c904ba68e4)
1*0e5bc969Sandvar /*	$NetBSD: main.c,v 1.25 2022/06/27 22:41:28 andvar Exp $	*/
2dcfebd78Scgd 
386a62b8dSjtc /*
486a62b8dSjtc  * Phantasia 3.3.2 -- Interterminal fantasy game
586a62b8dSjtc  *
686a62b8dSjtc  * Edward A. Estes
786a62b8dSjtc  * AT&T, March 12, 1986
886a62b8dSjtc  */
986a62b8dSjtc 
1086a62b8dSjtc /* DISCLAIMER:
1186a62b8dSjtc  *
1286a62b8dSjtc  * This game is distributed for free as is.  It is not guaranteed to work
1386a62b8dSjtc  * in every conceivable environment.  It is not even guaranteed to work
1486a62b8dSjtc  * in ANY environment.
1586a62b8dSjtc  *
1686a62b8dSjtc  * This game is distributed without notice of copyright, therefore it
1786a62b8dSjtc  * may be used in any manner the recipient sees fit.  However, the
1886a62b8dSjtc  * author assumes no responsibility for maintaining or revising this
1986a62b8dSjtc  * game, in its original form, or any derivitives thereof.
2086a62b8dSjtc  *
2186a62b8dSjtc  * The author shall not be responsible for any loss, cost, or damage,
2286a62b8dSjtc  * including consequential damage, caused by reliance on this material.
2386a62b8dSjtc  *
2486a62b8dSjtc  * The author makes no warranties, express or implied, including warranties
2586a62b8dSjtc  * of merchantability or fitness for a particular purpose or use.
2686a62b8dSjtc  *
2786a62b8dSjtc  * AT&T is in no way connected with this game.
2886a62b8dSjtc  */
2986a62b8dSjtc 
3086a62b8dSjtc #include <sys/types.h>
31e28fc908Sdholland #include <sys/stat.h>
320cf018c1Sdholland #include <err.h>
33e28fc908Sdholland #include <math.h>
3486a62b8dSjtc #include <pwd.h>
35e28fc908Sdholland #include <setjmp.h>
36e28fc908Sdholland #include <stdio.h>
37e28fc908Sdholland #include <stdlib.h>
38e28fc908Sdholland #include <string.h>
39e28fc908Sdholland #include <unistd.h>
40e28fc908Sdholland 
41e28fc908Sdholland #include "macros.h"
42e28fc908Sdholland #include "phantdefs.h"
43e28fc908Sdholland #include "phantstruct.h"
44e28fc908Sdholland #include "phantglobs.h"
45e28fc908Sdholland #include "pathnames.h"
46e28fc908Sdholland 
47e28fc908Sdholland #undef bool
48e28fc908Sdholland #include <curses.h>
4986a62b8dSjtc 
5086a62b8dSjtc /*
5186a62b8dSjtc  * The program allocates as much file space as it needs to store characters,
5286a62b8dSjtc  * so the possibility exists for the character file to grow without bound.
5386a62b8dSjtc  * The file is purged upon normal entry to try to avoid that problem.
5486a62b8dSjtc  * A similar problem exists for energy voids.  To alleviate the problem here,
5586a62b8dSjtc  * the void file is cleared with every new king, and a limit is placed
5686a62b8dSjtc  * on the size of the energy void file.
5786a62b8dSjtc  */
5886a62b8dSjtc 
5986a62b8dSjtc /*
6086a62b8dSjtc  * Put one line of text into the file 'motd' for announcements, etc.
6186a62b8dSjtc  */
6286a62b8dSjtc 
6386a62b8dSjtc /*
6486a62b8dSjtc  * The scoreboard file is updated when someone dies, and keeps track
6586a62b8dSjtc  * of the highest character to date for that login.
6686a62b8dSjtc  * Being purged from the character file does not cause the scoreboard
6786a62b8dSjtc  * to be updated.
6886a62b8dSjtc  */
6986a62b8dSjtc 
7086a62b8dSjtc 
7186a62b8dSjtc /*
7286a62b8dSjtc  * main.c	Main routines for Phantasia
7386a62b8dSjtc  */
7486a62b8dSjtc 
755305281bSdholland static void genchar(int);
765305281bSdholland static void initialstate(void);
775305281bSdholland static void neatstuff(void);
785305281bSdholland static void playinit(void);
795305281bSdholland static void procmain(void);
805305281bSdholland static long recallplayer(void);
815305281bSdholland static long rollnewplayer(void);
825305281bSdholland static void titlelist(void);
835305281bSdholland 
8473a79751Swiz int	main(int, char **);
8586a62b8dSjtc 
86a232aee2Slukem int
main(int argc,char ** argv)87c7a109ccSdholland main(int argc, char **argv)
8886a62b8dSjtc {
8986a62b8dSjtc 	bool    noheader = FALSE;	/* set if don't want header */
9086a62b8dSjtc 	bool    headeronly = FALSE;	/* set if only want header */
9186a62b8dSjtc 	bool    examine = FALSE;	/* set if examine a character */
92c4816c32Scgd 	time_t  seconds;		/* for time of day */
9386a62b8dSjtc 	double  dtemp;			/* for temporary calculations */
9486a62b8dSjtc 
9586a62b8dSjtc 	initialstate();			/* init globals */
9686a62b8dSjtc 
9786a62b8dSjtc 	/* process arguments */
9886a62b8dSjtc 	while (--argc && (*++argv)[0] == '-')
99a232aee2Slukem 		switch ((*argv)[1]) {
10086a62b8dSjtc 		case 's':	/* short */
10186a62b8dSjtc 			noheader = TRUE;
10286a62b8dSjtc 			break;
10386a62b8dSjtc 
10486a62b8dSjtc 		case 'H':	/* Header */
10586a62b8dSjtc 			headeronly = TRUE;
10686a62b8dSjtc 			break;
10786a62b8dSjtc 
10886a62b8dSjtc 		case 'a':	/* all users */
10986a62b8dSjtc 			activelist();
11086a62b8dSjtc 			cleanup(TRUE);
111fbffadb9Smrg 			__unreachable();
11286a62b8dSjtc 			/* NOTREACHED */
11386a62b8dSjtc 
11486a62b8dSjtc 		case 'p':	/* purge old players */
11586a62b8dSjtc 			purgeoldplayers();
11686a62b8dSjtc 			cleanup(TRUE);
117fbffadb9Smrg 			__unreachable();
11886a62b8dSjtc 			/* NOTREACHED */
11986a62b8dSjtc 
12086a62b8dSjtc 		case 'S':	/* set 'Wizard' */
12186a62b8dSjtc 			Wizard = !getuid();
12286a62b8dSjtc 			break;
12386a62b8dSjtc 
12486a62b8dSjtc 		case 'x':	/* examine */
12586a62b8dSjtc 			examine = TRUE;
12686a62b8dSjtc 			break;
12786a62b8dSjtc 
12886a62b8dSjtc 		case 'm':	/* monsters */
12986a62b8dSjtc 			monstlist();
13086a62b8dSjtc 			cleanup(TRUE);
131fbffadb9Smrg 			__unreachable();
13286a62b8dSjtc 			/* NOTREACHED */
13386a62b8dSjtc 
13486a62b8dSjtc 		case 'b':	/* scoreboard */
13586a62b8dSjtc 			scorelist();
13686a62b8dSjtc 			cleanup(TRUE);
137fbffadb9Smrg 			__unreachable();
13886a62b8dSjtc 			/* NOTREACHED */
13986a62b8dSjtc 		}
14086a62b8dSjtc 
14186a62b8dSjtc 	if (!isatty(0))		/* don't let non-tty's play */
14286a62b8dSjtc 		cleanup(TRUE);
14386a62b8dSjtc 	/* NOTREACHED */
14486a62b8dSjtc 
14586a62b8dSjtc 	playinit();		/* set up to catch signals, init curses */
14686a62b8dSjtc 
147a232aee2Slukem 	if (examine) {
14886a62b8dSjtc 		changestats(FALSE);
14986a62b8dSjtc 		cleanup(TRUE);
150fbffadb9Smrg 		__unreachable();
15186a62b8dSjtc 		/* NOTREACHED */
15286a62b8dSjtc 	}
153a232aee2Slukem 	if (!noheader) {
15486a62b8dSjtc 		titlelist();
15586a62b8dSjtc 		purgeoldplayers();	/* clean up old characters */
15686a62b8dSjtc 	}
157fbffadb9Smrg 	if (headeronly) {
15886a62b8dSjtc 		cleanup(TRUE);
159fbffadb9Smrg 		__unreachable();
16086a62b8dSjtc 		/* NOTREACHED */
161fbffadb9Smrg 	}
16286a62b8dSjtc 
16386a62b8dSjtc 	do
16486a62b8dSjtc 		/* get the player structure filled */
16586a62b8dSjtc 	{
16686a62b8dSjtc 		Fileloc = -1L;
16786a62b8dSjtc 
16886a62b8dSjtc 		mvaddstr(22, 17, "Do you have a character to run [Q = Quit] ? ");
16986a62b8dSjtc 
170a232aee2Slukem 		switch (getanswer("NYQ", FALSE)) {
17186a62b8dSjtc 		case 'Y':
17286a62b8dSjtc 			Fileloc = recallplayer();
17386a62b8dSjtc 			break;
17486a62b8dSjtc 
17586a62b8dSjtc 		case 'Q':
17686a62b8dSjtc 			cleanup(TRUE);
177fbffadb9Smrg 			__unreachable();
17886a62b8dSjtc 			/* NOTREACHED */
17986a62b8dSjtc 
18086a62b8dSjtc 		default:
18186a62b8dSjtc 			Fileloc = rollnewplayer();
18286a62b8dSjtc 			break;
18386a62b8dSjtc 		}
18486a62b8dSjtc 		clear();
18586a62b8dSjtc 	}
18686a62b8dSjtc 	while (Fileloc < 0L);
18786a62b8dSjtc 
18886a62b8dSjtc 	if (Player.p_level > 5.0)
18986a62b8dSjtc 		/* low level players have long timeout */
19086a62b8dSjtc 		Timeout = TRUE;
19186a62b8dSjtc 
19286a62b8dSjtc 	/* update some important player statistics */
193bee0eddcSdholland 	strlcpy(Player.p_login, Login, sizeof(Player.p_login));
19486a62b8dSjtc 	time(&seconds);
19586a62b8dSjtc 	Player.p_lastused = localtime(&seconds)->tm_yday;
19686a62b8dSjtc 	Player.p_status = S_PLAYING;
19786a62b8dSjtc 	writerecord(&Player, Fileloc);
19886a62b8dSjtc 
19986a62b8dSjtc 	Statptr = &Stattable[Player.p_type];	/* initialize pointer */
20086a62b8dSjtc 
20186a62b8dSjtc 	/* catch interrupts */
20286a62b8dSjtc #ifdef	BSD41
20386a62b8dSjtc 	sigset(SIGINT, interrupt);
20486a62b8dSjtc #endif
20586a62b8dSjtc #ifdef	BSD42
20686a62b8dSjtc 	signal(SIGINT, interrupt);
20786a62b8dSjtc #endif
20886a62b8dSjtc #ifdef	SYS3
20986a62b8dSjtc 	signal(SIGINT, interrupt);
21086a62b8dSjtc #endif
21186a62b8dSjtc #ifdef	SYS5
21286a62b8dSjtc 	signal(SIGINT, interrupt);
21386a62b8dSjtc #endif
21486a62b8dSjtc 
21586a62b8dSjtc 	altercoordinates(Player.p_x, Player.p_y, A_FORCED);	/* set some flags */
21686a62b8dSjtc 
21786a62b8dSjtc 	clear();
21886a62b8dSjtc 
21986a62b8dSjtc 	for (;;)
22086a62b8dSjtc 		/* loop forever, processing input */
22186a62b8dSjtc 	{
22286a62b8dSjtc 
22386a62b8dSjtc 		adjuststats();	/* cleanup stats */
22486a62b8dSjtc 
22586a62b8dSjtc 		if (Throne && Player.p_crowns == 0 && Player.p_specialtype != SC_KING)
22686a62b8dSjtc 			/* not allowed on throne -- move */
22786a62b8dSjtc 		{
22886a62b8dSjtc 			mvaddstr(5, 0, "You're not allowed in the Lord's Chamber without a crown.\n");
22986a62b8dSjtc 			altercoordinates(0.0, 0.0, A_NEAR);
23086a62b8dSjtc 		}
23186a62b8dSjtc 		checktampered();/* check for energy voids, etc. */
23286a62b8dSjtc 
23386a62b8dSjtc 		if (Player.p_status != S_CLOAKED
23486a62b8dSjtc 		/* not cloaked */
23586a62b8dSjtc 		    && (dtemp = fabs(Player.p_x)) == fabs(Player.p_y)
23686a62b8dSjtc 		/* |x| = |y| */
23786a62b8dSjtc 		    && !Throne)
23886a62b8dSjtc 			/* not on throne */
23986a62b8dSjtc 		{
24086a62b8dSjtc 			dtemp = sqrt(dtemp / 100.0);
24186a62b8dSjtc 			if (floor(dtemp) == dtemp)
24286a62b8dSjtc 				/* |x| / 100 == n*n; at a trading post */
24386a62b8dSjtc 			{
24486a62b8dSjtc 				tradingpost();
24586a62b8dSjtc 				clear();
24686a62b8dSjtc 			}
24786a62b8dSjtc 		}
24886a62b8dSjtc 		checkbattle();	/* check for player to player battle */
24986a62b8dSjtc 		neatstuff();	/* gurus, medics, etc. */
25086a62b8dSjtc 
25104afeca6Sveego 		if (Player.p_status == S_CLOAKED) {
25286a62b8dSjtc 			/* costs 3 mana per turn to be cloaked */
25386a62b8dSjtc 			if (Player.p_mana > 3.0)
25486a62b8dSjtc 				Player.p_mana -= 3.0;
25586a62b8dSjtc 			else
25686a62b8dSjtc 				/* ran out of mana, uncloak */
25786a62b8dSjtc 			{
25886a62b8dSjtc 				Player.p_status = S_PLAYING;
25986a62b8dSjtc 				Changed = TRUE;
26086a62b8dSjtc 			}
26104afeca6Sveego 		}
26286a62b8dSjtc 
26386a62b8dSjtc 		if (Player.p_status != S_PLAYING && Player.p_status != S_CLOAKED)
26486a62b8dSjtc 			/* change status back to S_PLAYING */
26586a62b8dSjtc 		{
26686a62b8dSjtc 			Player.p_status = S_PLAYING;
26786a62b8dSjtc 			Changed = TRUE;
26886a62b8dSjtc 		}
26986a62b8dSjtc 		if (Changed)
27086a62b8dSjtc 			/* update file only if important stuff has changed */
27186a62b8dSjtc 		{
27286a62b8dSjtc 			writerecord(&Player, Fileloc);
27386a62b8dSjtc 			Changed = FALSE;
27486a62b8dSjtc 			continue;
27586a62b8dSjtc 		}
27686a62b8dSjtc 		readmessage();	/* read message, if any */
27786a62b8dSjtc 
27886a62b8dSjtc 		displaystats();	/* print statistics */
27986a62b8dSjtc 
28086a62b8dSjtc 		move(6, 0);
28186a62b8dSjtc 
28286a62b8dSjtc 		if (Throne)
28386a62b8dSjtc 			/* maybe make king, print prompt, etc. */
28486a62b8dSjtc 			throneroom();
28586a62b8dSjtc 
28686a62b8dSjtc 		/* print status line */
28786a62b8dSjtc 		addstr("1:Move  2:Players  3:Talk  4:Stats  5:Quit  ");
28886a62b8dSjtc 		if (Player.p_level >= MEL_CLOAK && Player.p_magiclvl >= ML_CLOAK)
28986a62b8dSjtc 			addstr("6:Cloak  ");
29086a62b8dSjtc 		if (Player.p_level >= MEL_TELEPORT && Player.p_magiclvl >= ML_TELEPORT)
29186a62b8dSjtc 			addstr("7:Teleport  ");
29286a62b8dSjtc 		if (Player.p_specialtype >= SC_COUNCIL || Wizard)
29386a62b8dSjtc 			addstr("8:Intervene  ");
29486a62b8dSjtc 
29586a62b8dSjtc 		procmain();	/* process input */
29686a62b8dSjtc 	}
29786a62b8dSjtc }
29886a62b8dSjtc 
2995305281bSdholland static void
initialstate(void)300c7a109ccSdholland initialstate(void)
30186a62b8dSjtc {
30227984797Sjmc 	struct stat sb;
3030cf018c1Sdholland 	struct passwd *pw;
30427984797Sjmc 
30586a62b8dSjtc 	Beyond = FALSE;
30686a62b8dSjtc 	Marsh = FALSE;
30786a62b8dSjtc 	Throne = FALSE;
30886a62b8dSjtc 	Changed = FALSE;
30986a62b8dSjtc 	Wizard = FALSE;
31086a62b8dSjtc 	Timeout = FALSE;
31186a62b8dSjtc 	Users = 0;
31286a62b8dSjtc 	Windows = FALSE;
31386a62b8dSjtc 	Echo = TRUE;
31486a62b8dSjtc 
31586a62b8dSjtc 	/* setup login name */
3160cf018c1Sdholland 	if ((Login = getlogin()) == NULL) {
3170cf018c1Sdholland 		pw = getpwuid(getuid());
3180cf018c1Sdholland 		if (pw == NULL) {
3190cf018c1Sdholland 			errx(1, "Who are you?");
3200cf018c1Sdholland 		}
3210cf018c1Sdholland 		Login = pw->pw_name;
3220cf018c1Sdholland 	}
32386a62b8dSjtc 
32486a62b8dSjtc 	/* open some files */
32586a62b8dSjtc 	if ((Playersfp = fopen(_PATH_PEOPLE, "r+")) == NULL)
32686a62b8dSjtc 		error(_PATH_PEOPLE);
32786a62b8dSjtc 	/* NOTREACHED */
3287dc5308dSjsm 	if (fileno(Playersfp) < 3)
3297dc5308dSjsm 		exit(1);
33086a62b8dSjtc 
33186a62b8dSjtc 	if ((Monstfp = fopen(_PATH_MONST, "r+")) == NULL)
33286a62b8dSjtc 		error(_PATH_MONST);
33386a62b8dSjtc 	/* NOTREACHED */
33486a62b8dSjtc 
33586a62b8dSjtc 	if ((Messagefp = fopen(_PATH_MESS, "r")) == NULL)
33686a62b8dSjtc 		error(_PATH_MESS);
33786a62b8dSjtc 	/* NOTREACHED */
33886a62b8dSjtc 
33986a62b8dSjtc 	if ((Energyvoidfp = fopen(_PATH_VOID, "r+")) == NULL)
34086a62b8dSjtc 		error(_PATH_VOID);
34127984797Sjmc 	if (fstat(fileno(Energyvoidfp), &sb) == -1)
34227984797Sjmc 		error("stat");
34327984797Sjmc 	if (sb.st_size == 0) {
34427984797Sjmc 		/* initialize grail to new location */
34527984797Sjmc 		Enrgyvoid.ev_active = TRUE;
34627984797Sjmc 		Enrgyvoid.ev_x = ROLL(-1.0e6, 2.0e6);
34727984797Sjmc 		Enrgyvoid.ev_y = ROLL(-1.0e6, 2.0e6);
34827984797Sjmc 		writevoid(&Enrgyvoid, 0L);
34927984797Sjmc 	}
35027984797Sjmc 
35186a62b8dSjtc 	/* NOTREACHED */
35286a62b8dSjtc 
353c4816c32Scgd 	srandom((unsigned) time(NULL));	/* prime random numbers */
35486a62b8dSjtc }
35586a62b8dSjtc 
3565305281bSdholland static long
rollnewplayer(void)357c7a109ccSdholland rollnewplayer(void)
35886a62b8dSjtc {
35986a62b8dSjtc 	int     chartype;	/* character type */
36086a62b8dSjtc 	int     ch;		/* input */
36186a62b8dSjtc 
36286a62b8dSjtc 	initplayer(&Player);	/* initialize player structure */
36386a62b8dSjtc 
36486a62b8dSjtc 	clear();
36586a62b8dSjtc 	mvaddstr(4, 21, "Which type of character do you want:");
366a232aee2Slukem 	mvaddstr(8, 4,
367a232aee2Slukem "1:Magic User  2:Fighter  3:Elf  4:Dwarf  5:Halfling  6:Experimento  ");
36886a62b8dSjtc 	if (Wizard) {
36986a62b8dSjtc 		addstr("7:Super  ? ");
37086a62b8dSjtc 		chartype = getanswer("1234567", FALSE);
371a232aee2Slukem 	} else {
37286a62b8dSjtc 		addstr("?  ");
37386a62b8dSjtc 		chartype = getanswer("123456", FALSE);
37486a62b8dSjtc 	}
37586a62b8dSjtc 
376a232aee2Slukem 	do {
37786a62b8dSjtc 		genchar(chartype);	/* roll up a character */
37886a62b8dSjtc 
37986a62b8dSjtc 		/* print out results */
38086a62b8dSjtc 		mvprintw(12, 14,
38186a62b8dSjtc 		    "Strength    :  %2.0f  Quickness:  %2.0f  Mana       :  %2.0f\n",
38286a62b8dSjtc 		    Player.p_strength, Player.p_quickness, Player.p_mana);
38386a62b8dSjtc 		mvprintw(13, 14,
38486a62b8dSjtc 		    "Energy Level:  %2.0f  Brains   :  %2.0f  Magic Level:  %2.0f\n",
38586a62b8dSjtc 		    Player.p_energy, Player.p_brains, Player.p_magiclvl);
38686a62b8dSjtc 
38786a62b8dSjtc 		if (Player.p_type == C_EXPER || Player.p_type == C_SUPER)
38886a62b8dSjtc 			break;
38986a62b8dSjtc 
39086a62b8dSjtc 		mvaddstr(14, 14, "Type '1' to keep >");
39186a62b8dSjtc 		ch = getanswer(" ", TRUE);
39286a62b8dSjtc 	}
39386a62b8dSjtc 	while (ch != '1');
39486a62b8dSjtc 
39586a62b8dSjtc 	if (Player.p_type == C_EXPER || Player.p_type == C_SUPER)
39686a62b8dSjtc 		/* get coordinates for experimento */
397a232aee2Slukem 		for (;;) {
39886a62b8dSjtc 			mvaddstr(16, 0, "Enter the X Y coordinates of your experimento ? ");
39986a62b8dSjtc 			getstring(Databuf, SZ_DATABUF);
40086a62b8dSjtc 			sscanf(Databuf, "%lf %lf", &Player.p_x, &Player.p_y);
40186a62b8dSjtc 
40286a62b8dSjtc 			if (fabs(Player.p_x) > D_EXPER || fabs(Player.p_y) > D_EXPER)
40386a62b8dSjtc 				mvaddstr(17, 0, "Invalid coordinates.  Try again.\n");
40486a62b8dSjtc 			else
40586a62b8dSjtc 				break;
40686a62b8dSjtc 		}
40786a62b8dSjtc 
40886a62b8dSjtc 	for (;;)
40986a62b8dSjtc 		/* name the new character */
41086a62b8dSjtc 	{
41186a62b8dSjtc 		mvprintw(18, 0,
41286a62b8dSjtc 		    "Give your character a name [up to %d characters] ?  ", SZ_NAME - 1);
41386a62b8dSjtc 		getstring(Player.p_name, SZ_NAME);
41486a62b8dSjtc 		truncstring(Player.p_name);	/* remove trailing blanks */
41586a62b8dSjtc 
41686a62b8dSjtc 		if (Player.p_name[0] == '\0')
41786a62b8dSjtc 			/* no null names */
41886a62b8dSjtc 			mvaddstr(19, 0, "Invalid name.");
419a232aee2Slukem 		else
420a232aee2Slukem 			if (findname(Player.p_name, &Other) >= 0L)
42186a62b8dSjtc 				/* cannot have duplicate names */
42286a62b8dSjtc 				mvaddstr(19, 0, "Name already in use.");
42386a62b8dSjtc 			else
42486a62b8dSjtc 				/* name is acceptable */
42586a62b8dSjtc 				break;
42686a62b8dSjtc 
42786a62b8dSjtc 		addstr("  Pick another.\n");
42886a62b8dSjtc 	}
42986a62b8dSjtc 
43086a62b8dSjtc 	/* get a password for character */
43186a62b8dSjtc 	Echo = FALSE;
43286a62b8dSjtc 
433a232aee2Slukem 	do {
43486a62b8dSjtc 		mvaddstr(20, 0, "Give your character a password [up to 8 characters] ? ");
43586a62b8dSjtc 		getstring(Player.p_password, SZ_PASSWORD);
43696651fe7Shubertf 		mvaddstr(21, 0, "Enter again to verify: ");
43786a62b8dSjtc 		getstring(Databuf, SZ_PASSWORD);
43886a62b8dSjtc 	}
43986a62b8dSjtc 	while (strcmp(Player.p_password, Databuf) != 0);
44086a62b8dSjtc 
44186a62b8dSjtc 	Echo = TRUE;
44286a62b8dSjtc 
44386a62b8dSjtc 	return (allocrecord());
44486a62b8dSjtc }
44586a62b8dSjtc 
4465305281bSdholland static void
procmain(void)447c7a109ccSdholland procmain(void)
44886a62b8dSjtc {
44986a62b8dSjtc 	int     ch;		/* input */
45086a62b8dSjtc 	double  x;		/* desired new x coordinate */
45186a62b8dSjtc 	double  y;		/* desired new y coordinate */
45286a62b8dSjtc 	double  temp;		/* for temporary calculations */
45386a62b8dSjtc 	FILE   *fp;		/* for opening files */
454a232aee2Slukem 	int     loop;		/* a loop counter */
45586a62b8dSjtc 	bool    hasmoved = FALSE;	/* set if player has moved */
45686a62b8dSjtc 
45786a62b8dSjtc 	ch = inputoption();
45886a62b8dSjtc 	mvaddstr(4, 0, "\n\n");	/* clear status area */
45986a62b8dSjtc 
46086a62b8dSjtc 	move(7, 0);
46186a62b8dSjtc 	clrtobot();		/* clear data on bottom area of screen */
46286a62b8dSjtc 
46386a62b8dSjtc 	if (Player.p_specialtype == SC_VALAR && (ch == '1' || ch == '7'))
46486a62b8dSjtc 		/* valar cannot move */
46586a62b8dSjtc 		ch = ' ';
46686a62b8dSjtc 
467a232aee2Slukem 	switch (ch) {
46886a62b8dSjtc 	case 'K':		/* move up/north */
46986a62b8dSjtc 	case 'N':
47086a62b8dSjtc 		x = Player.p_x;
47186a62b8dSjtc 		y = Player.p_y + MAXMOVE();
47286a62b8dSjtc 		hasmoved = TRUE;
47386a62b8dSjtc 		break;
47486a62b8dSjtc 
47586a62b8dSjtc 	case 'J':		/* move down/south */
47686a62b8dSjtc 	case 'S':
47786a62b8dSjtc 		x = Player.p_x;
47886a62b8dSjtc 		y = Player.p_y - MAXMOVE();
47986a62b8dSjtc 		hasmoved = TRUE;
48086a62b8dSjtc 		break;
48186a62b8dSjtc 
48286a62b8dSjtc 	case 'L':		/* move right/east */
48386a62b8dSjtc 	case 'E':
48486a62b8dSjtc 		x = Player.p_x + MAXMOVE();
48586a62b8dSjtc 		y = Player.p_y;
48686a62b8dSjtc 		hasmoved = TRUE;
48786a62b8dSjtc 		break;
48886a62b8dSjtc 
48986a62b8dSjtc 	case 'H':		/* move left/west */
49086a62b8dSjtc 	case 'W':
49186a62b8dSjtc 		x = Player.p_x - MAXMOVE();
49286a62b8dSjtc 		y = Player.p_y;
49386a62b8dSjtc 		hasmoved = TRUE;
49486a62b8dSjtc 		break;
49586a62b8dSjtc 
49686a62b8dSjtc 	default:		/* rest */
49786a62b8dSjtc 		Player.p_energy += (Player.p_maxenergy + Player.p_shield) / 15.0
49886a62b8dSjtc 		    + Player.p_level / 3.0 + 2.0;
49986a62b8dSjtc 		Player.p_energy =
50086a62b8dSjtc 		    MIN(Player.p_energy, Player.p_maxenergy + Player.p_shield);
50186a62b8dSjtc 
50286a62b8dSjtc 		if (Player.p_status != S_CLOAKED)
50386a62b8dSjtc 			/* cannot find mana if cloaked */
50486a62b8dSjtc 		{
50586a62b8dSjtc 			Player.p_mana += (Circle + Player.p_level) / 4.0;
50686a62b8dSjtc 
50786a62b8dSjtc 			if (drandom() < 0.2 && Player.p_status == S_PLAYING && !Throne)
50886a62b8dSjtc 				/* wandering monster */
50986a62b8dSjtc 				encounter(-1);
51086a62b8dSjtc 		}
51186a62b8dSjtc 		break;
51286a62b8dSjtc 
51386a62b8dSjtc 	case 'X':		/* change/examine a character */
51486a62b8dSjtc 		changestats(TRUE);
51586a62b8dSjtc 		break;
51686a62b8dSjtc 
51786a62b8dSjtc 	case '1':		/* move */
518a232aee2Slukem 		for (loop = 3; loop; --loop) {
51986a62b8dSjtc 			mvaddstr(4, 0, "X Y Coordinates ? ");
52086a62b8dSjtc 			getstring(Databuf, SZ_DATABUF);
52186a62b8dSjtc 
52286a62b8dSjtc 			if (sscanf(Databuf, "%lf %lf", &x, &y) != 2)
52386a62b8dSjtc 				mvaddstr(5, 0, "Try again\n");
52486a62b8dSjtc 			else
525a232aee2Slukem 				if (distance(Player.p_x, x, Player.p_y, y) > MAXMOVE())
526a232aee2Slukem 					ILLMOVE();
527a232aee2Slukem 				else {
52886a62b8dSjtc 					hasmoved = TRUE;
52986a62b8dSjtc 					break;
53086a62b8dSjtc 				}
53186a62b8dSjtc 		}
53286a62b8dSjtc 		break;
53386a62b8dSjtc 
53486a62b8dSjtc 	case '2':		/* players */
53586a62b8dSjtc 		userlist(TRUE);
53686a62b8dSjtc 		break;
53786a62b8dSjtc 
53886a62b8dSjtc 	case '3':		/* message */
53986a62b8dSjtc 		mvaddstr(4, 0, "Message ? ");
54086a62b8dSjtc 		getstring(Databuf, SZ_DATABUF);
541a232aee2Slukem 		/* we open the file for writing to erase any data which is
542a232aee2Slukem 		 * already there */
54386a62b8dSjtc 		fp = fopen(_PATH_MESS, "w");
54486a62b8dSjtc 		if (Databuf[0] != '\0')
54586a62b8dSjtc 			fprintf(fp, "%s: %s", Player.p_name, Databuf);
54686a62b8dSjtc 		fclose(fp);
54786a62b8dSjtc 		break;
54886a62b8dSjtc 
54986a62b8dSjtc 	case '4':		/* stats */
55086a62b8dSjtc 		allstatslist();
55186a62b8dSjtc 		break;
55286a62b8dSjtc 
55386a62b8dSjtc 	case '5':		/* good-bye */
55486a62b8dSjtc 		leavegame();
555fbffadb9Smrg 		__unreachable();
55686a62b8dSjtc 		/* NOTREACHED */
55786a62b8dSjtc 
55886a62b8dSjtc 	case '6':		/* cloak */
55986a62b8dSjtc 		if (Player.p_level < MEL_CLOAK || Player.p_magiclvl < ML_CLOAK)
56086a62b8dSjtc 			ILLCMD();
56186a62b8dSjtc 		else
562a232aee2Slukem 			if (Player.p_status == S_CLOAKED)
563a232aee2Slukem 				Player.p_status = S_PLAYING;
564a232aee2Slukem 			else
565a232aee2Slukem 				if (Player.p_mana < MM_CLOAK)
566a232aee2Slukem 					mvaddstr(5, 0, "No mana left.\n");
567a232aee2Slukem 				else {
56886a62b8dSjtc 					Changed = TRUE;
56986a62b8dSjtc 					Player.p_mana -= MM_CLOAK;
57086a62b8dSjtc 					Player.p_status = S_CLOAKED;
57186a62b8dSjtc 				}
57286a62b8dSjtc 		break;
57386a62b8dSjtc 
57486a62b8dSjtc 	case '7':		/* teleport */
57586a62b8dSjtc 		/*
57686a62b8dSjtc 	         * conditions for teleport
57786a62b8dSjtc 	         *	- 20 per (level plus magic level)
57886a62b8dSjtc 	         *	- OR council of the wise or valar or ex-valar
57986a62b8dSjtc 	         *	- OR transport from throne
58086a62b8dSjtc 	         * transports from throne cost no mana
58186a62b8dSjtc 	         */
58286a62b8dSjtc 		if (Player.p_level < MEL_TELEPORT || Player.p_magiclvl < ML_TELEPORT)
58386a62b8dSjtc 			ILLCMD();
58486a62b8dSjtc 		else
585a232aee2Slukem 			for (loop = 3; loop; --loop) {
58686a62b8dSjtc 				mvaddstr(4, 0, "X Y Coordinates ? ");
58786a62b8dSjtc 				getstring(Databuf, SZ_DATABUF);
58886a62b8dSjtc 
589a232aee2Slukem 				if (sscanf(Databuf, "%lf %lf", &x, &y) == 2) {
59086a62b8dSjtc 					temp = distance(Player.p_x, x, Player.p_y, y);
59186a62b8dSjtc 					if (!Throne
59286a62b8dSjtc 					/* can transport anywhere from throne */
59386a62b8dSjtc 					    && Player.p_specialtype <= SC_COUNCIL
594a232aee2Slukem 					/* council, valar can transport
595a232aee2Slukem 					 * anywhere */
59686a62b8dSjtc 					    && temp > (Player.p_level + Player.p_magiclvl) * 20.0)
597a232aee2Slukem 						/* can only move 20 per exp.
598a232aee2Slukem 						 * level + mag. level */
59986a62b8dSjtc 						ILLMOVE();
600a232aee2Slukem 					else {
60186a62b8dSjtc 						temp = (temp / 75.0 + 1.0) * 20.0;	/* mana used */
60286a62b8dSjtc 
60386a62b8dSjtc 						if (!Throne && temp > Player.p_mana)
60486a62b8dSjtc 							mvaddstr(5, 0, "Not enough power for that distance.\n");
605a232aee2Slukem 						else {
60686a62b8dSjtc 							if (!Throne)
60786a62b8dSjtc 								Player.p_mana -= temp;
60886a62b8dSjtc 							hasmoved = TRUE;
60986a62b8dSjtc 							break;
61086a62b8dSjtc 						}
61186a62b8dSjtc 					}
61286a62b8dSjtc 				}
61386a62b8dSjtc 			}
61486a62b8dSjtc 		break;
61586a62b8dSjtc 
61686a62b8dSjtc 	case 'C':
61786a62b8dSjtc 	case '9':		/* monster */
61886a62b8dSjtc 		if (Throne)
61986a62b8dSjtc 			/* no monsters while on throne */
62086a62b8dSjtc 			mvaddstr(5, 0, "No monsters in the chamber!\n");
621a232aee2Slukem 		else
622a232aee2Slukem 			if (Player.p_specialtype != SC_VALAR)
62386a62b8dSjtc 				/* the valar cannot call monsters */
62486a62b8dSjtc 			{
62586a62b8dSjtc 				Player.p_sin += 1e-6;
62686a62b8dSjtc 				encounter(-1);
62786a62b8dSjtc 			}
62886a62b8dSjtc 		break;
62986a62b8dSjtc 
63086a62b8dSjtc 	case '0':		/* decree */
631a232aee2Slukem 		if (Wizard || (Player.p_specialtype == SC_KING && Throne))
63286a62b8dSjtc 			/* kings must be on throne to decree */
63386a62b8dSjtc 			dotampered();
63486a62b8dSjtc 		else
63586a62b8dSjtc 			ILLCMD();
63686a62b8dSjtc 		break;
63786a62b8dSjtc 
63886a62b8dSjtc 	case '8':		/* intervention */
63986a62b8dSjtc 		if (Wizard || Player.p_specialtype >= SC_COUNCIL)
64086a62b8dSjtc 			dotampered();
64186a62b8dSjtc 		else
64286a62b8dSjtc 			ILLCMD();
64386a62b8dSjtc 		break;
64486a62b8dSjtc 	}
64586a62b8dSjtc 
64686a62b8dSjtc 	if (hasmoved)
647a232aee2Slukem 		/* player has moved -- alter coordinates, and do random
648a232aee2Slukem 		 * monster */
64986a62b8dSjtc 	{
65086a62b8dSjtc 		altercoordinates(x, y, A_SPECIFIC);
65186a62b8dSjtc 
65286a62b8dSjtc 		if (drandom() < 0.2 && Player.p_status == S_PLAYING && !Throne)
65386a62b8dSjtc 			encounter(-1);
65486a62b8dSjtc 	}
65586a62b8dSjtc }
65686a62b8dSjtc 
6575305281bSdholland static void
titlelist(void)658c7a109ccSdholland titlelist(void)
65986a62b8dSjtc {
660a232aee2Slukem 	FILE   *fp;		/* used for opening various files */
661a232aee2Slukem 	bool    councilfound = FALSE;	/* set if we find a member of the
662a232aee2Slukem 					 * council */
66386a62b8dSjtc 	bool    kingfound = FALSE;	/* set if we find a king */
66486a62b8dSjtc 	double  hiexp, nxtexp;	/* used for finding the two highest players */
66586a62b8dSjtc 	double  hilvl, nxtlvl;	/* used for finding the two highest players */
666a232aee2Slukem 	char    hiname[21], nxtname[21];	/* used for finding the two
667a232aee2Slukem 						 * highest players */
66886a62b8dSjtc 
669a232aee2Slukem 	nxtexp = 0;
670a232aee2Slukem 	mvaddstr(0, 14,
671a232aee2Slukem 	    "W e l c o m e   t o   P h a n t a s i a (vers. 3.3.2)!");
67286a62b8dSjtc 
67386a62b8dSjtc 	/* print message of the day */
67486a62b8dSjtc 	if ((fp = fopen(_PATH_MOTD, "r")) != NULL
675a232aee2Slukem 	    && fgets(Databuf, SZ_DATABUF, fp) != NULL) {
67686a62b8dSjtc 		mvaddstr(2, 40 - strlen(Databuf) / 2, Databuf);
67786a62b8dSjtc 		fclose(fp);
67886a62b8dSjtc 	}
67986a62b8dSjtc 	/* search for king */
6805fb18dd9Sjsm 	fseek(Playersfp, 0L, SEEK_SET);
68186a62b8dSjtc 	while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
682a232aee2Slukem 		if (Other.p_specialtype == SC_KING &&
683a232aee2Slukem 		    Other.p_status != S_NOTUSED)
68486a62b8dSjtc 			/* found the king */
68586a62b8dSjtc 		{
686ebb769aeSdholland 			snprintf(Databuf, SZ_DATABUF,
687ebb769aeSdholland 			    "The present ruler is %s  Level:%.0f",
68886a62b8dSjtc 			    Other.p_name, Other.p_level);
68986a62b8dSjtc 			mvaddstr(4, 40 - strlen(Databuf) / 2, Databuf);
69086a62b8dSjtc 			kingfound = TRUE;
69186a62b8dSjtc 			break;
69286a62b8dSjtc 		}
69386a62b8dSjtc 	if (!kingfound)
69486a62b8dSjtc 		mvaddstr(4, 24, "There is no ruler at this time.");
69586a62b8dSjtc 
69686a62b8dSjtc 	/* search for valar */
6975fb18dd9Sjsm 	fseek(Playersfp, 0L, SEEK_SET);
69886a62b8dSjtc 	while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
69986a62b8dSjtc 		if (Other.p_specialtype == SC_VALAR && Other.p_status != S_NOTUSED)
70086a62b8dSjtc 			/* found the valar */
70186a62b8dSjtc 		{
702ebb769aeSdholland 			snprintf(Databuf, SZ_DATABUF,
703ebb769aeSdholland 				"The Valar is %s   Login:  %s",
704ebb769aeSdholland 				Other.p_name, Other.p_login);
70586a62b8dSjtc 			mvaddstr(6, 40 - strlen(Databuf) / 2, Databuf);
70686a62b8dSjtc 			break;
70786a62b8dSjtc 		}
70886a62b8dSjtc 	/* search for council of the wise */
7095fb18dd9Sjsm 	fseek(Playersfp, 0L, SEEK_SET);
71086a62b8dSjtc 	Lines = 10;
71186a62b8dSjtc 	while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
71286a62b8dSjtc 		if (Other.p_specialtype == SC_COUNCIL && Other.p_status != S_NOTUSED)
71386a62b8dSjtc 			/* found a member of the council */
71486a62b8dSjtc 		{
715a232aee2Slukem 			if (!councilfound) {
71686a62b8dSjtc 				mvaddstr(8, 30, "Council of the Wise:");
71786a62b8dSjtc 				councilfound = TRUE;
71886a62b8dSjtc 			}
71986a62b8dSjtc 			/* This assumes a finite (<=5) number of C.O.W.: */
720ebb769aeSdholland 			snprintf(Databuf, SZ_DATABUF,
721ebb769aeSdholland 				"%s   Login:  %s", Other.p_name, Other.p_login);
72286a62b8dSjtc 			mvaddstr(Lines++, 40 - strlen(Databuf) / 2, Databuf);
72386a62b8dSjtc 		}
72486a62b8dSjtc 	/* search for the two highest players */
72586a62b8dSjtc 	nxtname[0] = hiname[0] = '\0';
72686a62b8dSjtc 	hiexp = 0.0;
72786a62b8dSjtc 	nxtlvl = hilvl = 0;
72886a62b8dSjtc 
7295fb18dd9Sjsm 	fseek(Playersfp, 0L, SEEK_SET);
73086a62b8dSjtc 	while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
73186a62b8dSjtc 		if (Other.p_experience > hiexp && Other.p_specialtype <= SC_KING && Other.p_status != S_NOTUSED)
73286a62b8dSjtc 			/* highest found so far */
73386a62b8dSjtc 		{
73486a62b8dSjtc 			nxtexp = hiexp;
73586a62b8dSjtc 			hiexp = Other.p_experience;
73686a62b8dSjtc 			nxtlvl = hilvl;
73786a62b8dSjtc 			hilvl = Other.p_level;
73886a62b8dSjtc 			strcpy(nxtname, hiname);
73986a62b8dSjtc 			strcpy(hiname, Other.p_name);
740a232aee2Slukem 		} else
741a232aee2Slukem 			if (Other.p_experience > nxtexp
74286a62b8dSjtc 			    && Other.p_specialtype <= SC_KING
74386a62b8dSjtc 			    && Other.p_status != S_NOTUSED)
74486a62b8dSjtc 				/* next highest found so far */
74586a62b8dSjtc 			{
74686a62b8dSjtc 				nxtexp = Other.p_experience;
74786a62b8dSjtc 				nxtlvl = Other.p_level;
74886a62b8dSjtc 				strcpy(nxtname, Other.p_name);
74986a62b8dSjtc 			}
75086a62b8dSjtc 	mvaddstr(15, 28, "Highest characters are:");
751ebb769aeSdholland 	snprintf(Databuf, SZ_DATABUF,
752ebb769aeSdholland 	    "%s  Level:%.0f   and   %s  Level:%.0f",
75386a62b8dSjtc 	    hiname, hilvl, nxtname, nxtlvl);
75486a62b8dSjtc 	mvaddstr(17, 40 - strlen(Databuf) / 2, Databuf);
75586a62b8dSjtc 
75686a62b8dSjtc 	/* print last to die */
75786a62b8dSjtc 	if ((fp = fopen(_PATH_LASTDEAD, "r")) != NULL
758a232aee2Slukem 	    && fgets(Databuf, SZ_DATABUF, fp) != NULL) {
75986a62b8dSjtc 		mvaddstr(19, 25, "The last character to die was:");
76086a62b8dSjtc 		mvaddstr(20, 40 - strlen(Databuf) / 2, Databuf);
76186a62b8dSjtc 	}
762dad51bf4Schristos 	if (fp)
763dad51bf4Schristos 		fclose(fp);
76486a62b8dSjtc 	refresh();
76586a62b8dSjtc }
76686a62b8dSjtc 
7675305281bSdholland static long
recallplayer(void)768c7a109ccSdholland recallplayer(void)
76986a62b8dSjtc {
77086a62b8dSjtc 	long    loc = 0L;	/* location in player file */
771a232aee2Slukem 	int     loop;		/* loop counter */
77286a62b8dSjtc 	int     ch;		/* input */
77386a62b8dSjtc 
77486a62b8dSjtc 	clear();
77586a62b8dSjtc 	mvprintw(10, 0, "What was your character's name ? ");
77686a62b8dSjtc 	getstring(Databuf, SZ_NAME);
77786a62b8dSjtc 	truncstring(Databuf);
77886a62b8dSjtc 
77986a62b8dSjtc 	if ((loc = findname(Databuf, &Player)) >= 0L)
78086a62b8dSjtc 		/* found character */
78186a62b8dSjtc 	{
78286a62b8dSjtc 		Echo = FALSE;
78386a62b8dSjtc 
784a232aee2Slukem 		for (loop = 0; loop < 2; ++loop) {
78586a62b8dSjtc 			/* prompt for password */
78686a62b8dSjtc 			mvaddstr(11, 0, "Password ? ");
78786a62b8dSjtc 			getstring(Databuf, SZ_PASSWORD);
78886a62b8dSjtc 			if (strcmp(Databuf, Player.p_password) == 0)
78986a62b8dSjtc 				/* password good */
79086a62b8dSjtc 			{
79186a62b8dSjtc 				Echo = TRUE;
79286a62b8dSjtc 
79386a62b8dSjtc 				if (Player.p_status != S_OFF)
794a232aee2Slukem 					/* player did not exit normally last
795a232aee2Slukem 					 * time */
79686a62b8dSjtc 				{
79786a62b8dSjtc 					clear();
79886a62b8dSjtc 					addstr("Your character did not exit normally last time.\n");
79986a62b8dSjtc 					addstr("If you think you have good cause to have your character saved,\n");
80086a62b8dSjtc 					printw("you may quit and mail your reason to 'root'.\n");
80186a62b8dSjtc 					addstr("Otherwise, continuing spells certain death.\n");
80286a62b8dSjtc 					addstr("Do you want to quit ? ");
80386a62b8dSjtc 					ch = getanswer("YN", FALSE);
804a232aee2Slukem 					if (ch == 'Y') {
80586a62b8dSjtc 						Player.p_status = S_HUNGUP;
80686a62b8dSjtc 						writerecord(&Player, loc);
80786a62b8dSjtc 						cleanup(TRUE);
80886a62b8dSjtc 						/* NOTREACHED */
80986a62b8dSjtc 					}
81086a62b8dSjtc 					death("Stupidity");
81186a62b8dSjtc 					/* NOTREACHED */
81286a62b8dSjtc 				}
81386a62b8dSjtc 				return (loc);
814a232aee2Slukem 			} else
81586a62b8dSjtc 				mvaddstr(12, 0, "No good.\n");
81686a62b8dSjtc 		}
81786a62b8dSjtc 
81886a62b8dSjtc 		Echo = TRUE;
819a232aee2Slukem 	} else
82086a62b8dSjtc 		mvaddstr(11, 0, "Not found.\n");
82186a62b8dSjtc 
82286a62b8dSjtc 	more(13);
82386a62b8dSjtc 	return (-1L);
82486a62b8dSjtc }
82586a62b8dSjtc 
8265305281bSdholland static void
neatstuff(void)827c7a109ccSdholland neatstuff(void)
82886a62b8dSjtc {
82986a62b8dSjtc 	double  temp;		/* for temporary calculations */
83086a62b8dSjtc 	int     ch;		/* input */
83186a62b8dSjtc 
832a232aee2Slukem 	switch ((int) ROLL(0.0, 100.0)) {
83386a62b8dSjtc 	case 1:
83486a62b8dSjtc 	case 2:
835a232aee2Slukem 		if (Player.p_poison > 0.0) {
83686a62b8dSjtc 			mvaddstr(4, 0, "You've found a medic!  How much will you offer to be cured ? ");
83786a62b8dSjtc 			temp = floor(infloat());
83886a62b8dSjtc 			if (temp < 0.0 || temp > Player.p_gold)
83986a62b8dSjtc 				/* negative gold, or more than available */
84086a62b8dSjtc 			{
84186a62b8dSjtc 				mvaddstr(6, 0, "He was not amused, and made you worse.\n");
84286a62b8dSjtc 				Player.p_poison += 1.0;
843a232aee2Slukem 			} else
844a232aee2Slukem 				if (drandom() / 2.0 > (temp + 1.0) / MAX(Player.p_gold, 1))
84586a62b8dSjtc 					/* medic wants 1/2 of available gold */
84686a62b8dSjtc 					mvaddstr(5, 0, "Sorry, he wasn't interested.\n");
847a232aee2Slukem 				else {
84886a62b8dSjtc 					mvaddstr(5, 0, "He accepted.");
84986a62b8dSjtc 					Player.p_poison = MAX(0.0, Player.p_poison - 1.0);
85086a62b8dSjtc 					Player.p_gold -= temp;
85186a62b8dSjtc 				}
85286a62b8dSjtc 		}
85386a62b8dSjtc 		break;
85486a62b8dSjtc 
85586a62b8dSjtc 	case 3:
85686a62b8dSjtc 		mvaddstr(4, 0, "You've been caught raping and pillaging!\n");
85786a62b8dSjtc 		Player.p_experience += 4000.0;
85886a62b8dSjtc 		Player.p_sin += 0.5;
85986a62b8dSjtc 		break;
86086a62b8dSjtc 
86186a62b8dSjtc 	case 4:
86286a62b8dSjtc 		temp = ROLL(10.0, 75.0);
86386a62b8dSjtc 		mvprintw(4, 0, "You've found %.0f gold pieces, want them ? ", temp);
86486a62b8dSjtc 		ch = getanswer("NY", FALSE);
86586a62b8dSjtc 
86686a62b8dSjtc 		if (ch == 'Y')
86786a62b8dSjtc 			collecttaxes(temp, 0.0);
86886a62b8dSjtc 		break;
86986a62b8dSjtc 
87086a62b8dSjtc 	case 5:
871a232aee2Slukem 		if (Player.p_sin > 1.0) {
87286a62b8dSjtc 			mvaddstr(4, 0, "You've found a Holy Orb!\n");
87386a62b8dSjtc 			Player.p_sin -= 0.25;
87486a62b8dSjtc 		}
87586a62b8dSjtc 		break;
87686a62b8dSjtc 
87786a62b8dSjtc 	case 6:
878a232aee2Slukem 		if (Player.p_poison < 1.0) {
87986a62b8dSjtc 			mvaddstr(4, 0, "You've been hit with a plague!\n");
88086a62b8dSjtc 			Player.p_poison += 1.0;
88186a62b8dSjtc 		}
88286a62b8dSjtc 		break;
88386a62b8dSjtc 
88486a62b8dSjtc 	case 7:
88586a62b8dSjtc 		mvaddstr(4, 0, "You've found some holy water.\n");
88686a62b8dSjtc 		++Player.p_holywater;
88786a62b8dSjtc 		break;
88886a62b8dSjtc 
88986a62b8dSjtc 	case 8:
89086a62b8dSjtc 		mvaddstr(4, 0, "You've met a Guru. . .");
89186a62b8dSjtc 		if (drandom() * Player.p_sin > 1.0)
89286a62b8dSjtc 			addstr("You disgusted him with your sins!\n");
893a232aee2Slukem 		else
894a232aee2Slukem 			if (Player.p_poison > 0.0) {
89586a62b8dSjtc 				addstr("He looked kindly upon you, and cured you.\n");
89686a62b8dSjtc 				Player.p_poison = 0.0;
897a232aee2Slukem 			} else {
89886a62b8dSjtc 				addstr("He rewarded you for your virtue.\n");
89986a62b8dSjtc 				Player.p_mana += 50.0;
90086a62b8dSjtc 				Player.p_shield += 2.0;
90186a62b8dSjtc 			}
90286a62b8dSjtc 		break;
90386a62b8dSjtc 
90486a62b8dSjtc 	case 9:
90586a62b8dSjtc 		mvaddstr(4, 0, "You've found an amulet.\n");
90686a62b8dSjtc 		++Player.p_amulets;
90786a62b8dSjtc 		break;
90886a62b8dSjtc 
90986a62b8dSjtc 	case 10:
910a232aee2Slukem 		if (Player.p_blindness) {
91186a62b8dSjtc 			mvaddstr(4, 0, "You've regained your sight!\n");
91286a62b8dSjtc 			Player.p_blindness = FALSE;
91386a62b8dSjtc 		}
91486a62b8dSjtc 		break;
91586a62b8dSjtc 
91686a62b8dSjtc 	default:		/* deal with poison */
917a232aee2Slukem 		if (Player.p_poison > 0.0) {
91886a62b8dSjtc 			temp = Player.p_poison * Statptr->c_weakness
91986a62b8dSjtc 			    * Player.p_maxenergy / 600.0;
92086a62b8dSjtc 			if (Player.p_energy > Player.p_maxenergy / 10.0
92186a62b8dSjtc 			    && temp + 5.0 < Player.p_energy)
92286a62b8dSjtc 				Player.p_energy -= temp;
92386a62b8dSjtc 		}
92486a62b8dSjtc 		break;
92586a62b8dSjtc 	}
92686a62b8dSjtc }
92786a62b8dSjtc 
9285305281bSdholland static void
genchar(int type)929c7a109ccSdholland genchar(int type)
93086a62b8dSjtc {
931a232aee2Slukem 	int     subscript;	/* used for subscripting into Stattable */
932092d3130Sjsm 	const struct charstats *statptr; /* for pointing into Stattable */
93386a62b8dSjtc 
93486a62b8dSjtc 	subscript = type - '1';
93586a62b8dSjtc 
93686a62b8dSjtc 	if (subscript < C_MAGIC || subscript > C_EXPER)
93786a62b8dSjtc 		if (subscript != C_SUPER || !Wizard)
93886a62b8dSjtc 			/* fighter is default */
93986a62b8dSjtc 			subscript = C_FIGHTER;
94086a62b8dSjtc 
94186a62b8dSjtc 	statptr = &Stattable[subscript];
94286a62b8dSjtc 
94386a62b8dSjtc 	Player.p_quickness =
94486a62b8dSjtc 	    ROLL(statptr->c_quickness.base, statptr->c_quickness.interval);
94586a62b8dSjtc 	Player.p_strength =
94686a62b8dSjtc 	    ROLL(statptr->c_strength.base, statptr->c_strength.interval);
94786a62b8dSjtc 	Player.p_mana =
94886a62b8dSjtc 	    ROLL(statptr->c_mana.base, statptr->c_mana.interval);
94986a62b8dSjtc 	Player.p_maxenergy =
95086a62b8dSjtc 	    Player.p_energy =
95186a62b8dSjtc 	    ROLL(statptr->c_energy.base, statptr->c_energy.interval);
95286a62b8dSjtc 	Player.p_brains =
95386a62b8dSjtc 	    ROLL(statptr->c_brains.base, statptr->c_brains.interval);
95486a62b8dSjtc 	Player.p_magiclvl =
95586a62b8dSjtc 	    ROLL(statptr->c_magiclvl.base, statptr->c_magiclvl.interval);
95686a62b8dSjtc 
95786a62b8dSjtc 	Player.p_type = subscript;
95886a62b8dSjtc 
95986a62b8dSjtc 	if (Player.p_type == C_HALFLING)
96086a62b8dSjtc 		/* give halfling some experience */
96186a62b8dSjtc 		Player.p_experience = ROLL(600.0, 200.0);
96286a62b8dSjtc }
96386a62b8dSjtc 
9645305281bSdholland static void
playinit(void)965c7a109ccSdholland playinit(void)
96686a62b8dSjtc {
967*0e5bc969Sandvar 	/* catch/ignore signals */
96886a62b8dSjtc 
96986a62b8dSjtc #ifdef	BSD41
97086a62b8dSjtc 	sigignore(SIGQUIT);
97186a62b8dSjtc 	sigignore(SIGALRM);
97286a62b8dSjtc 	sigignore(SIGTERM);
97386a62b8dSjtc 	sigignore(SIGTSTP);
97486a62b8dSjtc 	sigignore(SIGTTIN);
97586a62b8dSjtc 	sigignore(SIGTTOU);
97686a62b8dSjtc 	sighold(SIGINT);
97786a62b8dSjtc 	sigset(SIGHUP, ill_sig);
97886a62b8dSjtc 	sigset(SIGTRAP, ill_sig);
97986a62b8dSjtc 	sigset(SIGIOT, ill_sig);
98086a62b8dSjtc 	sigset(SIGEMT, ill_sig);
98186a62b8dSjtc 	sigset(SIGFPE, ill_sig);
98286a62b8dSjtc 	sigset(SIGBUS, ill_sig);
98386a62b8dSjtc 	sigset(SIGSEGV, ill_sig);
98486a62b8dSjtc 	sigset(SIGSYS, ill_sig);
98586a62b8dSjtc 	sigset(SIGPIPE, ill_sig);
98686a62b8dSjtc #endif
98786a62b8dSjtc #ifdef	BSD42
98886a62b8dSjtc 	signal(SIGQUIT, ill_sig);
98986a62b8dSjtc 	signal(SIGALRM, SIG_IGN);
99086a62b8dSjtc 	signal(SIGTERM, SIG_IGN);
99186a62b8dSjtc 	signal(SIGTSTP, SIG_IGN);
99286a62b8dSjtc 	signal(SIGTTIN, SIG_IGN);
99386a62b8dSjtc 	signal(SIGTTOU, SIG_IGN);
99486a62b8dSjtc 	signal(SIGINT, ill_sig);
99586a62b8dSjtc 	signal(SIGHUP, SIG_DFL);
99686a62b8dSjtc 	signal(SIGTRAP, ill_sig);
99786a62b8dSjtc 	signal(SIGIOT, ill_sig);
99886a62b8dSjtc 	signal(SIGEMT, ill_sig);
99986a62b8dSjtc 	signal(SIGFPE, ill_sig);
100086a62b8dSjtc 	signal(SIGBUS, ill_sig);
100186a62b8dSjtc 	signal(SIGSEGV, ill_sig);
100286a62b8dSjtc 	signal(SIGSYS, ill_sig);
100386a62b8dSjtc 	signal(SIGPIPE, ill_sig);
100486a62b8dSjtc #endif
100586a62b8dSjtc #ifdef	SYS3
100686a62b8dSjtc 	signal(SIGINT, SIG_IGN);
100786a62b8dSjtc 	signal(SIGQUIT, SIG_IGN);
100886a62b8dSjtc 	signal(SIGTERM, SIG_IGN);
100986a62b8dSjtc 	signal(SIGALRM, SIG_IGN);
101086a62b8dSjtc 	signal(SIGHUP, ill_sig);
101186a62b8dSjtc 	signal(SIGTRAP, ill_sig);
101286a62b8dSjtc 	signal(SIGIOT, ill_sig);
101386a62b8dSjtc 	signal(SIGEMT, ill_sig);
101486a62b8dSjtc 	signal(SIGFPE, ill_sig);
101586a62b8dSjtc 	signal(SIGBUS, ill_sig);
101686a62b8dSjtc 	signal(SIGSEGV, ill_sig);
101786a62b8dSjtc 	signal(SIGSYS, ill_sig);
101886a62b8dSjtc 	signal(SIGPIPE, ill_sig);
101986a62b8dSjtc #endif
102086a62b8dSjtc #ifdef	SYS5
102186a62b8dSjtc 	signal(SIGINT, SIG_IGN);
102286a62b8dSjtc 	signal(SIGQUIT, SIG_IGN);
102386a62b8dSjtc 	signal(SIGTERM, SIG_IGN);
102486a62b8dSjtc 	signal(SIGALRM, SIG_IGN);
102586a62b8dSjtc 	signal(SIGHUP, ill_sig);
102686a62b8dSjtc 	signal(SIGTRAP, ill_sig);
102786a62b8dSjtc 	signal(SIGIOT, ill_sig);
102886a62b8dSjtc 	signal(SIGEMT, ill_sig);
102986a62b8dSjtc 	signal(SIGFPE, ill_sig);
103086a62b8dSjtc 	signal(SIGBUS, ill_sig);
103186a62b8dSjtc 	signal(SIGSEGV, ill_sig);
103286a62b8dSjtc 	signal(SIGSYS, ill_sig);
103386a62b8dSjtc 	signal(SIGPIPE, ill_sig);
103486a62b8dSjtc #endif
103586a62b8dSjtc 
1036432ec044Sdrochner 	if (!initscr()) {	/* turn on curses */
1037432ec044Sdrochner 		fprintf(stderr, "couldn't initialize screen\n");
1038432ec044Sdrochner 		exit (0);
1039432ec044Sdrochner 	}
104086a62b8dSjtc 	noecho();		/* do not echo input */
1041b74595a2Sblymn 	cbreak();		/* do not process erase, kill */
104286a62b8dSjtc 	clear();
104386a62b8dSjtc 	refresh();
104486a62b8dSjtc 	Windows = TRUE;		/* mark the state */
104586a62b8dSjtc }
104686a62b8dSjtc 
1047a232aee2Slukem void
cleanup(int doexit)1048c7a109ccSdholland cleanup(int doexit)
104986a62b8dSjtc {
1050a232aee2Slukem 	if (Windows) {
105186a62b8dSjtc 		move(LINES - 2, 0);
105286a62b8dSjtc 		refresh();
1053b74595a2Sblymn 		nocbreak();
105486a62b8dSjtc 		endwin();
105586a62b8dSjtc 	}
105650134cf2Sjsm 	if (Playersfp)
105786a62b8dSjtc 		fclose(Playersfp);
105850134cf2Sjsm 	if (Monstfp)
105986a62b8dSjtc 		fclose(Monstfp);
106050134cf2Sjsm 	if (Messagefp)
106186a62b8dSjtc 		fclose(Messagefp);
106250134cf2Sjsm 	if (Energyvoidfp)
106386a62b8dSjtc 		fclose(Energyvoidfp);
106486a62b8dSjtc 
106586a62b8dSjtc 	if (doexit)
106686a62b8dSjtc 		exit(0);
106786a62b8dSjtc 	/* NOTREACHED */
106886a62b8dSjtc }
1069