xref: /dragonfly/games/larn/scores.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
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
readboard(void)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
writeboard(void)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
makeboard(void)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
hashewon(void)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
paytaxes(long x)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
winshou(void)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
shou(int x)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
showscores(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
showallscores(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
sortboard(void)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
newscore(long score,char * whoo,int whyded,int winner)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
new1sub(long score,int i,char * whoo,long taxes)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
new2sub(long score,int i,char * whoo,int whyded)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
died(int x)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
diedsub(int x)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
diedlog(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
getplid(char * nam)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 */
789