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