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