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
killed_by(monster,other)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
win()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
quit(from_intrpt)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
put_scores(monster,other)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
insert_score(scores,n_names,n_name,rank,n,monster,other)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
is_vowel(ch)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
sell_pack()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
get_value(obj)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
id_all()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
name_cmp(s1,s2)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
xxxx(buf,n)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
xxx(st)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
nickize(buf,score,n_name)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
center(row,buf)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
sf_error()551 sf_error()
552 {
553 md_lock(0);
554 message("", 1);
555 clean_up("sorry, score file is out of order");
556 }
557