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