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