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