xref: /netbsd/games/phantasia/gamesupport.c (revision bf9ec67e)
1 /*	$NetBSD: gamesupport.c,v 1.6 1999/09/08 21:57:19 jsm Exp $	*/
2 
3 /*
4  * gamesupport.c - auxiliary routines for support of Phantasia
5  */
6 
7 #include "include.h"
8 
9 void
10 changestats(ingameflag)
11 	bool    ingameflag;
12 {
13 	static char flag[2] =	/* for printing values of bools */
14 	{'F', 'T'};
15 	struct player *playerp;	/* pointer to structure to alter */
16 	const char   *prompt;		/* pointer to prompt string */
17 	int     c;		/* input */
18 	int     today;		/* day of year of today */
19 	int     temp;		/* temporary variable */
20 	long    loc;		/* location in player file */
21 	time_t  now;		/* time now */
22 	double  dtemp;		/* temporary variable */
23 	bool   *bptr;		/* pointer to bool item to change */
24 	double *dptr;		/* pointer to double item to change */
25 	short  *sptr;		/* pointer to short item to change */
26 
27 	clear();
28 
29 	for (;;)
30 		/* get name of player to examine/alter */
31 	{
32 		mvaddstr(5, 0, "Which character do you want to look at ? ");
33 		getstring(Databuf, SZ_DATABUF);
34 		truncstring(Databuf);
35 
36 		if (Databuf[0] == '\0')
37 			userlist(ingameflag);
38 		else
39 			break;
40 	}
41 
42 	loc = -1L;
43 
44 	if (!ingameflag)
45 		/* use 'Player' structure */
46 		playerp = &Player;
47 	else
48 		if (strcmp(Databuf, Player.p_name) == 0)
49 			/* alter/examine current player */
50 		{
51 			playerp = &Player;
52 			loc = Fileloc;
53 		} else
54 			/* use 'Other' structure */
55 			playerp = &Other;
56 
57 	/* find player on file */
58 	if (loc < 0L && (loc = findname(Databuf, playerp)) < 0L)
59 		/* didn't find player */
60 	{
61 		clear();
62 		mvaddstr(11, 0, "Not found.");
63 		return;
64 	}
65 	time(&now);
66 	today = localtime(&now)->tm_yday;
67 
68 	clear();
69 
70 	for (;;)
71 		/* print player structure, and prompt for action */
72 	{
73 		mvprintw(0, 0, "A:Name         %s\n", playerp->p_name);
74 
75 		if (Wizard)
76 			printw("B:Password     %s\n", playerp->p_password);
77 		else
78 			addstr("B:Password     XXXXXXXX\n");
79 
80 		printw(" :Login        %s\n", playerp->p_login);
81 
82 		printw("C:Experience   %.0f\n", playerp->p_experience);
83 		printw("D:Level        %.0f\n", playerp->p_level);
84 		printw("E:Strength     %.0f\n", playerp->p_strength);
85 		printw("F:Sword        %.0f\n", playerp->p_sword);
86 		printw(" :Might        %.0f\n", playerp->p_might);
87 		printw("G:Energy       %.0f\n", playerp->p_energy);
88 		printw("H:Max-Energy   %.0f\n", playerp->p_maxenergy);
89 		printw("I:Shield       %.0f\n", playerp->p_shield);
90 		printw("J:Quickness    %.0f\n", playerp->p_quickness);
91 		printw("K:Quicksilver  %.0f\n", playerp->p_quksilver);
92 		printw(" :Speed        %.0f\n", playerp->p_speed);
93 		printw("L:Magic Level  %.0f\n", playerp->p_magiclvl);
94 		printw("M:Mana         %.0f\n", playerp->p_mana);
95 		printw("N:Brains       %.0f\n", playerp->p_brains);
96 
97 		if (Wizard || playerp->p_specialtype != SC_VALAR)
98 			mvaddstr(0, 40, descrstatus(playerp));
99 
100 		mvprintw(1, 40, "O:Poison       %0.3f\n", playerp->p_poison);
101 		mvprintw(2, 40, "P:Gold         %.0f\n", playerp->p_gold);
102 		mvprintw(3, 40, "Q:Gem          %.0f\n", playerp->p_gems);
103 		mvprintw(4, 40, "R:Sin          %0.3f\n", playerp->p_sin);
104 		if (Wizard) {
105 			mvprintw(5, 40, "S:X-coord      %.0f\n", playerp->p_x);
106 			mvprintw(6, 40, "T:Y-coord      %.0f\n", playerp->p_y);
107 		} else {
108 			mvaddstr(5, 40, "S:X-coord      ?\n");
109 			mvaddstr(6, 40, "T:Y-coord      ?\n");
110 		}
111 
112 		mvprintw(7, 40, "U:Age          %ld\n", playerp->p_age);
113 		mvprintw(8, 40, "V:Degenerated  %d\n", playerp->p_degenerated);
114 
115 		mvprintw(9, 40, "W:Type         %d (%s)\n",
116 		    playerp->p_type, descrtype(playerp, FALSE) + 1);
117 		mvprintw(10, 40, "X:Special Type %d\n", playerp->p_specialtype);
118 		mvprintw(11, 40, "Y:Lives        %d\n", playerp->p_lives);
119 		mvprintw(12, 40, "Z:Crowns       %d\n", playerp->p_crowns);
120 		mvprintw(13, 40, "0:Charms       %d\n", playerp->p_charms);
121 		mvprintw(14, 40, "1:Amulets      %d\n", playerp->p_amulets);
122 		mvprintw(15, 40, "2:Holy Water   %d\n", playerp->p_holywater);
123 
124 		temp = today - playerp->p_lastused;
125 		if (temp < 0)
126 			/* last year */
127 			temp += 365;
128 		mvprintw(16, 40, "3:Lastused     %d  (%d)\n", playerp->p_lastused, temp);
129 
130 		mvprintw(18, 8, "4:Palantir %c  5:Blessing %c  6:Virgin %c  7:Blind %c",
131 		    flag[(int)playerp->p_palantir],
132 		    flag[(int)playerp->p_blessing],
133 		    flag[(int)playerp->p_virgin],
134 		    flag[(int)playerp->p_blindness]);
135 
136 		if (!Wizard)
137 			mvprintw(19, 8, "8:Ring    %c",
138 			    flag[playerp->p_ring.ring_type != R_NONE]);
139 		else
140 			mvprintw(19, 8, "8:Ring    %d  9:Duration %d",
141 			    playerp->p_ring.ring_type, playerp->p_ring.ring_duration);
142 
143 		if (!Wizard
144 		/* not wizard */
145 		    && (ingameflag || strcmp(Login, playerp->p_login) != 0))
146 			/* in game or not examining own character */
147 		{
148 			if (ingameflag) {
149 				more(LINES - 1);
150 				clear();
151 				return;
152 			} else
153 				cleanup(TRUE);
154 			/* NOTREACHED */
155 		}
156 		mvaddstr(20, 0, "!:Quit       ?:Delete");
157 		mvaddstr(21, 0, "What would you like to change ? ");
158 
159 		if (Wizard)
160 			c = getanswer(" ", TRUE);
161 		else
162 			/* examining own player; allow to change name and
163 			 * password */
164 			c = getanswer("!BA", FALSE);
165 
166 		switch (c) {
167 		case 'A':	/* change name */
168 		case 'B':	/* change password */
169 			if (!Wizard)
170 				/* prompt for password */
171 			{
172 				mvaddstr(23, 0, "Password ? ");
173 				Echo = FALSE;
174 				getstring(Databuf, 9);
175 				Echo = TRUE;
176 				if (strcmp(Databuf, playerp->p_password) != 0)
177 					continue;
178 			}
179 			if (c == 'A')
180 				/* get new name */
181 			{
182 				mvaddstr(23, 0, "New name: ");
183 				getstring(Databuf, SZ_NAME);
184 				truncstring(Databuf);
185 				if (Databuf[0] != '\0')
186 					if (Wizard || findname(Databuf, &Other) < 0L)
187 						strcpy(playerp->p_name, Databuf);
188 			} else
189 				/* get new password */
190 			{
191 				if (!Wizard)
192 					Echo = FALSE;
193 
194 				do
195 					/* get two copies of new password
196 					 * until they match */
197 				{
198 					/* get first copy */
199 					mvaddstr(23, 0, "New password ? ");
200 					getstring(Databuf, SZ_PASSWORD);
201 					if (Databuf[0] == '\0')
202 						break;
203 
204 					/* get second copy */
205 					mvaddstr(23, 0, "One more time ? ");
206 					getstring(playerp->p_password, SZ_PASSWORD);
207 				}
208 				while (strcmp(playerp->p_password, Databuf) != 0);
209 
210 				Echo = TRUE;
211 			}
212 
213 			continue;
214 
215 		case 'C':	/* change experience */
216 			prompt = "experience";
217 			dptr = &playerp->p_experience;
218 			goto DALTER;
219 
220 		case 'D':	/* change level */
221 			prompt = "level";
222 			dptr = &playerp->p_level;
223 			goto DALTER;
224 
225 		case 'E':	/* change strength */
226 			prompt = "strength";
227 			dptr = &playerp->p_strength;
228 			goto DALTER;
229 
230 		case 'F':	/* change swords */
231 			prompt = "sword";
232 			dptr = &playerp->p_sword;
233 			goto DALTER;
234 
235 		case 'G':	/* change energy */
236 			prompt = "energy";
237 			dptr = &playerp->p_energy;
238 			goto DALTER;
239 
240 		case 'H':	/* change maximum energy */
241 			prompt = "max energy";
242 			dptr = &playerp->p_maxenergy;
243 			goto DALTER;
244 
245 		case 'I':	/* change shields */
246 			prompt = "shield";
247 			dptr = &playerp->p_shield;
248 			goto DALTER;
249 
250 		case 'J':	/* change quickness */
251 			prompt = "quickness";
252 			dptr = &playerp->p_quickness;
253 			goto DALTER;
254 
255 		case 'K':	/* change quicksilver */
256 			prompt = "quicksilver";
257 			dptr = &playerp->p_quksilver;
258 			goto DALTER;
259 
260 		case 'L':	/* change magic */
261 			prompt = "magic level";
262 			dptr = &playerp->p_magiclvl;
263 			goto DALTER;
264 
265 		case 'M':	/* change mana */
266 			prompt = "mana";
267 			dptr = &playerp->p_mana;
268 			goto DALTER;
269 
270 		case 'N':	/* change brains */
271 			prompt = "brains";
272 			dptr = &playerp->p_brains;
273 			goto DALTER;
274 
275 		case 'O':	/* change poison */
276 			prompt = "poison";
277 			dptr = &playerp->p_poison;
278 			goto DALTER;
279 
280 		case 'P':	/* change gold */
281 			prompt = "gold";
282 			dptr = &playerp->p_gold;
283 			goto DALTER;
284 
285 		case 'Q':	/* change gems */
286 			prompt = "gems";
287 			dptr = &playerp->p_gems;
288 			goto DALTER;
289 
290 		case 'R':	/* change sin */
291 			prompt = "sin";
292 			dptr = &playerp->p_sin;
293 			goto DALTER;
294 
295 		case 'S':	/* change x coord */
296 			prompt = "x";
297 			dptr = &playerp->p_x;
298 			goto DALTER;
299 
300 		case 'T':	/* change y coord */
301 			prompt = "y";
302 			dptr = &playerp->p_y;
303 			goto DALTER;
304 
305 		case 'U':	/* change age */
306 			mvprintw(23, 0, "age = %ld; age = ", playerp->p_age);
307 			dtemp = infloat();
308 			if (dtemp != 0.0)
309 				playerp->p_age = (long) dtemp;
310 			continue;
311 
312 		case 'V':	/* change degen */
313 			mvprintw(23, 0, "degen = %d; degen = ", playerp->p_degenerated);
314 			dtemp = infloat();
315 			if (dtemp != 0.0)
316 				playerp->p_degenerated = (int) dtemp;
317 			continue;
318 
319 		case 'W':	/* change type */
320 			prompt = "type";
321 			sptr = &playerp->p_type;
322 			goto SALTER;
323 
324 		case 'X':	/* change special type */
325 			prompt = "special type";
326 			sptr = &playerp->p_specialtype;
327 			goto SALTER;
328 
329 		case 'Y':	/* change lives */
330 			prompt = "lives";
331 			sptr = &playerp->p_lives;
332 			goto SALTER;
333 
334 		case 'Z':	/* change crowns */
335 			prompt = "crowns";
336 			sptr = &playerp->p_crowns;
337 			goto SALTER;
338 
339 		case '0':	/* change charms */
340 			prompt = "charm";
341 			sptr = &playerp->p_charms;
342 			goto SALTER;
343 
344 		case '1':	/* change amulet */
345 			prompt = "amulet";
346 			sptr = &playerp->p_amulets;
347 			goto SALTER;
348 
349 		case '2':	/* change holy water */
350 			prompt = "holy water";
351 			sptr = &playerp->p_holywater;
352 			goto SALTER;
353 
354 		case '3':	/* change last-used */
355 			prompt = "last-used";
356 			sptr = &playerp->p_lastused;
357 			goto SALTER;
358 
359 		case '4':	/* change palantir */
360 			prompt = "palantir";
361 			bptr = &playerp->p_palantir;
362 			goto BALTER;
363 
364 		case '5':	/* change blessing */
365 			prompt = "blessing";
366 			bptr = &playerp->p_blessing;
367 			goto BALTER;
368 
369 		case '6':	/* change virgin */
370 			prompt = "virgin";
371 			bptr = &playerp->p_virgin;
372 			goto BALTER;
373 
374 		case '7':	/* change blindness */
375 			prompt = "blindness";
376 			bptr = &playerp->p_blindness;
377 			goto BALTER;
378 
379 		case '8':	/* change ring type */
380 			prompt = "ring-type";
381 			sptr = &playerp->p_ring.ring_type;
382 			goto SALTER;
383 
384 		case '9':	/* change ring duration */
385 			prompt = "ring-duration";
386 			sptr = &playerp->p_ring.ring_duration;
387 			goto SALTER;
388 
389 		case '!':	/* quit, update */
390 			if (Wizard &&
391 			    (!ingameflag || playerp != &Player))
392 				/* turn off status if not modifying self */
393 			{
394 				playerp->p_status = S_OFF;
395 				playerp->p_tampered = T_OFF;
396 			}
397 			writerecord(playerp, loc);
398 			clear();
399 			return;
400 
401 		case '?':	/* delete player */
402 			if (ingameflag && playerp == &Player)
403 				/* cannot delete self */
404 				continue;
405 
406 			freerecord(playerp, loc);
407 			clear();
408 			return;
409 
410 		default:
411 			continue;
412 		}
413 DALTER:
414 		mvprintw(23, 0, "%s = %f; %s = ", prompt, *dptr, prompt);
415 		dtemp = infloat();
416 		if (dtemp != 0.0)
417 			*dptr = dtemp;
418 		continue;
419 
420 SALTER:
421 		mvprintw(23, 0, "%s = %d; %s = ", prompt, *sptr, prompt);
422 		dtemp = infloat();
423 		if (dtemp != 0.0)
424 			*sptr = (short) dtemp;
425 		continue;
426 
427 BALTER:
428 		mvprintw(23, 0, "%s = %c; %s = ", prompt, flag[(int)*bptr],
429 		    prompt);
430 		c = getanswer("\nTF", TRUE);
431 		if (c == 'T')
432 			*bptr = TRUE;
433 		else
434 			if (c == 'F')
435 				*bptr = FALSE;
436 		continue;
437 	}
438 }
439 
440 void
441 monstlist()
442 {
443 	int     count = 0;	/* count in file */
444 
445 	puts(" #)  Name                 Str  Brain  Quick  Energy  Exper  Treas  Type  Flock%\n");
446 	fseek(Monstfp, 0L, SEEK_SET);
447 	while (fread((char *) &Curmonster, SZ_MONSTERSTRUCT, 1, Monstfp) == 1)
448 		printf("%2d)  %-20.20s%4.0f   %4.0f     %2.0f   %5.0f  %5.0f     %2d    %2d     %3.0f\n", count++,
449 		    Curmonster.m_name, Curmonster.m_strength, Curmonster.m_brains,
450 		    Curmonster.m_speed, Curmonster.m_energy, Curmonster.m_experience,
451 		    Curmonster.m_treasuretype, Curmonster.m_type, Curmonster.m_flock);
452 }
453 
454 void
455 scorelist()
456 {
457 	struct scoreboard sbuf;	/* for reading entries */
458 	FILE   *fp;		/* to open the file */
459 
460 	if ((fp = fopen(_PATH_SCORE, "r")) != NULL) {
461 		while (fread((char *) &sbuf, SZ_SCORESTRUCT, 1, fp) == 1)
462 			printf("%-20s   (%-9s)  Level: %6.0f  Type: %s\n",
463 			    sbuf.sb_name, sbuf.sb_login, sbuf.sb_level, sbuf.sb_type);
464 		fclose(fp);
465 	}
466 }
467 
468 void
469 activelist()
470 {
471 	fseek(Playersfp, 0L, SEEK_SET);
472 	printf("Current characters on file are:\n\n");
473 
474 	while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
475 		if (Other.p_status != S_NOTUSED)
476 			printf("%-20s   (%-9s)  Level: %6.0f  %s  (%s)\n",
477 			    Other.p_name, Other.p_login, Other.p_level,
478 			    descrtype(&Other, FALSE), descrstatus(&Other));
479 
480 }
481 
482 void
483 purgeoldplayers()
484 {
485 	int     today;		/* day of year for today */
486 	int     daysold;	/* how many days since the character has been
487 				 * used */
488 	time_t  ltime;		/* time in seconds */
489 	long    loc = 0L;	/* location in file */
490 
491 	time(&ltime);
492 	today = localtime(&ltime)->tm_yday;
493 
494 	for (;;) {
495 		fseek(Playersfp, loc, SEEK_SET);
496 		if (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) != 1)
497 			break;
498 
499 		daysold = today - Other.p_lastused;
500 		if (daysold < 0)
501 			daysold += 365;
502 
503 		if (daysold > N_DAYSOLD)
504 			/* player hasn't been used in a while; delete */
505 			freerecord(&Other, loc);
506 
507 		loc += SZ_PLAYERSTRUCT;
508 	}
509 }
510 
511 void
512 enterscore()
513 {
514 	struct scoreboard sbuf;	/* buffer to read in scoreboard entries */
515 	FILE   *fp;		/* to open scoreboard file */
516 	long    loc = 0L;	/* location in scoreboard file */
517 	bool    found = FALSE;	/* set if we found an entry for this login */
518 
519 	if ((fp = fopen(_PATH_SCORE, "r+")) != NULL) {
520 		while (fread((char *) &sbuf, SZ_SCORESTRUCT, 1, fp) == 1)
521 			if (strcmp(Player.p_login, sbuf.sb_login) == 0) {
522 				found = TRUE;
523 				break;
524 			} else
525 				loc += SZ_SCORESTRUCT;
526 	} else {
527 		error(_PATH_SCORE);
528 		/* NOTREACHED */
529 	}
530 
531 	/*
532          * At this point, 'loc' will either indicate a point beyond
533          * the end of file, or the place where the previous entry
534          * was found.
535          */
536 
537 	if ((!found) || Player.p_level > sbuf.sb_level)
538 		/* put new entry in for this login */
539 	{
540 		strcpy(sbuf.sb_login, Player.p_login);
541 		strcpy(sbuf.sb_name, Player.p_name);
542 		sbuf.sb_level = Player.p_level;
543 		strcpy(sbuf.sb_type, descrtype(&Player, TRUE));
544 	}
545 	/* update entry */
546 	fseek(fp, loc, SEEK_SET);
547 	fwrite((char *) &sbuf, SZ_SCORESTRUCT, 1, fp);
548 	fclose(fp);
549 }
550