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