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