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