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