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