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