1 /* 2 * Copyright (c) 1988, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Timothy C. Stoehr. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 static char sccsid[] = "@(#)score.c 8.1 (Berkeley) 05/31/93"; 13 #endif /* not lint */ 14 15 /* 16 * score.c 17 * 18 * This source herein may be modified and/or distributed by anybody who 19 * so desires, with the following restrictions: 20 * 1.) No portion of this notice shall be removed. 21 * 2.) Credit shall not be taken for the creation of this source. 22 * 3.) This code is not to be traded, sold, or used for personal 23 * gain or profit. 24 * 25 */ 26 27 #include <stdio.h> 28 #include "rogue.h" 29 #include "pathnames.h" 30 31 extern char login_name[]; 32 extern char *m_names[]; 33 extern short max_level; 34 extern boolean score_only, no_skull, msg_cleared; 35 extern char *byebye_string, *nick_name; 36 37 killed_by(monster, other) 38 object *monster; 39 short other; 40 { 41 char buf[128]; 42 43 md_ignore_signals(); 44 45 if (other != QUIT) { 46 rogue.gold = ((rogue.gold * 9) / 10); 47 } 48 49 if (other) { 50 switch(other) { 51 case HYPOTHERMIA: 52 (void) strcpy(buf, "died of hypothermia"); 53 break; 54 case STARVATION: 55 (void) strcpy(buf, "died of starvation"); 56 break; 57 case POISON_DART: 58 (void) strcpy(buf, "killed by a dart"); 59 break; 60 case QUIT: 61 (void) strcpy(buf, "quit"); 62 break; 63 case KFIRE: 64 (void) strcpy(buf, "killed by fire"); 65 break; 66 } 67 } else { 68 (void) strcpy(buf, "Killed by "); 69 if (is_vowel(m_names[monster->m_char - 'A'][0])) { 70 (void) strcat(buf, "an "); 71 } else { 72 (void) strcat(buf, "a "); 73 } 74 (void) strcat(buf, m_names[monster->m_char - 'A']); 75 } 76 (void) strcat(buf, " with "); 77 sprintf(buf+strlen(buf), "%ld gold", rogue.gold); 78 if ((!other) && (!no_skull)) { 79 clear(); 80 mvaddstr(4, 32, "__---------__"); 81 mvaddstr(5, 30, "_~ ~_"); 82 mvaddstr(6, 29, "/ \\"); 83 mvaddstr(7, 28, "~ ~"); 84 mvaddstr(8, 27, "/ \\"); 85 mvaddstr(9, 27, "| XXXX XXXX |"); 86 mvaddstr(10, 27, "| XXXX XXXX |"); 87 mvaddstr(11, 27, "| XXX XXX |"); 88 mvaddstr(12, 28, "\\ @ /"); 89 mvaddstr(13, 29, "--\\ @@@ /--"); 90 mvaddstr(14, 30, "| | @@@ | |"); 91 mvaddstr(15, 30, "| | | |"); 92 mvaddstr(16, 30, "| vvVvvvvvvvVvv |"); 93 mvaddstr(17, 30, "| ^^^^^^^^^^^ |"); 94 mvaddstr(18, 31, "\\_ _/"); 95 mvaddstr(19, 33, "~---------~"); 96 center(21, nick_name); 97 center(22, buf); 98 } else { 99 message(buf, 0); 100 } 101 message("", 0); 102 put_scores(monster, other); 103 } 104 105 win() 106 { 107 unwield(rogue.weapon); /* disarm and relax */ 108 unwear(rogue.armor); 109 un_put_on(rogue.left_ring); 110 un_put_on(rogue.right_ring); 111 112 clear(); 113 mvaddstr(10, 11, "@ @ @@@ @ @ @ @ @ @@@ @ @ @"); 114 mvaddstr(11, 11, " @ @ @ @ @ @ @ @ @ @ @ @@ @ @"); 115 mvaddstr(12, 11, " @ @ @ @ @ @ @ @ @ @ @ @ @ @"); 116 mvaddstr(13, 11, " @ @ @ @ @ @ @ @ @ @ @ @@"); 117 mvaddstr(14, 11, " @ @@@ @@@ @@ @@ @@@ @ @ @"); 118 mvaddstr(17, 11, "Congratulations, you have been admitted to the"); 119 mvaddstr(18, 11, "Fighters' Guild. You return home, sell all your"); 120 mvaddstr(19, 11, "treasures at great profit and retire into comfort."); 121 message("", 0); 122 message("", 0); 123 id_all(); 124 sell_pack(); 125 put_scores((object *) 0, WIN); 126 } 127 128 quit(from_intrpt) 129 boolean from_intrpt; 130 { 131 char buf[128]; 132 short i, orow, ocol; 133 boolean mc; 134 135 md_ignore_signals(); 136 137 if (from_intrpt) { 138 orow = rogue.row; 139 ocol = rogue.col; 140 141 mc = msg_cleared; 142 143 for (i = 0; i < DCOLS; i++) { 144 buf[i] = mvinch(0, i); 145 } 146 } 147 check_message(); 148 message("really quit?", 1); 149 if (rgetchar() != 'y') { 150 md_heed_signals(); 151 check_message(); 152 if (from_intrpt) { 153 for (i = 0; i < DCOLS; i++) { 154 mvaddch(0, i, buf[i]); 155 } 156 msg_cleared = mc; 157 move(orow, ocol); 158 refresh(); 159 } 160 return; 161 } 162 if (from_intrpt) { 163 clean_up(byebye_string); 164 } 165 check_message(); 166 killed_by((object *) 0, QUIT); 167 } 168 169 put_scores(monster, other) 170 object *monster; 171 short other; 172 { 173 short i, n, rank = 10, x, ne = 0, found_player = -1; 174 char scores[10][82]; 175 char n_names[10][30]; 176 char buf[128]; 177 FILE *fp; 178 long s; 179 boolean pause = score_only; 180 181 md_lock(1); 182 183 if ((fp = fopen(_PATH_SCOREFILE, "r+")) == NULL && 184 (fp = fopen(_PATH_SCOREFILE, "w+")) == NULL) { 185 message("cannot read/write/create score file", 0); 186 sf_error(); 187 } 188 rewind(fp); 189 (void) xxx(1); 190 191 for (i = 0; i < 10; i++) { 192 if (((n = fread(scores[i], sizeof(char), 80, fp)) < 80) && (n != 0)) { 193 sf_error(); 194 } else if (n != 0) { 195 xxxx(scores[i], 80); 196 if ((n = fread(n_names[i], sizeof(char), 30, fp)) < 30) { 197 sf_error(); 198 } 199 xxxx(n_names[i], 30); 200 } else { 201 break; 202 } 203 ne++; 204 if ((!score_only) && (found_player == -1)) { 205 if (!name_cmp(scores[i]+15, login_name)) { 206 x = 5; 207 while (scores[i][x] == ' ') { 208 x++; 209 } 210 s = lget_number(scores[i] + x); 211 if (rogue.gold < s) { 212 score_only = 1; 213 } else { 214 found_player = i; 215 } 216 } 217 } 218 } 219 if (found_player != -1) { 220 ne--; 221 for (i = found_player; i < ne; i++) { 222 (void) strcpy(scores[i], scores[i+1]); 223 (void) strcpy(n_names[i], n_names[i+1]); 224 } 225 } 226 if (!score_only) { 227 for (i = 0; i < ne; i++) { 228 x = 5; 229 while (scores[i][x] == ' ') { 230 x++; 231 } 232 s = lget_number(scores[i] + x); 233 234 if (rogue.gold >= s) { 235 rank = i; 236 break; 237 } 238 } 239 if (ne == 0) { 240 rank = 0; 241 } else if ((ne < 10) && (rank == 10)) { 242 rank = ne; 243 } 244 if (rank < 10) { 245 insert_score(scores, n_names, nick_name, rank, ne, monster, 246 other); 247 if (ne < 10) { 248 ne++; 249 } 250 } 251 rewind(fp); 252 } 253 254 clear(); 255 mvaddstr(3, 30, "Top Ten Rogueists"); 256 mvaddstr(8, 0, "Rank Score Name"); 257 258 md_ignore_signals(); 259 260 (void) xxx(1); 261 262 for (i = 0; i < ne; i++) { 263 if (i == rank) { 264 standout(); 265 } 266 if (i == 9) { 267 scores[i][0] = '1'; 268 scores[i][1] = '0'; 269 } else { 270 scores[i][0] = ' '; 271 scores[i][1] = i + '1'; 272 } 273 nickize(buf, scores[i], n_names[i]); 274 mvaddstr(i+10, 0, buf); 275 if (rank < 10) { 276 xxxx(scores[i], 80); 277 fwrite(scores[i], sizeof(char), 80, fp); 278 xxxx(n_names[i], 30); 279 fwrite(n_names[i], sizeof(char), 30, fp); 280 } 281 if (i == rank) { 282 standend(); 283 } 284 } 285 md_lock(0); 286 refresh(); 287 fclose(fp); 288 message("", 0); 289 if (pause) { 290 message("", 0); 291 } 292 clean_up(""); 293 } 294 295 insert_score(scores, n_names, n_name, rank, n, monster, other) 296 char scores[][82]; 297 char n_names[][30]; 298 char *n_name; 299 short rank, n; 300 object *monster; 301 { 302 short i; 303 char buf[128]; 304 305 if (n > 0) { 306 for (i = n; i > rank; i--) { 307 if ((i < 10) && (i > 0)) { 308 (void) strcpy(scores[i], scores[i-1]); 309 (void) strcpy(n_names[i], n_names[i-1]); 310 } 311 } 312 } 313 sprintf(buf, "%2d %6d %s: ", rank+1, rogue.gold, login_name); 314 315 if (other) { 316 switch(other) { 317 case HYPOTHERMIA: 318 (void) strcat(buf, "died of hypothermia"); 319 break; 320 case STARVATION: 321 (void) strcat(buf, "died of starvation"); 322 break; 323 case POISON_DART: 324 (void) strcat(buf, "killed by a dart"); 325 break; 326 case QUIT: 327 (void) strcat(buf, "quit"); 328 break; 329 case WIN: 330 (void) strcat(buf, "a total winner"); 331 break; 332 case KFIRE: 333 (void) strcpy(buf, "killed by fire"); 334 break; 335 } 336 } else { 337 (void) strcat(buf, "killed by "); 338 if (is_vowel(m_names[monster->m_char - 'A'][0])) { 339 (void) strcat(buf, "an "); 340 } else { 341 (void) strcat(buf, "a "); 342 } 343 (void) strcat(buf, m_names[monster->m_char - 'A']); 344 } 345 sprintf(buf+strlen(buf), " on level %d ", max_level); 346 if ((other != WIN) && has_amulet()) { 347 (void) strcat(buf, "with amulet"); 348 } 349 for (i = strlen(buf); i < 79; i++) { 350 buf[i] = ' '; 351 } 352 buf[79] = 0; 353 (void) strcpy(scores[rank], buf); 354 (void) strcpy(n_names[rank], n_name); 355 } 356 357 is_vowel(ch) 358 short ch; 359 { 360 return( (ch == 'a') || 361 (ch == 'e') || 362 (ch == 'i') || 363 (ch == 'o') || 364 (ch == 'u') ); 365 } 366 367 sell_pack() 368 { 369 object *obj; 370 short row = 2, val; 371 char buf[DCOLS]; 372 373 obj = rogue.pack.next_object; 374 375 clear(); 376 mvaddstr(1, 0, "Value Item"); 377 378 while (obj) { 379 if (obj->what_is != FOOD) { 380 obj->identified = 1; 381 val = get_value(obj); 382 rogue.gold += val; 383 384 if (row < DROWS) { 385 sprintf(buf, "%5d ", val); 386 get_desc(obj, buf+11); 387 mvaddstr(row++, 0, buf); 388 } 389 } 390 obj = obj->next_object; 391 } 392 refresh(); 393 if (rogue.gold > MAX_GOLD) { 394 rogue.gold = MAX_GOLD; 395 } 396 message("", 0); 397 } 398 399 get_value(obj) 400 object *obj; 401 { 402 short wc; 403 int val; 404 405 wc = obj->which_kind; 406 407 switch(obj->what_is) { 408 case WEAPON: 409 val = id_weapons[wc].value; 410 if ((wc == ARROW) || (wc == DAGGER) || (wc == SHURIKEN) || 411 (wc == DART)) { 412 val *= obj->quantity; 413 } 414 val += (obj->d_enchant * 85); 415 val += (obj->hit_enchant * 85); 416 break; 417 case ARMOR: 418 val = id_armors[wc].value; 419 val += (obj->d_enchant * 75); 420 if (obj->is_protected) { 421 val += 200; 422 } 423 break; 424 case WAND: 425 val = id_wands[wc].value * (obj->class + 1); 426 break; 427 case SCROL: 428 val = id_scrolls[wc].value * obj->quantity; 429 break; 430 case POTION: 431 val = id_potions[wc].value * obj->quantity; 432 break; 433 case AMULET: 434 val = 5000; 435 break; 436 case RING: 437 val = id_rings[wc].value * (obj->class + 1); 438 break; 439 } 440 if (val <= 0) { 441 val = 10; 442 } 443 return(val); 444 } 445 446 id_all() 447 { 448 short i; 449 450 for (i = 0; i < SCROLS; i++) { 451 id_scrolls[i].id_status = IDENTIFIED; 452 } 453 for (i = 0; i < WEAPONS; i++) { 454 id_weapons[i].id_status = IDENTIFIED; 455 } 456 for (i = 0; i < ARMORS; i++) { 457 id_armors[i].id_status = IDENTIFIED; 458 } 459 for (i = 0; i < WANDS; i++) { 460 id_wands[i].id_status = IDENTIFIED; 461 } 462 for (i = 0; i < POTIONS; i++) { 463 id_potions[i].id_status = IDENTIFIED; 464 } 465 } 466 467 name_cmp(s1, s2) 468 char *s1, *s2; 469 { 470 short i = 0; 471 int r; 472 473 while(s1[i] != ':') { 474 i++; 475 } 476 s1[i] = 0; 477 r = strcmp(s1, s2); 478 s1[i] = ':'; 479 return(r); 480 } 481 482 xxxx(buf, n) 483 char *buf; 484 short n; 485 { 486 short i; 487 unsigned char c; 488 489 for (i = 0; i < n; i++) { 490 491 /* It does not matter if accuracy is lost during this assignment */ 492 c = (unsigned char) xxx(0); 493 494 buf[i] ^= c; 495 } 496 } 497 498 long 499 xxx(st) 500 boolean st; 501 { 502 static long f, s; 503 long r; 504 505 if (st) { 506 f = 37; 507 s = 7; 508 return(0L); 509 } 510 r = ((f * s) + 9337) % 8887; 511 f = s; 512 s = r; 513 return(r); 514 } 515 516 nickize(buf, score, n_name) 517 char *buf, *score, *n_name; 518 { 519 short i = 15, j; 520 521 if (!n_name[0]) { 522 (void) strcpy(buf, score); 523 } else { 524 (void) strncpy(buf, score, 16); 525 526 while (score[i] != ':') { 527 i++; 528 } 529 530 (void) strcpy(buf+15, n_name); 531 j = strlen(buf); 532 533 while (score[i]) { 534 buf[j++] = score[i++]; 535 } 536 buf[j] = 0; 537 buf[79] = 0; 538 } 539 } 540 541 center(row, buf) 542 short row; 543 char *buf; 544 { 545 short margin; 546 547 margin = ((DCOLS - strlen(buf)) / 2); 548 mvaddstr(row, margin, buf); 549 } 550 551 sf_error() 552 { 553 md_lock(0); 554 message("", 1); 555 clean_up("sorry, score file is out of order"); 556 } 557