]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - larn/scores.c
More assorted cleanup merged from larn 12.2.
[bsdgames-darwin.git] / larn / scores.c
1 /* $NetBSD: scores.c,v 1.17 2008/02/03 20:41:53 dholland Exp $ */
2
3 /*
4 * scores.c Larn is copyrighted 1986 by Noah Morgan.
5 *
6 * Functions in this file are:
7 *
8 * readboard() Function to read in the scoreboard into a static buffer
9 * writeboard() Function to write the scoreboard from readboard()'s buffer
10 * makeboard() Function to create a new scoreboard (wipe out old one)
11 * hashewon() Function to return 1 if player has won a game before, else 0
12 * long paytaxes(x) Function to pay taxes if any are due winshou()
13 * ubroutine to print out the winning scoreboard shou(x)
14 * ubroutine to print out the non-winners scoreboard showscores()
15 * unction to show the scoreboard on the terminal showallscores()
16 * Function to show scores and the iven lists that go with them sortboard()
17 * unction to sort the scoreboard newscore(score, whoo, whyded, winner)
18 * Function to add entry to scoreboard new1sub(score,i,whoo,taxes)
19 * Subroutine to put player into a new2sub(score,i,whoo,whyded)
20 * Subroutine to put player into a died(x) Subroutine to record who
21 * played larn, and what the score was diedsub(x) Subroutine to print out a
22 * line showing player when he is killed diedlog() Subroutine to read a
23 * log file and print it out in ascii format getplid(name)
24 * on to get players id # from id file
25 *
26 */
27 #include <sys/cdefs.h>
28 #ifndef lint
29 __RCSID("$NetBSD: scores.c,v 1.17 2008/02/03 20:41:53 dholland Exp $");
30 #endif /* not lint */
31 #include <sys/types.h>
32 #include <sys/times.h>
33 #include <sys/stat.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <unistd.h>
37 #include <stdlib.h>
38 #include "header.h"
39 #include "extern.h"
40
41 struct scofmt { /* This is the structure for the scoreboard */
42 long score; /* the score of the player */
43 long suid; /* the user id number of the player */
44 short what; /* the number of the monster that killed
45 * player */
46 short level; /* the level player was on when he died */
47 short hardlev;/* the level of difficulty player played at */
48 short order; /* the relative ordering place of this entry */
49 char who[40];/* the name of the character */
50 char sciv[26][2]; /* this is the inventory list of the
51 * character */
52 };
53 struct wscofmt { /* This is the structure for the winning
54 * scoreboard */
55 long score; /* the score of the player */
56 long timeused; /* the time used in mobuls to win the
57 * game */
58 long taxes; /* taxes he owes to LRS */
59 long suid; /* the user id number of the player */
60 short hardlev;/* the level of difficulty player played at */
61 short order; /* the relative ordering place of this entry */
62 char who[40];/* the name of the character */
63 };
64
65 struct log_fmt { /* 102 bytes struct for the log file */
66 long score; /* the players score */
67 time_t diedtime; /* time when game was over */
68 short cavelev;/* level in caves */
69 short diff; /* difficulty player played at */
70 #ifdef EXTRA
71 long elapsedtime; /* real time of game in seconds */
72 long bytout; /* bytes input and output */
73 long bytin;
74 long moves; /* number of moves made by player */
75 short ac; /* armor class of player */
76 short hp, hpmax; /* players hitpoints */
77 short cputime;/* CPU time needed in seconds */
78 short killed, spused; /* monsters killed and spells cast */
79 short usage; /* usage of the CPU in % */
80 short lev; /* player level */
81 #endif
82 char who[12];/* player name */
83 char what[46]; /* what happened to player */
84 };
85
86 static struct scofmt sco[SCORESIZE]; /* the structure for the scoreboard */
87 static struct wscofmt winr[SCORESIZE]; /* struct for the winning scoreboard */
88 static struct log_fmt logg; /* structure for the log file */
89 static const char *whydead[] = {
90 "quit", "suspended", "self - annihilated", "shot by an arrow",
91 "hit by a dart", "fell into a pit", "fell into a bottomless pit",
92 "a winner", "trapped in solid rock", "killed by a missing save file",
93 "killed by an old save file", "caught by the greedy cheater checker trap",
94 "killed by a protected save file", "killed his family and committed suicide",
95 "erased by a wayward finger", "fell through a bottomless trap door",
96 "fell through a trap door", "drank some poisonous water",
97 "fried by an electric shock", "slipped on a volcano shaft",
98 "killed by a stupid act of frustration", "attacked by a revolting demon",
99 "hit by his own magic", "demolished by an unseen attacker",
100 "fell into the dreadful sleep", "killed by an exploding chest",
101 /* 26 */ "killed by a missing maze data file", "annihilated in a sphere",
102 "died a post mortem death", "wasted by a malloc() failure"
103 };
104
105 /*
106 * readboard() Function to read in the scoreboard into a static buffer
107 *
108 * returns -1 if unable to read in the scoreboard, returns 0 if all is OK
109 */
110 int
111 readboard()
112 {
113 int i;
114
115 if (gid != egid)
116 setegid(egid);
117 i = lopen(scorefile);
118 if (gid != egid)
119 setegid(gid);
120 if (i < 0) {
121 lprcat("Can't read scoreboard\n");
122 lflush();
123 return (-1);
124 }
125 lrfill((char *) sco, sizeof(sco));
126 lrfill((char *) winr, sizeof(winr));
127 lrclose();
128 lcreat((char *) 0);
129 return (0);
130 }
131
132 /*
133 * writeboard() Function to write the scoreboard from readboard()'s buffer
134 *
135 * returns -1 if unable to write the scoreboard, returns 0 if all is OK
136 */
137 int
138 writeboard()
139 {
140 int i;
141
142 set_score_output();
143 if (gid != egid)
144 setegid(egid);
145 i = lcreat(scorefile);
146 if (gid != egid)
147 setegid(gid);
148 if (i < 0) {
149 lprcat("Can't write scoreboard\n");
150 lflush();
151 return (-1);
152 }
153 lwrite((char *) sco, sizeof(sco));
154 lwrite((char *) winr, sizeof(winr));
155 lwclose();
156 lcreat((char *) 0);
157 return (0);
158 }
159
160 /*
161 * makeboard() Function to create a new scoreboard (wipe out old one)
162 *
163 * returns -1 if unable to write the scoreboard, returns 0 if all is OK
164 */
165 int
166 makeboard()
167 {
168 int i;
169 set_score_output();
170 for (i = 0; i < SCORESIZE; i++) {
171 winr[i].taxes = winr[i].score = sco[i].score = 0;
172 winr[i].order = sco[i].order = i;
173 }
174 if (writeboard())
175 return (-1);
176 if (gid != egid)
177 setegid(egid);
178 chmod(scorefile, 0660);
179 if (gid != egid)
180 setegid(gid);
181 return (0);
182 }
183
184 /*
185 * hashewon() Function to return 1 if player has won a game before, else 0
186 *
187 * This function also sets c[HARDGAME] to appropriate value -- 0 if not a
188 * winner, otherwise the next level of difficulty listed in the winners
189 * scoreboard. This function also sets outstanding_taxes to the value in
190 * the winners scoreboard.
191 */
192 int
193 hashewon()
194 {
195 int i;
196 c[HARDGAME] = 0;
197 if (readboard() < 0)
198 return (0); /* can't find scoreboard */
199 for (i = 0; i < SCORESIZE; i++) /* search through winners scoreboard */
200 if (winr[i].suid == userid)
201 if (winr[i].score > 0) {
202 c[HARDGAME] = winr[i].hardlev + 1;
203 outstanding_taxes = winr[i].taxes;
204 return (1);
205 }
206 return (0);
207 }
208
209 /*
210 * long paytaxes(x) Function to pay taxes if any are due
211 *
212 * Enter with the amount (in gp) to pay on the taxes.
213 * Returns amount actually paid.
214 */
215 long
216 paytaxes(x)
217 long x;
218 {
219 int i;
220 long amt;
221 if (x < 0)
222 return (0L);
223 if (readboard() < 0)
224 return (0L);
225 for (i = 0; i < SCORESIZE; i++)
226 if (winr[i].suid == userid) /* look for players winning
227 * entry */
228 if (winr[i].score > 0) { /* search for a winning
229 * entry for the player */
230 amt = winr[i].taxes;
231 if (x < amt)
232 amt = x; /* don't overpay taxes
233 * (Ughhhhh) */
234 winr[i].taxes -= amt;
235 outstanding_taxes -= amt;
236 set_score_output();
237 if (writeboard() < 0)
238 return (0);
239 return (amt);
240 }
241 return (0L); /* couldn't find user on winning scoreboard */
242 }
243
244 /*
245 * winshou() Subroutine to print out the winning scoreboard
246 *
247 * Returns the number of players on scoreboard that were shown
248 */
249 int
250 winshou()
251 {
252 struct wscofmt *p;
253 int i, j, count;
254 for (count = j = i = 0; i < SCORESIZE; i++) /* is there anyone on
255 * the scoreboard? */
256 if (winr[i].score != 0) {
257 j++;
258 break;
259 }
260 if (j) {
261 lprcat("\n Score Difficulty Time Needed Larn Winners List\n");
262
263 for (i = 0; i < SCORESIZE; i++) /* this loop is needed to
264 * print out the */
265 for (j = 0; j < SCORESIZE; j++) { /* winners in order */
266 p = &winr[j]; /* pointer to the scoreboard
267 * entry */
268 if (p->order == i) {
269 if (p->score) {
270 count++;
271 lprintf("%10ld %2ld %5ld Mobuls %s \n",
272 (long) p->score, (long) p->hardlev, (long) p->timeused, p->who);
273 }
274 break;
275 }
276 }
277 }
278 return (count); /* return number of people on scoreboard */
279 }
280
281 /*
282 * shou(x) Subroutine to print out the non-winners scoreboard
283 * int x;
284 *
285 * Enter with 0 to list the scores, enter with 1 to list inventories too
286 * Returns the number of players on scoreboard that were shown
287 */
288 int
289 shou(x)
290 int x;
291 {
292 int i, j, n, k;
293 int count;
294 for (count = j = i = 0; i < SCORESIZE; i++) /* is the scoreboard
295 * empty? */
296 if (sco[i].score != 0) {
297 j++;
298 break;
299 }
300 if (j) {
301 lprcat("\n Score Difficulty Larn Visitor Log\n");
302 for (i = 0; i < SCORESIZE; i++) /* be sure to print them out
303 * in order */
304 for (j = 0; j < SCORESIZE; j++)
305 if (sco[j].order == i) {
306 if (sco[j].score) {
307 count++;
308 lprintf("%10ld %2ld %s ",
309 (long) sco[j].score, (long) sco[j].hardlev, sco[j].who);
310 if (sco[j].what < 256)
311 lprintf("killed by a %s", monster[sco[j].what].name);
312 else
313 lprintf("%s", whydead[sco[j].what - 256]);
314 if (x != 263)
315 lprintf(" on %s", levelname[sco[j].level]);
316 if (x) {
317 for (n = 0; n < 26; n++) {
318 iven[n] = sco[j].sciv[n][0];
319 ivenarg[n] = sco[j].sciv[n][1];
320 }
321 for (k = 1; k < 99; k++)
322 for (n = 0; n < 26; n++)
323 if (k == iven[n]) {
324 srcount = 0;
325 show3(n);
326 }
327 lprcat("\n\n");
328 } else
329 lprc('\n');
330 }
331 j = SCORESIZE;
332 }
333 }
334 return (count); /* return the number of players just shown */
335 }
336
337 /*
338 * showscores() Function to show the scoreboard on the terminal
339 *
340 * Returns nothing of value
341 */
342 static char esb[] = "The scoreboard is empty.\n";
343 void
344 showscores()
345 {
346 int i, j;
347 lflush();
348 lcreat((char *) 0);
349 if (readboard() < 0)
350 return;
351 i = winshou();
352 j = shou(0);
353 if (i + j == 0)
354 lprcat(esb);
355 else
356 lprc('\n');
357 lflush();
358 }
359
360 /*
361 * showallscores() Function to show scores and the iven lists that go with them
362 *
363 * Returns nothing of value
364 */
365 void
366 showallscores()
367 {
368 int i, j;
369 lflush();
370 lcreat((char *) 0);
371 if (readboard() < 0)
372 return;
373 c[WEAR] = c[WIELD] = c[SHIELD] = -1; /* not wielding or wearing
374 * anything */
375 for (i = 0; i < MAXPOTION; i++)
376 potionname[i] = potionhide[i];
377 for (i = 0; i < MAXSCROLL; i++)
378 scrollname[i] = scrollhide[i];
379 i = winshou();
380 j = shou(1);
381 if (i + j == 0)
382 lprcat(esb);
383 else
384 lprc('\n');
385 lflush();
386 }
387
388 /*
389 * sortboard() Function to sort the scoreboard
390 *
391 * Returns 0 if no sorting done, else returns 1
392 */
393 int
394 sortboard()
395 {
396 int i, j = 0, pos;
397 long jdat;
398 for (i = 0; i < SCORESIZE; i++)
399 sco[i].order = winr[i].order = -1;
400 pos = 0;
401 while (pos < SCORESIZE) {
402 jdat = 0;
403 for (i = 0; i < SCORESIZE; i++)
404 if ((sco[i].order < 0) && (sco[i].score >= jdat)) {
405 j = i;
406 jdat = sco[i].score;
407 }
408 sco[j].order = pos++;
409 }
410 pos = 0;
411 while (pos < SCORESIZE) {
412 jdat = 0;
413 for (i = 0; i < SCORESIZE; i++)
414 if ((winr[i].order < 0) && (winr[i].score >= jdat)) {
415 j = i;
416 jdat = winr[i].score;
417 }
418 winr[j].order = pos++;
419 }
420 return (1);
421 }
422
423 /*
424 * newscore(score, whoo, whyded, winner) Function to add entry to scoreboard
425 * int score, winner, whyded;
426 * char *whoo;
427 *
428 * Enter with the total score in gp in score, players name in whoo,
429 * died() reason # in whyded, and TRUE/FALSE in winner if a winner
430 * ex. newscore(1000, "player 1", 32, 0);
431 */
432 void
433 newscore(score, whoo, whyded, winner)
434 long score;
435 int winner, whyded;
436 char *whoo;
437 {
438 int i;
439 long taxes;
440 if (readboard() < 0)
441 return; /* do the scoreboard */
442 /* if a winner then delete all non-winning scores */
443 if (cheat)
444 winner = 0; /* if he cheated, don't let him win */
445 if (winner) {
446 for (i = 0; i < SCORESIZE; i++)
447 if (sco[i].suid == userid)
448 sco[i].score = 0;
449 taxes = score * TAXRATE;
450 score += 100000 * c[HARDGAME]; /* bonus for winning */
451 /*
452 * if he has a slot on the winning scoreboard update it if
453 * greater score
454 */
455 for (i = 0; i < SCORESIZE; i++)
456 if (winr[i].suid == userid) {
457 new1sub(score, i, whoo, taxes);
458 return;
459 }
460 /*
461 * he had no entry. look for last entry and see if he has a
462 * greater score
463 */
464 for (i = 0; i < SCORESIZE; i++)
465 if (winr[i].order == SCORESIZE - 1) {
466 new1sub(score, i, whoo, taxes);
467 return;
468 }
469 } else if (!cheat) { /* for not winning scoreboard */
470 /*
471 * if he has a slot on the scoreboard update it if greater
472 * score
473 */
474 for (i = 0; i < SCORESIZE; i++)
475 if (sco[i].suid == userid) {
476 new2sub(score, i, whoo, whyded);
477 return;
478 }
479 /*
480 * he had no entry. look for last entry and see if he has a
481 * greater score
482 */
483 for (i = 0; i < SCORESIZE; i++)
484 if (sco[i].order == SCORESIZE - 1) {
485 new2sub(score, i, whoo, whyded);
486 return;
487 }
488 }
489 }
490
491 /*
492 * new1sub(score,i,whoo,taxes) Subroutine to put player into a
493 * int score,i,whyded,taxes; winning scoreboard entry if his score
494 * char *whoo; is high enough
495 *
496 * Enter with the total score in gp in score, players name in whoo,
497 * died() reason # in whyded, and TRUE/FALSE in winner if a winner
498 * slot in scoreboard in i, and the tax bill in taxes.
499 * Returns nothing of value
500 */
501 void
502 new1sub(score, i, whoo, taxes)
503 long score, taxes;
504 int i;
505 char *whoo;
506 {
507 struct wscofmt *p;
508 p = &winr[i];
509 p->taxes += taxes;
510 if ((score >= p->score) || (c[HARDGAME] > p->hardlev)) {
511 strcpy(p->who, whoo);
512 p->score = score;
513 p->hardlev = c[HARDGAME];
514 p->suid = userid;
515 p->timeused = gltime / 100;
516 }
517 }
518
519 /*
520 * new2sub(score,i,whoo,whyded) Subroutine to put player into a
521 * int score,i,whyded,taxes; non-winning scoreboard entry if his
522 * char *whoo; score is high enough
523 *
524 * Enter with the total score in gp in score, players name in whoo,
525 * died() reason # in whyded, and slot in scoreboard in i.
526 * Returns nothing of value
527 */
528 void
529 new2sub(score, i, whoo, whyded)
530 long score;
531 int i, whyded;
532 char *whoo;
533 {
534 int j;
535 struct scofmt *p;
536 p = &sco[i];
537 if ((score >= p->score) || (c[HARDGAME] > p->hardlev)) {
538 strcpy(p->who, whoo);
539 p->score = score;
540 p->what = whyded;
541 p->hardlev = c[HARDGAME];
542 p->suid = userid;
543 p->level = level;
544 for (j = 0; j < 26; j++) {
545 p->sciv[j][0] = iven[j];
546 p->sciv[j][1] = ivenarg[j];
547 }
548 }
549 }
550
551 /*
552 * died(x) Subroutine to record who played larn, and what the score was
553 * int x;
554 *
555 * if x < 0 then don't show scores
556 * died() never returns! (unless c[LIFEPROT] and a reincarnatable death!)
557 *
558 * < 256 killed by the monster number
559 * 256 quit
560 * 257 suspended
561 * 258 self - annihilated
562 * 259 shot by an arrow
563 * 260 hit by a dart
564 * 261 fell into a pit
565 * 262 fell into a bottomless pit
566 * 263 a winner
567 * 264 trapped in solid rock
568 * 265 killed by a missing save file
569 * 266 killed by an old save file
570 * 267 caught by the greedy cheater checker trap
571 * 268 killed by a protected save file
572 * 269 killed his family and killed himself
573 * 270 erased by a wayward finger
574 * 271 fell through a bottomless trap door
575 * 272 fell through a trap door
576 * 273 drank some poisonous water
577 * 274 fried by an electric shock
578 * 275 slipped on a volcano shaft
579 * 276 killed by a stupid act of frustration
580 * 277 attacked by a revolting demon
581 * 278 hit by his own magic
582 * 279 demolished by an unseen attacker
583 * 280 fell into the dreadful sleep
584 * 281 killed by an exploding chest
585 * 282 killed by a missing maze data file
586 * 283 killed by a sphere of annihilation
587 * 284 died a post mortem death
588 * 285 malloc() failure
589 * 300 quick quit -- don't put on scoreboard
590 */
591
592 static int scorerror;
593 void
594 died(x)
595 int x;
596 {
597 int f, win;
598 char ch;
599 const char *mod;
600 time_t zzz;
601 if (c[LIFEPROT] > 0) { /* if life protection */
602 switch ((x > 0) ? x : -x) {
603 case 256:
604 case 257:
605 case 262:
606 case 263:
607 case 265:
608 case 266:
609 case 267:
610 case 268:
611 case 269:
612 case 271:
613 case 282:
614 case 284:
615 case 285:
616 case 300:
617 goto invalid; /* can't be saved */
618 };
619 --c[LIFEPROT];
620 c[HP] = 1;
621 --c[CONSTITUTION];
622 cursors();
623 lprcat("\nYou feel wiiieeeeerrrrrd all over! ");
624 beep();
625 lflush();
626 sleep(4);
627 return; /* only case where died() returns */
628 }
629 invalid:
630 clearvt100();
631 lflush();
632 f = 0;
633 if (ckpflag)
634 unlink(ckpfile);/* remove checkpoint file if used */
635 if (x < 0) {
636 f++;
637 x = -x;
638 } /* if we are not to display the scores */
639 if ((x == 300) || (x == 257))
640 exit(0); /* for quick exit or saved game */
641 if (x == 263)
642 win = 1;
643 else
644 win = 0;
645 c[GOLD] += c[BANKACCOUNT];
646 c[BANKACCOUNT] = 0;
647 /* now enter the player at the end of the scoreboard */
648 newscore(c[GOLD], logname, x, win);
649 diedsub(x); /* print out the score line */
650 lflush();
651
652 set_score_output();
653 if ((wizard == 0) && (c[GOLD] > 0)) { /* wizards can't score */
654 #ifndef NOLOG
655 if (gid != egid)
656 setegid(egid);
657 if (lappend(logfile) < 0) { /* append to file */
658 if (lcreat(logfile) < 0) { /* and can't create new
659 * log file */
660 lcreat((char *) 0);
661 lprcat("\nCan't open record file: I can't post your score.\n");
662 sncbr();
663 resetscroll();
664 lflush();
665 exit(0);
666 }
667 if (gid != egid)
668 setegid(egid);
669 chmod(logfile, 0660);
670 if (gid != egid)
671 setegid(gid);
672 }
673 if (gid != egid)
674 setegid(gid);
675 strcpy(logg.who, loginname);
676 logg.score = c[GOLD];
677 logg.diff = c[HARDGAME];
678 if (x < 256) {
679 ch = *monster[x].name;
680 if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u')
681 mod = "an";
682 else
683 mod = "a";
684 snprintf(logg.what, sizeof(logg.what),
685 "killed by %s %s", mod, monster[x].name);
686 } else
687 snprintf(logg.what, sizeof(logg.what),
688 "%s", whydead[x - 256]);
689 logg.cavelev = level;
690 time(&zzz); /* get CPU time -- write out score info */
691 logg.diedtime = zzz;
692 #ifdef EXTRA
693 times(&cputime);/* get CPU time -- write out score info */
694 logg.cputime = i = (cputime.tms_utime + cputime.tms_stime) / 60 + c[CPUTIME];
695 logg.lev = c[LEVEL];
696 logg.ac = c[AC];
697 logg.hpmax = c[HPMAX];
698 logg.hp = c[HP];
699 logg.elapsedtime = (zzz - initialtime + 59) / 60;
700 logg.usage = (10000 * i) / (zzz - initialtime);
701 logg.bytin = c[BYTESIN];
702 logg.bytout = c[BYTESOUT];
703 logg.moves = c[MOVESMADE];
704 logg.spused = c[SPELLSCAST];
705 logg.killed = c[MONSTKILLED];
706 #endif
707 lwrite((char *) &logg, sizeof(struct log_fmt));
708 lwclose();
709 #endif /* NOLOG */
710
711 /*
712 * now for the scoreboard maintenance -- not for a suspended
713 * game
714 */
715 if (x != 257) {
716 if (sortboard()) {
717 set_score_output();
718 scorerror = writeboard();
719 }
720 }
721 }
722 if ((x == 256) || (x == 257) || (f != 0))
723 exit(0);
724 if (scorerror == 0)
725 showscores(); /* if we updated the scoreboard */
726 if (x == 263)
727 mailbill();
728 exit(0);
729 }
730
731 /*
732 * diedsub(x) Subroutine to print out the line showing the player when he is killed
733 * int x;
734 */
735 void
736 diedsub(int x)
737 {
738 char ch;
739 const char *mod;
740
741 lprintf("Score: %ld, Diff: %ld, %s ", (long) c[GOLD], (long) c[HARDGAME], logname);
742 if (x < 256) {
743 ch = *monster[x].name;
744 if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u')
745 mod = "an";
746 else
747 mod = "a";
748 lprintf("killed by %s %s", mod, monster[x].name);
749 } else
750 lprintf("%s", whydead[x - 256]);
751 if (x != 263)
752 lprintf(" on %s\n", levelname[level]);
753 else
754 lprc('\n');
755 }
756
757 /*
758 * diedlog() Subroutine to read a log file and print it out in ascii format
759 */
760 void
761 diedlog()
762 {
763 int n;
764 char *p;
765 struct stat stbuf;
766 lcreat((char *) 0);
767 if (lopen(logfile) < 0) {
768 lprintf("Can't locate log file <%s>\n", logfile);
769 return;
770 }
771 if (fstat(io_infd, &stbuf) < 0) {
772 lprintf("Can't stat log file <%s>\n", logfile);
773 return;
774 }
775 for (n = stbuf.st_size / sizeof(struct log_fmt); n > 0; --n) {
776 lrfill((char *) &logg, sizeof(struct log_fmt));
777 p = ctime(&logg.diedtime);
778 p[16] = '\n';
779 p[17] = 0;
780 lprintf("Score: %ld, Diff: %ld, %s %s on %ld at %s", (long) (logg.score), (long) (logg.diff), logg.who, logg.what, (long) (logg.cavelev), p + 4);
781 #ifdef EXTRA
782 if (logg.moves <= 0)
783 logg.moves = 1;
784 lprintf(" Experience Level: %ld, AC: %ld, HP: %ld/%ld, Elapsed Time: %ld minutes\n", (long) (logg.lev), (long) (logg.ac), (long) (logg.hp), (long) (logg.hpmax), (long) (logg.elapsedtime));
785 lprintf(" CPU time used: %ld seconds, Machine usage: %ld.%02ld%%\n", (long) (logg.cputime), (long) (logg.usage / 100), (long) (logg.usage % 100));
786 lprintf(" BYTES in: %ld, out: %ld, moves: %ld, deaths: %ld, spells cast: %ld\n", (long) (logg.bytin), (long) (logg.bytout), (long) (logg.moves), (long) (logg.killed), (long) (logg.spused));
787 lprintf(" out bytes per move: %ld, time per move: %ld ms\n", (long) (logg.bytout / logg.moves), (long) ((logg.cputime * 1000) / logg.moves));
788 #endif
789 }
790 lflush();
791 lrclose();
792 return;
793 }
794
795 #ifndef UIDSCORE
796 /*
797 * getplid(name) Function to get players id # from id file
798 *
799 * Enter with the name of the players character in name.
800 * Returns the id # of the players character, or -1 if failure.
801 * This routine will try to find the name in the id file, if its not there,
802 * it will try to make a new entry in the file. Only returns -1 if can't
803 * find him in the file, and can't make a new entry in the file.
804 * Format of playerids file:
805 * Id # in ascii \n character name \n
806 */
807 static int havepid = -1; /* playerid # if previously done */
808 int
809 getplid(nam)
810 char *nam;
811 {
812 int fd7, high = 999, no;
813 char *p, *p2;
814 char name[80];
815 if (havepid != -1)
816 return (havepid); /* already did it */
817 lflush(); /* flush any pending I/O */
818 snprintf(name, sizeof(name), "%s\n", nam);/* append a \n to name */
819 if (lopen(playerids) < 0) { /* no file, make it */
820 if ((fd7 = creat(playerids, 0664)) < 0)
821 return (-1); /* can't make it */
822 close(fd7);
823 goto addone; /* now append new playerid record to file */
824 }
825 for (;;) { /* now search for the name in the player id
826 * file */
827 p = lgetl();
828 if (p == NULL)
829 break; /* EOF? */
830 no = atoi(p); /* the id # */
831 p2 = lgetl();
832 if (p2 == NULL)
833 break; /* EOF? */
834 if (no > high)
835 high = no; /* accumulate highest id # */
836 if (strcmp(p2, name) == 0) { /* we found him */
837 return (no); /* his id number */
838 }
839 }
840 lrclose();
841 /* if we get here, we didn't find him in the file -- put him there */
842 addone:
843 if (lappend(playerids) < 0)
844 return (-1); /* can't open file for append */
845 lprintf("%ld\n%s", (long) ++high, name); /* new id # and name */
846 lwclose();
847 lcreat((char *) 0); /* re-open terminal channel */
848 return (high);
849 }
850 #endif /* UIDSCORE */