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 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 static char sccsid[] = "@(#)score.c 5.5 (Berkeley) 06/01/90"; 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, "a+")) == NULL) { 184 message("cannot read/write/create score file", 0); 185 sf_error(); 186 } 187 rewind(fp); 188 (void) xxx(1); 189 190 for (i = 0; i < 10; i++) { 191 if (((n = fread(scores[i], sizeof(char), 80, fp)) < 80) && (n != 0)) { 192 sf_error(); 193 } else if (n != 0) { 194 xxxx(scores[i], 80); 195 if ((n = fread(n_names[i], sizeof(char), 30, fp)) < 30) { 196 sf_error(); 197 } 198 xxxx(n_names[i], 30); 199 } else { 200 break; 201 } 202 ne++; 203 if ((!score_only) && (found_player == -1)) { 204 if (!name_cmp(scores[i]+15, login_name)) { 205 x = 5; 206 while (scores[i][x] == ' ') { 207 x++; 208 } 209 s = lget_number(scores[i] + x); 210 if (rogue.gold < s) { 211 score_only = 1; 212 } else { 213 found_player = i; 214 } 215 } 216 } 217 } 218 if (found_player != -1) { 219 ne--; 220 for (i = found_player; i < ne; i++) { 221 (void) strcpy(scores[i], scores[i+1]); 222 (void) strcpy(n_names[i], n_names[i+1]); 223 } 224 } 225 if (!score_only) { 226 for (i = 0; i < ne; i++) { 227 x = 5; 228 while (scores[i][x] == ' ') { 229 x++; 230 } 231 s = lget_number(scores[i] + x); 232 233 if (rogue.gold >= s) { 234 rank = i; 235 break; 236 } 237 } 238 if (ne == 0) { 239 rank = 0; 240 } else if ((ne < 10) && (rank == 10)) { 241 rank = ne; 242 } 243 if (rank < 10) { 244 insert_score(scores, n_names, nick_name, rank, ne, monster, 245 other); 246 if (ne < 10) { 247 ne++; 248 } 249 } 250 rewind(fp); 251 } 252 253 clear(); 254 mvaddstr(3, 30, "Top Ten Rogueists"); 255 mvaddstr(8, 0, "Rank Score Name"); 256 257 md_ignore_signals(); 258 259 (void) xxx(1); 260 261 for (i = 0; i < ne; i++) { 262 if (i == rank) { 263 standout(); 264 } 265 if (i == 9) { 266 scores[i][0] = '1'; 267 scores[i][1] = '0'; 268 } else { 269 scores[i][0] = ' '; 270 scores[i][1] = i + '1'; 271 } 272 nickize(buf, scores[i], n_names[i]); 273 mvaddstr(i+10, 0, buf); 274 if (rank < 10) { 275 xxxx(scores[i], 80); 276 fwrite(scores[i], sizeof(char), 80, fp); 277 xxxx(n_names[i], 30); 278 fwrite(n_names[i], sizeof(char), 30, fp); 279 } 280 if (i == rank) { 281 standend(); 282 } 283 } 284 md_lock(0); 285 refresh(); 286 fclose(fp); 287 message("", 0); 288 if (pause) { 289 message("", 0); 290 } 291 clean_up(""); 292 } 293 294 insert_score(scores, n_names, n_name, rank, n, monster, other) 295 char scores[][82]; 296 char n_names[][30]; 297 char *n_name; 298 short rank, n; 299 object *monster; 300 { 301 short i; 302 char buf[128]; 303 304 if (n > 0) { 305 for (i = n; i > rank; i--) { 306 if ((i < 10) && (i > 0)) { 307 (void) strcpy(scores[i], scores[i-1]); 308 (void) strcpy(n_names[i], n_names[i-1]); 309 } 310 } 311 } 312 sprintf(buf, "%2d %6d %s: ", rank+1, rogue.gold, login_name); 313 314 if (other) { 315 switch(other) { 316 case HYPOTHERMIA: 317 (void) strcat(buf, "died of hypothermia"); 318 break; 319 case STARVATION: 320 (void) strcat(buf, "died of starvation"); 321 break; 322 case POISON_DART: 323 (void) strcat(buf, "killed by a dart"); 324 break; 325 case QUIT: 326 (void) strcat(buf, "quit"); 327 break; 328 case WIN: 329 (void) strcat(buf, "a total winner"); 330 break; 331 case KFIRE: 332 (void) strcpy(buf, "killed by fire"); 333 break; 334 } 335 } else { 336 (void) strcat(buf, "killed by "); 337 if (is_vowel(m_names[monster->m_char - 'A'][0])) { 338 (void) strcat(buf, "an "); 339 } else { 340 (void) strcat(buf, "a "); 341 } 342 (void) strcat(buf, m_names[monster->m_char - 'A']); 343 } 344 sprintf(buf+strlen(buf), " on level %d ", max_level); 345 if ((other != WIN) && has_amulet()) { 346 (void) strcat(buf, "with amulet"); 347 } 348 for (i = strlen(buf); i < 79; i++) { 349 buf[i] = ' '; 350 } 351 buf[79] = 0; 352 (void) strcpy(scores[rank], buf); 353 (void) strcpy(n_names[rank], n_name); 354 } 355 356 is_vowel(ch) 357 short ch; 358 { 359 return( (ch == 'a') || 360 (ch == 'e') || 361 (ch == 'i') || 362 (ch == 'o') || 363 (ch == 'u') ); 364 } 365 366 sell_pack() 367 { 368 object *obj; 369 short row = 2, val; 370 char buf[DCOLS]; 371 372 obj = rogue.pack.next_object; 373 374 clear(); 375 mvaddstr(1, 0, "Value Item"); 376 377 while (obj) { 378 if (obj->what_is != FOOD) { 379 obj->identified = 1; 380 val = get_value(obj); 381 rogue.gold += val; 382 383 if (row < DROWS) { 384 sprintf(buf, "%5d ", val); 385 get_desc(obj, buf+11); 386 mvaddstr(row++, 0, buf); 387 } 388 } 389 obj = obj->next_object; 390 } 391 refresh(); 392 if (rogue.gold > MAX_GOLD) { 393 rogue.gold = MAX_GOLD; 394 } 395 message("", 0); 396 } 397 398 get_value(obj) 399 object *obj; 400 { 401 short wc; 402 int val; 403 404 wc = obj->which_kind; 405 406 switch(obj->what_is) { 407 case WEAPON: 408 val = id_weapons[wc].value; 409 if ((wc == ARROW) || (wc == DAGGER) || (wc == SHURIKEN) || 410 (wc == DART)) { 411 val *= obj->quantity; 412 } 413 val += (obj->d_enchant * 85); 414 val += (obj->hit_enchant * 85); 415 break; 416 case ARMOR: 417 val = id_armors[wc].value; 418 val += (obj->d_enchant * 75); 419 if (obj->is_protected) { 420 val += 200; 421 } 422 break; 423 case WAND: 424 val = id_wands[wc].value * (obj->class + 1); 425 break; 426 case SCROL: 427 val = id_scrolls[wc].value * obj->quantity; 428 break; 429 case POTION: 430 val = id_potions[wc].value * obj->quantity; 431 break; 432 case AMULET: 433 val = 5000; 434 break; 435 case RING: 436 val = id_rings[wc].value * (obj->class + 1); 437 break; 438 } 439 if (val <= 0) { 440 val = 10; 441 } 442 return(val); 443 } 444 445 id_all() 446 { 447 short i; 448 449 for (i = 0; i < SCROLS; i++) { 450 id_scrolls[i].id_status = IDENTIFIED; 451 } 452 for (i = 0; i < WEAPONS; i++) { 453 id_weapons[i].id_status = IDENTIFIED; 454 } 455 for (i = 0; i < ARMORS; i++) { 456 id_armors[i].id_status = IDENTIFIED; 457 } 458 for (i = 0; i < WANDS; i++) { 459 id_wands[i].id_status = IDENTIFIED; 460 } 461 for (i = 0; i < POTIONS; i++) { 462 id_potions[i].id_status = IDENTIFIED; 463 } 464 } 465 466 name_cmp(s1, s2) 467 char *s1, *s2; 468 { 469 short i = 0; 470 int r; 471 472 while(s1[i] != ':') { 473 i++; 474 } 475 s1[i] = 0; 476 r = strcmp(s1, s2); 477 s1[i] = ':'; 478 return(r); 479 } 480 481 xxxx(buf, n) 482 char *buf; 483 short n; 484 { 485 short i; 486 unsigned char c; 487 488 for (i = 0; i < n; i++) { 489 490 /* It does not matter if accuracy is lost during this assignment */ 491 c = (unsigned char) xxx(0); 492 493 buf[i] ^= c; 494 } 495 } 496 497 long 498 xxx(st) 499 boolean st; 500 { 501 static long f, s; 502 long r; 503 504 if (st) { 505 f = 37; 506 s = 7; 507 return(0L); 508 } 509 r = ((f * s) + 9337) % 8887; 510 f = s; 511 s = r; 512 return(r); 513 } 514 515 nickize(buf, score, n_name) 516 char *buf, *score, *n_name; 517 { 518 short i = 15, j; 519 520 if (!n_name[0]) { 521 (void) strcpy(buf, score); 522 } else { 523 (void) strncpy(buf, score, 16); 524 525 while (score[i] != ':') { 526 i++; 527 } 528 529 (void) strcpy(buf+15, n_name); 530 j = strlen(buf); 531 532 while (score[i]) { 533 buf[j++] = score[i++]; 534 } 535 buf[j] = 0; 536 buf[79] = 0; 537 } 538 } 539 540 center(row, buf) 541 short row; 542 char *buf; 543 { 544 short margin; 545 546 margin = ((DCOLS - strlen(buf)) / 2); 547 mvaddstr(row, margin, buf); 548 } 549 550 sf_error() 551 { 552 md_lock(0); 553 message("", 1); 554 clean_up("sorry, score file is out of order"); 555 } 556