Annotation of early-roguelike/xrogue/rip.c, Revision 1.1
1.1 ! rubenllo 1: /*
! 2: rip.c - File for the fun ends Death or a total win
! 3:
! 4: XRogue: Expeditions into the Dungeons of Doom
! 5: Copyright (C) 1991 Robert Pietkivitch
! 6: All rights reserved.
! 7:
! 8: Based on "Advanced Rogue"
! 9: Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
! 10: All rights reserved.
! 11:
! 12: Based on "Rogue: Exploring the Dungeons of Doom"
! 13: Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
! 14: All rights reserved.
! 15:
! 16: See the file LICENSE.TXT for full copyright and licensing information.
! 17: */
! 18:
! 19: #define REALLIFE 1 /* Print out machine and logname */
! 20: #define EDITSCORE 2 /* Edit the current score file */
! 21: #define ADDSCORE 3 /* Add a new score */
! 22:
! 23: #include <stdlib.h>
! 24: #include <curses.h>
! 25: #include <time.h>
! 26: #include <signal.h>
! 27: #include <ctype.h>
! 28: #include <string.h>
! 29: #include <sys/types.h>
! 30: #include <fcntl.h>
! 31: #include "mach_dep.h"
! 32: #include "network.h"
! 33: #include "rogue.h"
! 34:
! 35: /* Network machines (for mutual score keeping) */
! 36: struct network Network[] = {
! 37: { "", "" },
! 38: };
! 39:
! 40: static char *rip[] = {
! 41: " ___________",
! 42: " / \\",
! 43: " / \\",
! 44: " / R. I. P. \\",
! 45: " / \\",
! 46: " / \\",
! 47: " | |",
! 48: " | |",
! 49: " | killed by |",
! 50: " | |",
! 51: " | |",
! 52: " | |",
! 53: " *| * * * |*",
! 54: " _________)|//\\\\///\\///\\//\\//\\/|(_________",
! 55: NULL
! 56: };
! 57:
! 58: int rs_read_scorefile(FILE *savef, struct sc_ent *entries, int count);
! 59: void rs_write_scorefile(FILE *savef, struct sc_ent *entries, int count);
! 60:
! 61: char *killname(short monst);
! 62: void showpack(char *howso);
! 63: int update(struct sc_ent top_ten[], unsigned long amount, short quest,
! 64: char *whoami, short flags, short level, short monst, short ctype,
! 65: char *system, char *login);
! 66:
! 67: extern FILE *scorefi, *logfile;
! 68:
! 69: /*UNUSED*/
! 70: void
! 71: byebye(int sig)
! 72: {
! 73: NOOP(sig);
! 74: exit_game(EXIT_ENDWIN);
! 75: }
! 76:
! 77:
! 78: /*
! 79: * death:
! 80: * Do something really fun when he dies
! 81: */
! 82:
! 83: void
! 84: death(short monst)
! 85: {
! 86: register char **dp = rip, *killer;
! 87: register struct tm *lt;
! 88: time_t date;
! 89: char buf[LINELEN];
! 90: struct tm *localtime();
! 91:
! 92: writelog(pstats.s_exp, KILLED, monst);
! 93: time(&date);
! 94: lt = localtime(&date);
! 95: clear();
! 96: move(8, 0);
! 97: while (*dp)
! 98: printw("%s\n", *dp++);
! 99: mvaddstr(14, 28-((strlen(whoami)+1)/2), whoami);
! 100: sprintf(buf, "%lu Points", pstats.s_exp );
! 101: mvaddstr(15, 28-((strlen(buf)+1)/2), buf);
! 102: killer = killname(monst);
! 103: mvaddstr(17, 28-((strlen(killer)+1)/2), killer);
! 104: mvaddstr(18, 25, (sprintf(prbuf, "%4d", 1900+lt->tm_year), prbuf));
! 105: move(lines-1, 0);
! 106: refresh();
! 107: score(pstats.s_exp, KILLED, monst);
! 108: exit_game(EXIT_ENDWIN);
! 109: }
! 110:
! 111: char *
! 112: killname(short monst)
! 113: {
! 114: static char mons_name[LINELEN/2];
! 115: int i;
! 116:
! 117: if (monst > NUMMONST) return("a strange monster");
! 118:
! 119: if (monst >= 0) {
! 120: switch (monsters[monst].m_name[0]) {
! 121: case 'a':
! 122: case 'e':
! 123: case 'i':
! 124: case 'o':
! 125: case 'u':
! 126: sprintf(mons_name, "an %s", monsters[monst].m_name);
! 127: break;
! 128: default:
! 129: sprintf(mons_name, "a %s", monsters[monst].m_name);
! 130: }
! 131: return(mons_name);
! 132: }
! 133: for (i = 0; i< DEATHNUM; i++) {
! 134: if (deaths[i].reason == monst)
! 135: break;
! 136: }
! 137: if (i >= DEATHNUM)
! 138: return ("strange death");
! 139: return (deaths[i].name);
! 140: }
! 141:
! 142: /* Writes an entry in the log file */
! 143:
! 144: void
! 145: writelog(unsigned long amount, int flags, short monst)
! 146: {
! 147: char had_quest = '0';
! 148: char fate[LINELEN];
! 149: struct linked_list *item;
! 150: struct object *obj;
! 151: #ifdef LOGFILE
! 152: if (waswizard)
! 153: return;
! 154: if (logfile == NULL)
! 155: {
! 156: /* Error message? */
! 157: return;
! 158: }
! 159: /* Adjustments to the score */
! 160: if (level == 0 && max_level == 0)
! 161: amount = 0;
! 162: if (flags == CHICKEN)
! 163: amount /= 100;
! 164: /* Check for quest item */
! 165: for (item = pack; item != NULL; item = next(item)) {
! 166: obj = OBJPTR(item);
! 167: if (obj->o_type == RELIC && obj->o_which == quest_item)
! 168: had_quest = '1';
! 169: }
! 170: /* Describe what happened */
! 171: if (flags == KILLED) {
! 172: snprintf(fate, LINELEN, "killed by %s", killname(monst));
! 173: }
! 174: else if (flags == CHICKEN) {
! 175: strcpy(fate, "quit");
! 176: }
! 177: else if (flags == WINNER) {
! 178: strcpy(fate, "escaped");
! 179: }
! 180: else
! 181: return;
! 182: /* Write the line */
! 183: fprintf(logfile, "%ld %ld %s %d %s %d %d %d %c %s\n", time(NULL), amount,
! 184: whoami, pstats.s_lvl, char_class[char_type].name, level, max_level,
! 185: quest_item, had_quest, fate);
! 186: fclose(logfile);
! 187: #endif
! 188: return;
! 189: }
! 190:
! 191: /*
! 192: * score -- figure score and post it.
! 193: */
! 194:
! 195: /* VARARGS2 */
! 196: void
! 197: score(unsigned long amount, int flags, short monst)
! 198: {
! 199: struct sc_ent top_ten[NUMSCORE];
! 200: register struct sc_ent *scp;
! 201: register int i;
! 202: register struct sc_ent *sc2;
! 203: register FILE *outf;
! 204: register char *killer;
! 205: register int prflags = 0;
! 206: short upquest=0, wintype=0, uplevel=0, uptype=0; /* For network updating */
! 207: char upsystem[SYSLEN], uplogin[LOGLEN];
! 208: char *thissys; /* Holds the name of this system */
! 209:
! 210: #define REASONLEN 3
! 211: static char *reason[] = {
! 212: "killed",
! 213: "quit",
! 214: "A total winner",
! 215: "somehow left",
! 216: };
! 217: char *packend;
! 218:
! 219: memset(top_ten,0,sizeof(top_ten));
! 220:
! 221: signal(SIGINT, byebye);
! 222: if (level == 0 && max_level == 0)
! 223: amount = 0; /*don't count if quit early */
! 224: if (flags != WINNER && flags != SCOREIT && flags != UPDATE) {
! 225: if (flags == CHICKEN) {
! 226: packend = "when you quit";
! 227: amount = amount / 100;
! 228: }
! 229: else
! 230: packend = "at your untimely demise";
! 231: mvaddstr(lines - 1, 0, retstr);
! 232: refresh();
! 233: getstr(prbuf);
! 234: showpack(packend);
! 235: }
! 236: purse = 0; /* Steal all the gold */
! 237:
! 238: /*
! 239: * Open file and read list
! 240: */
! 241:
! 242: if (scorefi == NULL)
! 243: {
! 244: mvprintw(lines - 1, 0, "Unable to open or create score file: %s",score_file);
! 245: refresh();
! 246: return;
! 247: }
! 248: else
! 249: {
! 250: outf = scorefi;
! 251: }
! 252:
! 253: thissys = md_gethostname();
! 254:
! 255: /*
! 256: * If this is a SCOREIT optin (rogue -s), don't call byebye. The
! 257: * endwin() calls in byebye() will and this results in a core dump.
! 258: */
! 259: if (flags == SCOREIT) signal(SIGINT, SIG_DFL);
! 260: else signal(SIGINT, byebye);
! 261:
! 262: if (flags != SCOREIT && flags != UPDATE)
! 263: {
! 264: mvaddstr(lines - 1, 0, retstr);
! 265: refresh();
! 266: fflush(stdout);
! 267: getstr(prbuf);
! 268: }
! 269:
! 270: /* Check for special options */
! 271: if (strcmp(prbuf, "names") == 0)
! 272: prflags = REALLIFE;
! 273: else if (wizard) {
! 274: if (strcmp(prbuf, "edit") == 0) prflags = EDITSCORE;
! 275: else if (strcmp(prbuf, "add") == 0) {
! 276: prflags = ADDSCORE;
! 277: waswizard = FALSE; /* We want the new score recorded */
! 278: }
! 279: }
! 280:
! 281: /* Read the score and convert it to a compatible format */
! 282:
! 283: fseek(outf, 0, SEEK_SET);
! 284: rs_read_scorefile(outf, top_ten, NUMSCORE);
! 285:
! 286: /* Get some values if this is an update */
! 287: if (flags == UPDATE) {
! 288: int errcheck, errors = 0;
! 289:
! 290: upquest = (short) netread(&errcheck, sizeof(short), stdin);
! 291: if (errcheck) errors++;
! 292:
! 293: if (fread(whoami, 1, NAMELEN, stdin) != NAMELEN) errors++;
! 294:
! 295: wintype = (short) netread(&errcheck, sizeof(short), stdin);
! 296: if (errcheck) errors++;
! 297:
! 298: uplevel = (short) netread(&errcheck, sizeof(short), stdin);
! 299: if (errcheck) errors++;
! 300:
! 301: uptype = (short) netread(&errcheck, sizeof(short), stdin);
! 302: if (errcheck) errors++;
! 303:
! 304: if (fread(upsystem, 1, SYSLEN, stdin) != SYSLEN)
! 305: errors++;
! 306: if (fread(uplogin, 1, LOGLEN, stdin) != LOGLEN)
! 307: errors++;
! 308:
! 309: if (errors) {
! 310: fclose(outf);
! 311: return;
! 312: }
! 313: }
! 314:
! 315: /*
! 316: * Insert player in list if need be
! 317: */
! 318: if (!waswizard) {
! 319: char *login= NULL;
! 320:
! 321: if (flags != UPDATE) {
! 322: login = md_getusername();
! 323:
! 324: if ((login == NULL) || (*login == 0))
! 325: login = "another rogue fiend";
! 326: }
! 327:
! 328: if (flags == UPDATE)
! 329: (void) update(top_ten, amount, upquest, whoami, wintype,
! 330: uplevel, monst, uptype, upsystem, uplogin);
! 331: else {
! 332: if (prflags == ADDSCORE) { /* Overlay characteristic by new ones */
! 333: char buffer[LINELEN];
! 334:
! 335: clear();
! 336: mvaddstr(1, 0, "Score: ");
! 337: mvaddstr(2, 0, "Quest (number): ");
! 338: mvaddstr(3, 0, "Name: ");
! 339: mvaddstr(4, 0, "System: ");
! 340: mvaddstr(5, 0, "Login: ");
! 341: mvaddstr(6, 0, "Level: ");
! 342: mvaddstr(7, 0, "Char type: ");
! 343: mvaddstr(8, 0, "Result: ");
! 344:
! 345: /* Get the score */
! 346: move(1, 7);
! 347: get_str(buffer, stdscr);
! 348: amount = atol(buffer);
! 349:
! 350: /* Get the character's quest -- must be a number */
! 351: move(2, 16);
! 352: get_str(buffer, stdscr);
! 353: quest_item = atoi(buffer);
! 354:
! 355: /* Get the character's name */
! 356: move(3, 6);
! 357: get_str(buffer, stdscr);
! 358: strncpy(whoami, buffer, NAMELEN);
! 359:
! 360: /* Get the system */
! 361: move(4, 8);
! 362: get_str(buffer, stdscr);
! 363: strncpy(thissys, buffer, SYSLEN);
! 364:
! 365: /* Get the login */
! 366: move(5, 7);
! 367: get_str(buffer, stdscr);
! 368: strncpy(login, buffer, LOGLEN);
! 369:
! 370: /* Get the level */
! 371: move(6, 7);
! 372: get_str(buffer, stdscr);
! 373: level = max_level = (short) atoi(buffer);
! 374:
! 375: /* Get the character type */
! 376: move(7, 11);
! 377: get_str(buffer, stdscr);
! 378: for (i=0; i<NUM_CHARTYPES; i++) {
! 379: if (EQSTR(buffer, char_class[i].name, strlen(buffer)))
! 380: break;
! 381: }
! 382: player.t_ctype = i;
! 383:
! 384: /* Get the win type */
! 385: move(8, 8);
! 386: get_str(buffer, stdscr);
! 387: switch (buffer[0]) {
! 388: case 'W':
! 389: case 'w':
! 390: case 'T':
! 391: case 't':
! 392: flags = WINNER;
! 393: break;
! 394:
! 395: case 'Q':
! 396: case 'q':
! 397: flags = CHICKEN;
! 398: break;
! 399:
! 400: case 'k':
! 401: case 'K':
! 402: default:
! 403: flags = KILLED;
! 404: break;
! 405: }
! 406:
! 407: /* Get the monster if player was killed */
! 408: if (flags == KILLED) {
! 409: mvaddstr(9, 0, "Death type: ");
! 410: get_str(buffer, stdscr);
! 411: if (buffer[0] == 'M' || buffer[0] == 'm')
! 412: do {
! 413: monst = makemonster(TRUE, "choose");
! 414: } while (monst < 0); /* Force a choice */
! 415: else monst = getdeath();
! 416: }
! 417: }
! 418:
! 419: if (update(top_ten, amount, (short) quest_item, whoami, flags,
! 420: (flags == WINNER) ? (short) max_level : (short) level,
! 421: monst, player.t_ctype, thissys, login)
! 422: ) {
! 423: /* Send this update to the other systems in the network */
! 424: int i, j;
! 425: char cmd[256]; /* Command for remote execution */
! 426: FILE *rmf, *popen(); /* For input to remote command */
! 427:
! 428: for (i=0; Network[i].system[0] != 0; i++)
! 429: if (Network[i].system[0] != '!' &&
! 430: strcmp(Network[i].system, thissys)) {
! 431: sprintf(cmd, NETCOMMAND,
! 432: Network[i].system, Network[i].rogue);
! 433:
! 434: /* Execute the command */
! 435: if ((rmf=popen(cmd, "w")) != NULL) {
! 436: unsigned long temp; /* Temporary value */
! 437:
! 438: /* Write out the parameters */
! 439: (void) netwrite((unsigned long) amount,
! 440: sizeof(unsigned long), rmf);
! 441:
! 442: (void) netwrite((unsigned long) monst,
! 443: sizeof(short), rmf);
! 444:
! 445: (void) netwrite((unsigned long) quest_item,
! 446: sizeof(short), rmf);
! 447:
! 448: (void) fwrite(whoami, 1, strlen(whoami), rmf);
! 449: for (j=strlen(whoami); j<NAMELEN; j++)
! 450: putc('\0', rmf);
! 451:
! 452: (void) netwrite((unsigned long) flags,
! 453: sizeof(short), rmf);
! 454:
! 455: temp = (unsigned long)
! 456: (flags==WINNER ? max_level : level);
! 457: (void) netwrite(temp, sizeof(short), rmf);
! 458:
! 459: (void) netwrite((unsigned long) player.t_ctype,
! 460: sizeof(short), rmf);
! 461:
! 462: (void) fwrite(thissys, 1,
! 463: strlen(thissys), rmf);
! 464: for (j=strlen(thissys); j<SYSLEN; j++)
! 465: putc('\0', rmf);
! 466:
! 467: (void) fwrite(login, 1, strlen(login), rmf);
! 468: for (j=strlen(login); j<LOGLEN; j++)
! 469: putc('\0', rmf);
! 470:
! 471: /* Close off the command */
! 472: (void) pclose(rmf);
! 473: }
! 474: }
! 475: }
! 476: }
! 477: }
! 478:
! 479: /*
! 480: * SCOREIT -- rogue -s option. Never started curses if this option.
! 481: * UPDATE -- network scoring update. Never started curses if this option.
! 482: * EDITSCORE -- want to delete or change a score.
! 483: */
! 484: /* if (flags != SCOREIT && flags != UPDATE && prflags != EDITSCORE)
! 485: endwin(); */
! 486:
! 487: if (flags != UPDATE) {
! 488: if (flags != SCOREIT) {
! 489: clear();
! 490: refresh();
! 491: endwin();
! 492: }
! 493: /*
! 494: * Print the list
! 495: */
! 496: printf("\nTop %d Adventurers:\nRank Score\tName\n",
! 497: NUMSCORE);
! 498: for (scp = top_ten; scp < &top_ten[NUMSCORE]; scp++) {
! 499: char *class;
! 500:
! 501: if (scp->sc_score != 0) {
! 502: class = char_class[scp->sc_ctype].name;
! 503:
! 504: /* Make sure we have an in-bound reason */
! 505: if (scp->sc_flags > REASONLEN) scp->sc_flags = REASONLEN;
! 506:
! 507: printf("%3d %10lu\t%s (%s)", scp - top_ten + 1,
! 508: scp->sc_score, scp->sc_name, class);
! 509:
! 510: if (prflags == REALLIFE) printf(" [in real life %.*s!%.*s]",
! 511: SYSLEN, scp->sc_system, LOGLEN, scp->sc_login);
! 512:
! 513: printf(":\n\t\t%s on level %d", reason[scp->sc_flags],
! 514: scp->sc_level);
! 515:
! 516: switch (scp->sc_flags) {
! 517: case KILLED:
! 518: printf(" by");
! 519: killer = killname(scp->sc_monster);
! 520: printf(" %s", killer);
! 521: break;
! 522:
! 523: case WINNER:
! 524: printf(" with the %s",
! 525: rel_magic[scp->sc_quest].mi_name);
! 526: break;
! 527: }
! 528:
! 529: if (prflags == EDITSCORE)
! 530: {
! 531: fflush(stdout);
! 532: getstr(prbuf);
! 533: printf("\n");
! 534: if (prbuf[0] == 'd') {
! 535: for (sc2 = scp; sc2 < &top_ten[NUMSCORE-1]; sc2++)
! 536: *sc2 = *(sc2 + 1);
! 537: top_ten[NUMSCORE-1].sc_score = 0;
! 538: for (i = 0; i < NAMELEN; i++)
! 539: top_ten[NUMSCORE-1].sc_name[i] = rnd(255);
! 540: top_ten[NUMSCORE-1].sc_flags = RN;
! 541: top_ten[NUMSCORE-1].sc_level = RN;
! 542: top_ten[NUMSCORE-1].sc_monster = RN;
! 543: scp--;
! 544: }
! 545: else if (prbuf[0] == 'e') {
! 546: printf("Death type: ");
! 547: getstr(prbuf);
! 548: if (prbuf[0] == 'M' || prbuf[0] == 'm')
! 549: do {
! 550: scp->sc_monster =
! 551: makemonster(TRUE, "choose");
! 552: } while (scp->sc_monster < 0); /* Force a choice */
! 553: else scp->sc_monster = getdeath();
! 554: clear();
! 555: refresh();
! 556: }
! 557: }
! 558: else printf("\n");
! 559: }
! 560: }
! 561: if (flags != SCOREIT)
! 562: {
! 563: printf("\n[Press return to exit]");
! 564: fflush(stdout);
! 565: fgets(prbuf,80,stdin);
! 566: }
! 567: /* if (prflags == EDITSCORE) endwin();*/ /* End editing windowing */
! 568: }
! 569: fseek(outf, 0L, SEEK_SET);
! 570:
! 571: if (flags != SCOREIT)
! 572: rs_write_scorefile(outf,top_ten,NUMSCORE);
! 573: fclose(outf);
! 574: }
! 575:
! 576: /*
! 577: * showpack:
! 578: * Display the contents of the hero's pack
! 579: */
! 580:
! 581: void
! 582: showpack(char *howso)
! 583: {
! 584: reg char *iname;
! 585: reg int cnt, packnum;
! 586: reg struct linked_list *item;
! 587: reg struct object *obj;
! 588:
! 589: idenpack();
! 590: cnt = 1;
! 591: clear();
! 592: mvprintw(0, 0, "Contents of your pack %s:\n",howso);
! 593: packnum = 'a';
! 594: for (item = pack; item != NULL; item = next(item)) {
! 595: obj = OBJPTR(item);
! 596: iname = inv_name(obj, FALSE);
! 597: mvprintw(cnt, 0, "%c) %s\n",packnum++,iname);
! 598: if (++cnt >= lines - 2 &&
! 599: next(item) != NULL) {
! 600: cnt = 1;
! 601: mvaddstr(lines - 1, 0, morestr);
! 602: refresh();
! 603: wait_for(' ');
! 604: clear();
! 605: }
! 606: }
! 607: mvprintw(cnt + 1,0,"--- %ld Gold Pieces ---",purse);
! 608: refresh();
! 609: }
! 610:
! 611: void
! 612: total_winner(void)
! 613: {
! 614: register struct linked_list *item;
! 615: register struct object *obj;
! 616: register long worth;
! 617: register char c;
! 618: register long oldpurse;
! 619:
! 620: clear();
! 621: standout();
! 622: addstr(" \n");
! 623: addstr(" @ @ @ @ @ @@@ @ @ \n");
! 624: addstr(" @ @ @@ @@ @ @ @ @ \n");
! 625: addstr(" @ @ @@@ @ @ @ @ @ @@@ @@@@ @@@ @ @@@ @ \n");
! 626: addstr(" @@@@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ \n");
! 627: addstr(" @ @ @ @ @ @ @ @@@@ @ @ @@@@@ @ @ @ \n");
! 628: addstr(" @ @ @ @ @ @@ @ @ @ @ @ @ @ @ @ @ \n");
! 629: addstr(" @@@ @@@ @@ @ @ @ @@@@ @@@@ @@@ @@@ @@ @ \n");
! 630: addstr(" \n");
! 631: addstr(" Congratulations, you have made it to the light of day! \n");
! 632: standend();
! 633: addstr("\nYou have joined the elite ranks of those who have escaped the\n");
! 634: addstr("Dungeons of Doom alive. You journey home and sell all your loot at\n");
! 635: addstr("a great profit and are appointed ");
! 636: switch (player.t_ctype) {
! 637: case C_FIGHTER: addstr("Leader of the Fighter's Guild.\n");
! 638: when C_RANGER: addstr("King of the Northern Land.\n");
! 639: when C_PALADIN: addstr("King of the Southern Land.\n");
! 640: when C_MAGICIAN:addstr("High Wizard of the Sorcerer's Guild.\n");
! 641: when C_CLERIC: addstr("Bishop of the Monastery.\n");
! 642: when C_THIEF: addstr("Leader of the Thief's Guild.\n");
! 643: when C_MONK: addstr("Master of the Temple.\n");
! 644: when C_ASSASSIN: addstr("Leader of the Assassin's Guild.\n");
! 645: when C_DRUID: addstr("High Priest of the Monastery.\n");
! 646: otherwise: addstr("Town Drunk in the Tavern.\n");
! 647: }
! 648: mvaddstr(lines - 1, 0, spacemsg);
! 649: refresh();
! 650: wait_for(' ');
! 651: clear();
! 652: mvaddstr(0, 0, " Worth Item");
! 653: oldpurse = purse;
! 654: for (c = 'a', item = pack; item != NULL; c++, item = next(item))
! 655: {
! 656: obj = OBJPTR(item);
! 657: worth = get_worth(obj);
! 658: if (obj->o_group == 0)
! 659: worth *= obj->o_count;
! 660: whatis(item);
! 661: mvprintw(c-'a'+1, 0, "%c) %6ld %s", c, worth, inv_name(obj, FALSE));
! 662: purse += worth;
! 663: }
! 664: mvprintw(c - 'a' + 1, 0," %5ld Gold Pieces ", oldpurse);
! 665: refresh();
! 666: writelog(pstats.s_exp + (long) purse, WINNER, '\0');
! 667: score(pstats.s_exp + (long) purse, WINNER, '\0');
! 668: exit_game(EXIT_ENDWIN);
! 669: }
! 670:
! 671:
! 672: void
! 673: delete_score(struct sc_ent top_ten[NUMSCORE], int idx)
! 674: {
! 675: for(;idx < NUMSCORE-1;idx++)
! 676: top_ten[idx] = top_ten[idx+1];
! 677:
! 678: top_ten[NUMSCORE-1].sc_score = 0L;
! 679: }
! 680:
! 681: int
! 682: insert_score(struct sc_ent top_ten[NUMSCORE], struct sc_ent *sc)
! 683: {
! 684: int i,j;
! 685:
! 686: if (top_ten[NUMSCORE-1].sc_score > 0)
! 687: return(-1); /* no room */
! 688:
! 689: for(i = 0; i < NUMSCORE; i++) {
! 690: if (sc->sc_score > top_ten[i].sc_score) {
! 691: for(j = NUMSCORE-1; j > i; j--)
! 692: top_ten[j] = top_ten[j-1];
! 693: top_ten[i] = *sc;
! 694: return(i);
! 695: }
! 696: }
! 697:
! 698: return(-1);
! 699: }
! 700:
! 701: /* PCS = player-class-system (used to determines uniqueness of player) */
! 702:
! 703: bool
! 704: is_pcs_match(struct sc_ent *sc1, struct sc_ent *sc2)
! 705: {
! 706: return( (strcmp(sc1->sc_name,sc2->sc_name) == 0) &&
! 707: (sc1->sc_ctype == sc2->sc_ctype) &&
! 708: (strcmp(sc1->sc_system, sc2->sc_system)==0) );
! 709: }
! 710:
! 711: int
! 712: count_pcs_matches(struct sc_ent top_ten[NUMSCORE], struct sc_ent *sc,
! 713: int *lowest)
! 714: {
! 715: int i, matches = 0;
! 716:
! 717: *lowest = -1;
! 718:
! 719: for(i = 0; i < NUMSCORE; i++) {
! 720: if (is_pcs_match(sc,&top_ten[i])) {
! 721: matches++;
! 722: *lowest = i;
! 723: }
! 724: }
! 725: return(matches);
! 726: }
! 727:
! 728: int
! 729: find_most_pcs_matches(struct sc_ent top_ten[NUMSCORE], struct sc_ent *sc,
! 730: int *num, int *idx)
! 731: {
! 732: int i, matches, max_match=0, max_match_idx=-1, lowest;
! 733:
! 734: for(i = NUMSCORE-1; i > 0; i--) {
! 735: matches = count_pcs_matches(top_ten,&top_ten[i],&lowest);
! 736:
! 737: if (matches > max_match) {
! 738: max_match = matches;
! 739: max_match_idx = lowest;
! 740: }
! 741: }
! 742:
! 743: matches = count_pcs_matches(top_ten,sc,&lowest) + 1;
! 744:
! 745: if (matches > max_match) {
! 746: *num = matches;
! 747: *idx = lowest;
! 748: }
! 749: else {
! 750: *num = max_match;
! 751: *idx = max_match_idx;
! 752: }
! 753:
! 754: return(0);
! 755: }
! 756:
! 757:
! 758: void
! 759: add_score(struct sc_ent top_ten[NUMSCORE], struct sc_ent *sc)
! 760: {
! 761: int idx, count;
! 762:
! 763: if (insert_score(top_ten,sc) == -1) {
! 764: /* Simple insert if space available in table */
! 765:
! 766: find_most_pcs_matches(top_ten,sc,&count,&idx);
! 767:
! 768: /* EVERY ENTRY UNIQUE, */
! 769: /* INSERT IF SCORE > LOWEST MATCH SCORE */
! 770: if (count == 1) {
! 771: if (sc->sc_score > top_ten[idx].sc_score) {
! 772: delete_score(top_ten,idx);
! 773: insert_score(top_ten,sc);
! 774: }
! 775: }
! 776: /* CURRENT PCS HAS HIGHEST DUPE COUNT */
! 777: /* INSERT IF SCORE > LOWEST MATCH SCORE */
! 778: else if (is_pcs_match(sc,&top_ten[idx])) {
! 779: if (sc->sc_score > top_ten[idx].sc_score) {
! 780: delete_score(top_ten,idx);
! 781: insert_score(top_ten,sc);
! 782: }
! 783: }
! 784: /* UNRELATED PCS HAS HIGHEST DUPE COUNT */
! 785: /* DELETE LOWEST DUPE TO MAKE ROOM AND INSERT */
! 786: else {
! 787: delete_score(top_ten,idx);
! 788: insert_score(top_ten,sc);
! 789: }
! 790: }
! 791: }
! 792:
! 793: int
! 794: update(struct sc_ent top_ten[], unsigned long amount, short quest, char *whoami,
! 795: short flags, short level, short monst, short ctype, char *system,
! 796: char *login)
! 797: {
! 798: struct sc_ent sc;
! 799:
! 800: sc.sc_score = amount;
! 801: sc.sc_quest = quest;
! 802: strncpy(sc.sc_name, whoami, NAMELEN);
! 803: sc.sc_name[NAMELEN-1] = 0;
! 804: sc.sc_flags = flags;
! 805: sc.sc_level = level;
! 806: sc.sc_monster = monst;
! 807: sc.sc_ctype = ctype;
! 808: strncpy(sc.sc_system, system, SYSLEN);
! 809: sc.sc_system[SYSLEN - 1] = 0;
! 810: strncpy(sc.sc_login, login, LOGLEN);
! 811: sc.sc_login[LOGLEN-1] = 0;
! 812:
! 813: add_score(top_ten, &sc);
! 814: return(1);
! 815: }
! 816:
CVSweb