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