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