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