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