Fix integer-size bug in score file parsing / printing.
[rogue-pphs.git] / rip.c
1 /*
2 * File for the fun ends
3 * Death or a total win
4 *
5 * @(#)rip.c 3.13 (Berkeley) 6/16/81
6 *
7 * Rogue: Exploring the Dungeons of Doom
8 * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
9 * All rights reserved.
10 *
11 * See the file LICENSE.TXT for full copyright and licensing information.
12 */
13
14 #include "curses.h"
15 #include <time.h>
16 #include <signal.h>
17 #include <ctype.h>
18 #include <sys/types.h>
19 #include <fcntl.h>
20 #include <string.h>
21 #include "machdep.h"
22 #include "rogue.h"
23
24 static char *rip[] = {
25 " __________",
26 " / \\",
27 " / REST \\",
28 " / IN \\",
29 " / PEACE \\",
30 " / \\",
31 " | |",
32 " | |",
33 " | killed by a |",
34 " | |",
35 " | 1980 |",
36 " *| * * * | *",
37 " ________)/\\\\_//(\\/(/\\)/\\//\\/|_)_______",
38 0
39 };
40
41 char *killname();
42
43 /*
44 * death:
45 * Do something really fun when he dies
46 */
47
48 death(monst)
49 register char monst;
50 {
51 register char **dp = rip, *killer;
52 register struct tm *lt;
53 time_t date;
54 char buf[80];
55
56 time(&date);
57 lt = localtime(&date);
58 clear();
59 move(8, 0);
60 while (*dp)
61 printw("%s\n", *dp++);
62 mvaddstr(14, 28-(((int)strlen(whoami)+1)/2), whoami);
63 purse -= purse/10;
64 sprintf(buf, "%d Au", purse);
65 mvaddstr(15, 28-(((int)strlen(buf)+1)/2), buf);
66 killer = killname(monst);
67 mvaddstr(17, 28-(((int)strlen(killer)+1)/2), killer);
68 mvaddstr(16, 33, vowelstr(killer));
69 sprintf(prbuf, "%4d", 1900+lt->tm_year);
70 mvaddstr(18, 26, prbuf);
71 move(LINES-1, 0);
72 draw(stdscr);
73 score(purse, 0, monst);
74 exit(0);
75 }
76
77 /*
78 * score -- figure score and post it.
79 */
80
81 /* VARARGS2 */
82 score(amount, flags, monst)
83 char monst;
84 {
85 static struct sc_ent {
86 int sc_score;
87 char sc_name[80];
88 int sc_flags;
89 int sc_level;
90 char sc_login[8];
91 char sc_monster;
92 } top_ten[10];
93 register struct sc_ent *scp;
94 register int i;
95 register struct sc_ent *sc2;
96 register FILE *outf;
97 register char *killer;
98 register int prflags = 0;
99 register int fd;
100 static char *reason[] = {
101 "killed",
102 "quit",
103 "A total winner",
104 };
105 char scoreline[100];
106 char score_file[PATH_MAX];
107 int rogue_ver = 0, scorefile_ver = 0;
108
109 /*
110 * Open file and read list
111 */
112
113 /* Get default score file */
114 strcpy(score_file, md_getroguedir());
115
116 if (*score_file)
117 strcat(score_file,"\\");
118
119 strcat(score_file, "rogue36.scr");
120
121 if ((fd = open(score_file, O_RDWR | O_CREAT, 0666 )) < 0)
122 return;
123
124 outf = (FILE *) fdopen(fd, "w");
125
126 for (scp = top_ten; scp <= &top_ten[9]; scp++)
127 {
128 scp->sc_score = 0;
129 for (i = 0; i < 80; i++)
130 scp->sc_name[i] = rnd(255);
131 scp->sc_flags = RN;
132 scp->sc_level = RN;
133 scp->sc_monster = RN;
134 scp->sc_login[0] = '\0';
135 }
136
137 signal(SIGINT, SIG_DFL);
138 if ((flags != -1) && (flags != 1))
139 {
140 mvaddstr(LINES-1, 0, "[Press return to continue]");
141 draw(stdscr);
142 prbuf[0] = 0;
143 get_str(prbuf, stdscr);
144 endwin();
145 }
146 if (wizard)
147 if (strcmp(prbuf, "names") == 0)
148 prflags = 1;
149 else if (strcmp(prbuf, "edit") == 0)
150 prflags = 2;
151
152 encread((char *) scoreline, 100, fd);
153 sscanf(scoreline, "R%d %d\n", &rogue_ver, &scorefile_ver);
154
155 if ((rogue_ver == 36) && (scorefile_ver == 2))
156 for(i = 0; i < 10; i++)
157 {
158 int monster;
159 encread((char *) &top_ten[i].sc_name, 80, fd);
160 encread((char *) &top_ten[i].sc_login, 8, fd);
161 encread((char *) scoreline, 100, fd);
162 sscanf(scoreline, " %d %d %d %d \n",
163 &top_ten[i].sc_score, &top_ten[i].sc_flags,
164 &top_ten[i].sc_level, &monster);
165 top_ten[i].sc_monster = monster;
166 }
167
168 /*
169 * Insert her in list if need be
170 */
171 if (!waswizard)
172 {
173 for (scp = top_ten; scp <= &top_ten[9]; scp++)
174 if (amount > scp->sc_score)
175 break;
176 if (scp <= &top_ten[9])
177 {
178 for (sc2 = &top_ten[9]; sc2 > scp; sc2--)
179 *sc2 = *(sc2-1);
180 scp->sc_score = amount;
181 strcpy(scp->sc_name, whoami);
182 scp->sc_flags = flags;
183 if (flags == 2)
184 scp->sc_level = max_level;
185 else
186 scp->sc_level = level;
187 scp->sc_monster = monst;
188 strncpy(scp->sc_login, md_getusername(), 8);
189 }
190 }
191 /*
192 * Print the list
193 */
194 if (flags != -1)
195 printf("\n\n\n");
196 printf("Top Ten Adventurers:\nRank\tScore\tName\n");
197 for (scp = top_ten; scp <= &top_ten[9]; scp++) {
198 if (scp->sc_score) {
199 printf("%ld\t%d\t%s: %s on level %d", scp - top_ten + 1,
200 scp->sc_score, scp->sc_name, reason[scp->sc_flags],
201 scp->sc_level);
202 if (scp->sc_flags == 0) {
203 printf(" by a");
204 killer = killname(scp->sc_monster);
205 if (*killer == 'a' || *killer == 'e' || *killer == 'i' ||
206 *killer == 'o' || *killer == 'u')
207 putchar('n');
208 printf(" %s", killer);
209 }
210 if (prflags == 1)
211 {
212 printf(" (%s)", scp->sc_login);
213 putchar('\n');
214 }
215 else if (prflags == 2)
216 {
217 fflush(stdout);
218 fgets(prbuf,80,stdin);
219 if (prbuf[0] == 'd')
220 {
221 for (sc2 = scp; sc2 < &top_ten[9]; sc2++)
222 *sc2 = *(sc2 + 1);
223 top_ten[9].sc_score = 0;
224 for (i = 0; i < 80; i++)
225 top_ten[9].sc_name[i] = rnd(255);
226 top_ten[9].sc_flags = RN;
227 top_ten[9].sc_level = RN;
228 top_ten[9].sc_monster = RN;
229 scp--;
230 }
231 }
232 else
233 printf(".\n");
234 }
235 }
236 fseek(outf, 0L, 0);
237 /*
238 * Update the list file
239 */
240 strcpy(scoreline, "R36 2\n");
241 encwrite(scoreline, 100, outf);
242 for(i = 0; i < 10; i++)
243 {
244 encwrite((char *) &top_ten[i].sc_name, 80, outf);
245 encwrite((char *) &top_ten[i].sc_login, 8, outf);
246 sprintf(scoreline, " %d %d %d %d \n",
247 top_ten[i].sc_score, top_ten[i].sc_flags,
248 top_ten[i].sc_level, top_ten[i].sc_monster);
249 encwrite((char *) scoreline, 100, outf);
250 }
251 fclose(outf);
252 }
253
254 total_winner()
255 {
256 register struct linked_list *item;
257 register struct object *obj;
258 register int worth;
259 register char c;
260 register int oldpurse;
261
262 clear();
263 standout();
264 addstr(" \n");
265 addstr(" @ @ @ @ @ @@@ @ @ \n");
266 addstr(" @ @ @@ @@ @ @ @ @ \n");
267 addstr(" @ @ @@@ @ @ @ @ @ @@@ @@@@ @@@ @ @@@ @ \n");
268 addstr(" @@@@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ \n");
269 addstr(" @ @ @ @ @ @ @ @@@@ @ @ @@@@@ @ @ @ \n");
270 addstr(" @ @ @ @ @ @@ @ @ @ @ @ @ @ @ @ @ \n");
271 addstr(" @@@ @@@ @@ @ @ @ @@@@ @@@@ @@@ @@@ @@ @ \n");
272 addstr(" \n");
273 addstr(" Congratulations, you have made it to the light of day! \n");
274 standend();
275 addstr("\nYou have joined the elite ranks of those who have escaped the\n");
276 addstr("Dungeons of Doom alive. You journey home and sell all your loot at\n");
277 addstr("a great profit and are admitted to the fighters guild.\n");
278 mvaddstr(LINES - 1, 0, "--Press space to continue--");
279 refresh();
280 wait_for(' ');
281 clear();
282 mvaddstr(0, 0, " Worth Item");
283 oldpurse = purse;
284 for (c = 'a', item = pack; item != NULL; c++, item = next(item))
285 {
286 obj = (struct object *) ldata(item);
287 switch (obj->o_type)
288 {
289 case FOOD:
290 worth = 2 * obj->o_count;
291 when WEAPON:
292 switch (obj->o_which)
293 {
294 case MACE: worth = 8;
295 when SWORD: worth = 15;
296 when BOW: worth = 75;
297 when ARROW: worth = 1;
298 when DAGGER: worth = 2;
299 when ROCK: worth = 1;
300 when TWOSWORD: worth = 30;
301 when SLING: worth = 1;
302 when DART: worth = 1;
303 when CROSSBOW: worth = 15;
304 when BOLT: worth = 1;
305 when SPEAR: worth = 2;
306 otherwise: worth = 0;
307 }
308 worth *= (1 + (10 * obj->o_hplus + 10 * obj->o_dplus));
309 worth *= obj->o_count;
310 obj->o_flags |= ISKNOW;
311 when ARMOR:
312 switch (obj->o_which)
313 {
314 case LEATHER: worth = 5;
315 when RING_MAIL: worth = 30;
316 when STUDDED_LEATHER: worth = 15;
317 when SCALE_MAIL: worth = 3;
318 when CHAIN_MAIL: worth = 75;
319 when SPLINT_MAIL: worth = 80;
320 when BANDED_MAIL: worth = 90;
321 when PLATE_MAIL: worth = 400;
322 otherwise: worth = 0;
323 }
324 worth *= (1 + (10 * (a_class[obj->o_which] - obj->o_ac)));
325 obj->o_flags |= ISKNOW;
326 when SCROLL:
327 s_know[obj->o_which] = TRUE;
328 worth = s_magic[obj->o_which].mi_worth;
329 worth *= obj->o_count;
330 when POTION:
331 p_know[obj->o_which] = TRUE;
332 worth = p_magic[obj->o_which].mi_worth;
333 worth *= obj->o_count;
334 when RING:
335 obj->o_flags |= ISKNOW;
336 r_know[obj->o_which] = TRUE;
337 worth = r_magic[obj->o_which].mi_worth;
338 if (obj->o_which == R_ADDSTR || obj->o_which == R_ADDDAM ||
339 obj->o_which == R_PROTECT || obj->o_which == R_ADDHIT)
340 if (obj->o_ac > 0)
341 worth += obj->o_ac * 20;
342 else
343 worth = 50;
344 when STICK:
345 obj->o_flags |= ISKNOW;
346 ws_know[obj->o_which] = TRUE;
347 worth = ws_magic[obj->o_which].mi_worth;
348 worth += 20 * obj->o_charges;
349 when AMULET:
350 worth = 1000;
351 }
352 mvprintw(c - 'a' + 1, 0, "%c) %5d %s", c, worth, inv_name(obj, FALSE));
353 purse += worth;
354 }
355 mvprintw(c - 'a' + 1, 0," %5d Gold Peices ", oldpurse);
356 refresh();
357 score(purse, 2, 0);
358 exit(0);
359 }
360
361 char *
362 killname(monst)
363 register char monst;
364 {
365 if (isupper(monst))
366 return monsters[monst-'A'].m_name;
367 else
368 switch (monst)
369 {
370 case 'a':
371 return "arrow";
372 case 'd':
373 return "dart";
374 case 'b':
375 return "bolt";
376 }
377 return("");
378 }