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