]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - phantasia/gamesupport.c
rcs id conventions
[bsdgames-darwin.git] / phantasia / gamesupport.c
1 /* $NetBSD: gamesupport.c,v 1.2 1995/03/24 03:58:43 cgd Exp $ */
2
3 /*
4 * gamesupport.c - auxiliary routines for support of Phantasia
5 */
6
7 #include "include.h"
8
9 /************************************************************************
10 /
11 / FUNCTION NAME: changestats()
12 /
13 / FUNCTION: examine/change statistics for a player
14 /
15 / AUTHOR: E. A. Estes, 12/4/85
16 /
17 / ARGUMENTS:
18 / bool ingameflag - set if called while playing game (Wizard only)
19 /
20 / RETURN VALUE: none
21 /
22 / MODULES CALLED: freerecord(), writerecord(), descrstatus(), truncstring(),
23 / time(), more(), wmove(), wclear(), strcmp(), printw(), strcpy(),
24 / infloat(), waddstr(), cleanup(), findname(), userlist(), mvprintw(),
25 / localtime(), getanswer(), descrtype(), getstring()
26 /
27 / GLOBAL INPUTS: LINES, *Login, Other, Wizard, Player, *stdscr, Databuf[],
28 / Fileloc
29 /
30 / GLOBAL OUTPUTS: Echo
31 /
32 / DESCRIPTION:
33 / Prompt for player name to examine/change.
34 / If the name is NULL, print a list of all players.
35 / If we are called from within the game, check for the
36 / desired name being the same as the current player's name.
37 / Only the 'Wizard' may alter players.
38 / Items are changed only if a non-zero value is specified.
39 / To change an item to 0, use 0.1; it will be truncated later.
40 /
41 / Players may alter their names and passwords, if the following
42 / are true:
43 / - current login matches the character's logins
44 / - the password is known
45 / - the player is not in the middle of the game (ingameflag == FALSE)
46 /
47 / The last condition is imposed for two reasons:
48 / - the game could possibly get a bit hectic if a player were
49 / continually changing his/her name
50 / - another player structure would be necessary to check for names
51 / already in use
52 /
53 /************************************************************************/
54
55 changestats(ingameflag)
56 bool ingameflag;
57 {
58 static char flag[2] = /* for printing values of bools */
59 {'F', 'T'};
60 register struct player *playerp;/* pointer to structure to alter */
61 register char *prompt; /* pointer to prompt string */
62 int c; /* input */
63 int today; /* day of year of today */
64 int temp; /* temporary variable */
65 long loc; /* location in player file */
66 long now; /* time now */
67 double dtemp; /* temporary variable */
68 bool *bptr; /* pointer to bool item to change */
69 double *dptr; /* pointer to double item to change */
70 short *sptr; /* pointer to short item to change */
71
72 clear();
73
74 for (;;)
75 /* get name of player to examine/alter */
76 {
77 mvaddstr(5, 0, "Which character do you want to look at ? ");
78 getstring(Databuf, SZ_DATABUF);
79 truncstring(Databuf);
80
81 if (Databuf[0] == '\0')
82 userlist(ingameflag);
83 else
84 break;
85 }
86
87 loc = -1L;
88
89 if (!ingameflag)
90 /* use 'Player' structure */
91 playerp = &Player;
92 else if (strcmp(Databuf, Player.p_name) == 0)
93 /* alter/examine current player */
94 {
95 playerp = &Player;
96 loc = Fileloc;
97 }
98 else
99 /* use 'Other' structure */
100 playerp = &Other;
101
102 /* find player on file */
103 if (loc < 0L && (loc = findname(Databuf, playerp)) < 0L)
104 /* didn't find player */
105 {
106 clear();
107 mvaddstr(11, 0, "Not found.");
108 return;
109 }
110
111 time(&now);
112 today = localtime(&now)->tm_yday;
113
114 clear();
115
116 for (;;)
117 /* print player structure, and prompt for action */
118 {
119 mvprintw(0, 0,"A:Name %s\n", playerp->p_name);
120
121 if (Wizard)
122 printw("B:Password %s\n", playerp->p_password);
123 else
124 addstr("B:Password XXXXXXXX\n");
125
126 printw(" :Login %s\n", playerp->p_login);
127
128 printw("C:Experience %.0f\n", playerp->p_experience);
129 printw("D:Level %.0f\n", playerp->p_level);
130 printw("E:Strength %.0f\n", playerp->p_strength);
131 printw("F:Sword %.0f\n", playerp->p_sword);
132 printw(" :Might %.0f\n", playerp->p_might);
133 printw("G:Energy %.0f\n", playerp->p_energy);
134 printw("H:Max-Energy %.0f\n", playerp->p_maxenergy);
135 printw("I:Shield %.0f\n", playerp->p_shield);
136 printw("J:Quickness %.0f\n", playerp->p_quickness);
137 printw("K:Quicksilver %.0f\n", playerp->p_quksilver);
138 printw(" :Speed %.0f\n", playerp->p_speed);
139 printw("L:Magic Level %.0f\n", playerp->p_magiclvl);
140 printw("M:Mana %.0f\n", playerp->p_mana);
141 printw("N:Brains %.0f\n", playerp->p_brains);
142
143 if (Wizard || playerp->p_specialtype != SC_VALAR)
144 mvaddstr(0, 40, descrstatus(playerp));
145
146 mvprintw(1, 40, "O:Poison %0.3f\n", playerp->p_poison);
147 mvprintw(2, 40, "P:Gold %.0f\n", playerp->p_gold);
148 mvprintw(3, 40, "Q:Gem %.0f\n", playerp->p_gems);
149 mvprintw(4, 40, "R:Sin %0.3f\n", playerp->p_sin);
150 if (Wizard)
151 {
152 mvprintw(5, 40, "S:X-coord %.0f\n", playerp->p_x);
153 mvprintw(6, 40, "T:Y-coord %.0f\n", playerp->p_y);
154 }
155 else
156 {
157 mvaddstr(5, 40, "S:X-coord ?\n");
158 mvaddstr(6, 40, "T:Y-coord ?\n");
159 }
160
161 mvprintw(7, 40, "U:Age %ld\n", playerp->p_age);
162 mvprintw(8, 40, "V:Degenerated %d\n", playerp->p_degenerated);
163
164 mvprintw(9, 40, "W:Type %d (%s)\n",
165 playerp->p_type, descrtype(playerp, FALSE) + 1);
166 mvprintw(10, 40, "X:Special Type %d\n", playerp->p_specialtype);
167 mvprintw(11, 40, "Y:Lives %d\n", playerp->p_lives);
168 mvprintw(12, 40, "Z:Crowns %d\n", playerp->p_crowns);
169 mvprintw(13, 40, "0:Charms %d\n", playerp->p_charms);
170 mvprintw(14, 40, "1:Amulets %d\n", playerp->p_amulets);
171 mvprintw(15, 40, "2:Holy Water %d\n", playerp->p_holywater);
172
173 temp = today - playerp->p_lastused;
174 if (temp < 0)
175 /* last year */
176 temp += 365;
177 mvprintw(16, 40, "3:Lastused %d (%d)\n", playerp->p_lastused, temp);
178
179 mvprintw(18, 8, "4:Palantir %c 5:Blessing %c 6:Virgin %c 7:Blind %c",
180 flag[playerp->p_palantir],
181 flag[playerp->p_blessing],
182 flag[playerp->p_virgin],
183 flag[playerp->p_blindness]);
184
185 if (!Wizard)
186 mvprintw(19, 8, "8:Ring %c",
187 flag[playerp->p_ring.ring_type != R_NONE]);
188 else
189 mvprintw(19, 8, "8:Ring %d 9:Duration %d",
190 playerp->p_ring.ring_type, playerp->p_ring.ring_duration);
191
192 if (!Wizard
193 /* not wizard */
194 && (ingameflag || strcmp(Login, playerp->p_login) != 0))
195 /* in game or not examining own character */
196 {
197 if (ingameflag)
198 {
199 more(LINES - 1);
200 clear();
201 return;
202 }
203 else
204 cleanup(TRUE);
205 /*NOTREACHED*/
206 }
207
208 mvaddstr(20, 0, "!:Quit ?:Delete");
209 mvaddstr(21, 0, "What would you like to change ? ");
210
211 if (Wizard)
212 c = getanswer(" ", TRUE);
213 else
214 /* examining own player; allow to change name and password */
215 c = getanswer("!BA", FALSE);
216
217 switch (c)
218 {
219 case 'A': /* change name */
220 case 'B': /* change password */
221 if (!Wizard)
222 /* prompt for password */
223 {
224 mvaddstr(23, 0, "Password ? ");
225 Echo = FALSE;
226 getstring(Databuf, 9);
227 Echo = TRUE;
228 if (strcmp(Databuf, playerp->p_password) != 0)
229 continue;
230 }
231
232 if (c == 'A')
233 /* get new name */
234 {
235 mvaddstr(23, 0, "New name: ");
236 getstring(Databuf, SZ_NAME);
237 truncstring(Databuf);
238 if (Databuf[0] != '\0')
239 if (Wizard || findname(Databuf, &Other) < 0L)
240 strcpy(playerp->p_name, Databuf);
241 }
242 else
243 /* get new password */
244 {
245 if (!Wizard)
246 Echo = FALSE;
247
248 do
249 /* get two copies of new password until they match */
250 {
251 /* get first copy */
252 mvaddstr(23, 0, "New password ? ");
253 getstring(Databuf, SZ_PASSWORD);
254 if (Databuf[0] == '\0')
255 break;
256
257 /* get second copy */
258 mvaddstr(23, 0, "One more time ? ");
259 getstring(playerp->p_password, SZ_PASSWORD);
260 }
261 while (strcmp(playerp->p_password, Databuf) != 0);
262
263 Echo = TRUE;
264 }
265
266 continue;
267
268 case 'C': /* change experience */
269 prompt = "experience";
270 dptr = &playerp->p_experience;
271 goto DALTER;
272
273 case 'D': /* change level */
274 prompt = "level";
275 dptr = &playerp->p_level;
276 goto DALTER;
277
278 case 'E': /* change strength */
279 prompt = "strength";
280 dptr = &playerp->p_strength;
281 goto DALTER;
282
283 case 'F': /* change swords */
284 prompt = "sword";
285 dptr = &playerp->p_sword;
286 goto DALTER;
287
288 case 'G': /* change energy */
289 prompt = "energy";
290 dptr = &playerp->p_energy;
291 goto DALTER;
292
293 case 'H': /* change maximum energy */
294 prompt = "max energy";
295 dptr = &playerp->p_maxenergy;
296 goto DALTER;
297
298 case 'I': /* change shields */
299 prompt = "shield";
300 dptr = &playerp->p_shield;
301 goto DALTER;
302
303 case 'J': /* change quickness */
304 prompt = "quickness";
305 dptr = &playerp->p_quickness;
306 goto DALTER;
307
308 case 'K': /* change quicksilver */
309 prompt = "quicksilver";
310 dptr = &playerp->p_quksilver;
311 goto DALTER;
312
313 case 'L': /* change magic */
314 prompt = "magic level";
315 dptr = &playerp->p_magiclvl;
316 goto DALTER;
317
318 case 'M': /* change mana */
319 prompt = "mana";
320 dptr = &playerp->p_mana;
321 goto DALTER;
322
323 case 'N': /* change brains */
324 prompt = "brains";
325 dptr = &playerp->p_brains;
326 goto DALTER;
327
328 case 'O': /* change poison */
329 prompt = "poison";
330 dptr = &playerp->p_poison;
331 goto DALTER;
332
333 case 'P': /* change gold */
334 prompt = "gold";
335 dptr = &playerp->p_gold;
336 goto DALTER;
337
338 case 'Q': /* change gems */
339 prompt = "gems";
340 dptr = &playerp->p_gems;
341 goto DALTER;
342
343 case 'R': /* change sin */
344 prompt = "sin";
345 dptr = &playerp->p_sin;
346 goto DALTER;
347
348 case 'S': /* change x coord */
349 prompt = "x";
350 dptr = &playerp->p_x;
351 goto DALTER;
352
353 case 'T': /* change y coord */
354 prompt = "y";
355 dptr = &playerp->p_y;
356 goto DALTER;
357
358 case 'U': /* change age */
359 mvprintw(23, 0, "age = %ld; age = ", playerp->p_age);
360 dtemp = infloat();
361 if (dtemp != 0.0)
362 playerp->p_age = (long) dtemp;
363 continue;
364
365 case 'V': /* change degen */
366 mvprintw(23, 0, "degen = %d; degen = ", playerp->p_degenerated);
367 dtemp = infloat();
368 if (dtemp != 0.0)
369 playerp->p_degenerated = (int) dtemp;
370 continue;
371
372 case 'W': /* change type */
373 prompt = "type";
374 sptr = &playerp->p_type;
375 goto SALTER;
376
377 case 'X': /* change special type */
378 prompt = "special type";
379 sptr = &playerp->p_specialtype;
380 goto SALTER;
381
382 case 'Y': /* change lives */
383 prompt = "lives";
384 sptr = &playerp->p_lives;
385 goto SALTER;
386
387 case 'Z': /* change crowns */
388 prompt = "crowns";
389 sptr = &playerp->p_crowns;
390 goto SALTER;
391
392 case '0': /* change charms */
393 prompt = "charm";
394 sptr = &playerp->p_charms;
395 goto SALTER;
396
397 case '1': /* change amulet */
398 prompt = "amulet";
399 sptr = &playerp->p_amulets;
400 goto SALTER;
401
402 case '2': /* change holy water */
403 prompt = "holy water";
404 sptr = &playerp->p_holywater;
405 goto SALTER;
406
407 case '3': /* change last-used */
408 prompt = "last-used";
409 sptr = &playerp->p_lastused;
410 goto SALTER;
411
412 case '4': /* change palantir */
413 prompt = "palantir";
414 bptr = &playerp->p_palantir;
415 goto BALTER;
416
417 case '5': /* change blessing */
418 prompt = "blessing";
419 bptr = &playerp->p_blessing;
420 goto BALTER;
421
422 case '6': /* change virgin */
423 prompt = "virgin";
424 bptr = &playerp->p_virgin;
425 goto BALTER;
426
427 case '7': /* change blindness */
428 prompt = "blindness";
429 bptr = &playerp->p_blindness;
430 goto BALTER;
431
432 case '8': /* change ring type */
433 prompt = "ring-type";
434 sptr = &playerp->p_ring.ring_type;
435 goto SALTER;
436
437 case '9': /* change ring duration */
438 prompt = "ring-duration";
439 sptr = &playerp->p_ring.ring_duration;
440 goto SALTER;
441
442 case '!': /* quit, update */
443 if (Wizard &&
444 (!ingameflag || playerp != &Player))
445 /* turn off status if not modifying self */
446 {
447 playerp->p_status = S_OFF;
448 playerp->p_tampered = T_OFF;
449 }
450
451 writerecord(playerp, loc);
452 clear();
453 return;
454
455 case '?': /* delete player */
456 if (ingameflag && playerp == &Player)
457 /* cannot delete self */
458 continue;
459
460 freerecord(playerp, loc);
461 clear();
462 return;
463
464 default:
465 continue;
466 }
467 DALTER:
468 mvprintw(23, 0, "%s = %f; %s = ", prompt, *dptr, prompt);
469 dtemp = infloat();
470 if (dtemp != 0.0)
471 *dptr = dtemp;
472 continue;
473
474 SALTER:
475 mvprintw(23, 0, "%s = %d; %s = ", prompt, *sptr, prompt);
476 dtemp = infloat();
477 if (dtemp != 0.0)
478 *sptr = (short) dtemp;
479 continue;
480
481 BALTER:
482 mvprintw(23, 0, "%s = %c; %s = ", prompt, flag[*bptr], prompt);
483 c = getanswer("\nTF", TRUE);
484 if (c == 'T')
485 *bptr = TRUE;
486 else if (c == 'F')
487 *bptr = FALSE;
488 continue;
489 }
490 }
491 /*\f*/
492 /************************************************************************
493 /
494 / FUNCTION NAME: monstlist()
495 /
496 / FUNCTION: print a monster listing
497 /
498 / AUTHOR: E. A. Estes, 2/27/86
499 /
500 / ARGUMENTS: none
501 /
502 / RETURN VALUE: none
503 /
504 / MODULES CALLED: puts(), fread(), fseek(), printf()
505 /
506 / GLOBAL INPUTS: Curmonster, *Monstfp
507 /
508 / GLOBAL OUTPUTS: none
509 /
510 / DESCRIPTION:
511 / Read monster file, and print a monster listing on standard output.
512 /
513 /************************************************************************/
514
515 monstlist()
516 {
517 register int count = 0; /* count in file */
518
519 puts(" #) Name Str Brain Quick Energy Exper Treas Type Flock%\n");
520 fseek(Monstfp, 0L, 0);
521 while (fread((char *) &Curmonster, SZ_MONSTERSTRUCT, 1, Monstfp) == 1)
522 printf("%2d) %-20.20s%4.0f %4.0f %2.0f %5.0f %5.0f %2d %2d %3.0f\n", count++,
523 Curmonster.m_name, Curmonster.m_strength, Curmonster.m_brains,
524 Curmonster.m_speed, Curmonster.m_energy, Curmonster.m_experience,
525 Curmonster.m_treasuretype, Curmonster.m_type, Curmonster.m_flock);
526 }
527 /*\f*/
528 /************************************************************************
529 /
530 / FUNCTION NAME: scorelist()
531 /
532 / FUNCTION: print player score board
533 /
534 / AUTHOR: E. A. Estes, 12/4/85
535 /
536 / ARGUMENTS: none
537 /
538 / RETURN VALUE: none
539 /
540 / MODULES CALLED: fread(), fopen(), printf(), fclose()
541 /
542 / GLOBAL INPUTS:
543 /
544 / GLOBAL OUTPUTS: none
545 /
546 / DESCRIPTION:
547 / Read the scoreboard file and print the contents.
548 /
549 /************************************************************************/
550
551 scorelist()
552 {
553 struct scoreboard sbuf; /* for reading entries */
554 register FILE *fp; /* to open the file */
555
556 if ((fp = fopen(_PATH_SCORE, "r")) != NULL)
557 {
558 while (fread((char *) &sbuf, SZ_SCORESTRUCT, 1, fp) == 1)
559 printf("%-20s (%-9s) Level: %6.0f Type: %s\n",
560 sbuf.sb_name, sbuf.sb_login, sbuf.sb_level, sbuf.sb_type);
561 fclose(fp);
562 }
563 }
564 /*\f*/
565 /************************************************************************
566 /
567 / FUNCTION NAME: activelist()
568 /
569 / FUNCTION: print list of active players to standard output
570 /
571 / AUTHOR: E. A. Estes, 3/7/86
572 /
573 / ARGUMENTS: none
574 /
575 / RETURN VALUE: none
576 /
577 / MODULES CALLED: descrstatus(), fread(), fseek(), printf(), descrtype()
578 /
579 / GLOBAL INPUTS: Other, *Playersfp
580 /
581 / GLOBAL OUTPUTS: none
582 /
583 / DESCRIPTION:
584 / Read player file, and print list of active records to standard output.
585 /
586 /************************************************************************/
587
588 activelist()
589 {
590 fseek(Playersfp, 0L, 0);
591 printf("Current characters on file are:\n\n");
592
593 while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
594 if (Other.p_status != S_NOTUSED)
595 printf("%-20s (%-9s) Level: %6.0f %s (%s)\n",
596 Other.p_name, Other.p_login, Other.p_level,
597 descrtype(&Other, FALSE), descrstatus(&Other));
598
599 }
600 /*\f*/
601 /************************************************************************
602 /
603 / FUNCTION NAME: purgeoldplayers()
604 /
605 / FUNCTION: purge inactive players from player file
606 /
607 / AUTHOR: E. A. Estes, 12/4/85
608 /
609 / ARGUMENTS: none
610 /
611 / RETURN VALUE: none
612 /
613 / MODULES CALLED: freerecord(), time(), fread(), fseek(), localtime()
614 /
615 / GLOBAL INPUTS: Other, *Playersfp
616 /
617 / GLOBAL OUTPUTS: none
618 /
619 / DESCRIPTION:
620 / Delete characters which have not been used with the last
621 / three weeks.
622 /
623 /************************************************************************/
624
625 purgeoldplayers()
626 {
627 int today; /* day of year for today */
628 int daysold; /* how many days since the character has been used */
629 long ltime; /* time in seconds */
630 long loc = 0L; /* location in file */
631
632 time(&ltime);
633 today = localtime(&ltime)->tm_yday;
634
635 for (;;)
636 {
637 fseek(Playersfp, loc, 0);
638 if (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) != 1)
639 break;
640
641 daysold = today - Other.p_lastused;
642 if (daysold < 0)
643 daysold += 365;
644
645 if (daysold > N_DAYSOLD)
646 /* player hasn't been used in a while; delete */
647 freerecord(&Other, loc);
648
649 loc += SZ_PLAYERSTRUCT;
650 }
651 }
652 /*\f*/
653 /************************************************************************
654 /
655 / FUNCTION NAME: enterscore()
656 /
657 / FUNCTION: enter player into scoreboard
658 /
659 / AUTHOR: E. A. Estes, 12/4/85
660 /
661 / ARGUMENTS: none
662 /
663 / RETURN VALUE: none
664 /
665 / MODULES CALLED: fread(), fseek(), fopen(), error(), strcmp(), fclose(),
666 / strcpy(), fwrite(), descrtype()
667 /
668 / GLOBAL INPUTS: Player
669 /
670 / GLOBAL OUTPUTS: none
671 /
672 / DESCRIPTION:
673 / The scoreboard keeps track of the highest character on a
674 / per-login basis.
675 / Search the scoreboard for an entry for the current login,
676 / if an entry is found, and it is lower than the current player,
677 / replace it, otherwise create an entry.
678 /
679 /************************************************************************/
680
681 enterscore()
682 {
683 struct scoreboard sbuf; /* buffer to read in scoreboard entries */
684 FILE *fp; /* to open scoreboard file */
685 long loc = 0L; /* location in scoreboard file */
686 bool found = FALSE; /* set if we found an entry for this login */
687
688 if ((fp = fopen(_PATH_SCORE, "r+")) != NULL)
689 {
690 while (fread((char *) &sbuf, SZ_SCORESTRUCT, 1, fp) == 1)
691 if (strcmp(Player.p_login, sbuf.sb_login) == 0)
692 {
693 found = TRUE;
694 break;
695 }
696 else
697 loc += SZ_SCORESTRUCT;
698 }
699 else
700 {
701 error(_PATH_SCORE);
702 /*NOTREACHED*/
703 }
704
705 /*
706 * At this point, 'loc' will either indicate a point beyond
707 * the end of file, or the place where the previous entry
708 * was found.
709 */
710
711 if ((!found) || Player.p_level > sbuf.sb_level)
712 /* put new entry in for this login */
713 {
714 strcpy(sbuf.sb_login, Player.p_login);
715 strcpy(sbuf.sb_name, Player.p_name);
716 sbuf.sb_level = Player.p_level;
717 strcpy(sbuf.sb_type, descrtype(&Player, TRUE));
718 }
719
720 /* update entry */
721 fseek(fp, loc, 0);
722 fwrite((char *) &sbuf, SZ_SCORESTRUCT, 1, fp);
723 fclose(fp);
724 }