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