Annotation of early-roguelike/rogue5/rip.c, Revision 1.1.1.1
1.1 rubenllo 1: /*
2: * File for the fun ends
3: * Death or a total win
4: *
5: * @(#)rip.c 4.57 (Berkeley) 02/05/99
6: *
7: * Rogue: Exploring the Dungeons of Doom
8: * Copyright (C) 1980-1983, 1985, 1999 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 <stdlib.h>
15: #include <string.h>
16: #include <time.h>
17: #include <signal.h>
18: #include <sys/types.h>
19: #include <ctype.h>
20: #include <fcntl.h>
21: #include <curses.h>
22: #include "rogue.h"
23: #include "score.h"
24:
25: static char *rip[] = {
26: " __________\n",
27: " / \\\n",
28: " / REST \\\n",
29: " / IN \\\n",
30: " / PEACE \\\n",
31: " / \\\n",
32: " | |\n",
33: " | |\n",
34: " | killed by a |\n",
35: " | |\n",
36: " | 1980 |\n",
37: " *| * * * | *\n",
38: " ________)/\\\\_//(\\/(/\\)/\\//\\/|_)_______\n",
39: 0
40: };
41:
42: /*
43: * score:
44: * Figure score and post it.
45: */
46: /* VARARGS2 */
47:
48: void
49: score(int amount, int flags, int monst)
50: {
51: SCORE *scp;
52: int i;
53: SCORE *sc2;
54: SCORE *top_ten, *endp;
55: # ifdef MASTER
56: int prflags = 0;
57: # endif
58: void (*fp)(int);
59: uid_t uid;
60: char *reason[] = {
61: "killed",
62: "quit",
63: "A total winner",
64: "killed with Amulet"
65: };
66:
67: start_score();
68:
69: if (flags >= 0
70: #ifdef MASTER
71: || wizard
72: #endif
73: )
74: {
75: mvaddstr(LINES - 1, 0 , "[Press return to continue]");
76: refresh();
77: wgetnstr(stdscr,prbuf,80);
78: endwin();
79: printf("\n");
80: resetltchars();
81: /*
82: * free up space to "guarantee" there is space for the top_ten
83: */
84: delwin(stdscr);
85: delwin(curscr);
86: if (hw != NULL)
87: delwin(hw);
88: }
89:
90: top_ten = malloc(numscores * sizeof (SCORE));
91:
92: if (top_ten == NULL)
93: return;
94:
95: endp = &top_ten[numscores];
96: for (scp = top_ten; scp < endp; scp++)
97: {
98: scp->sc_score = 0;
99: for (i = 0; i < MAXSTR; i++)
100: scp->sc_name[i] = (char) rnd(255);
101: scp->sc_flags = RN;
102: scp->sc_level = RN;
103: scp->sc_monster = RN;
104: scp->sc_uid = RN;
105: }
106:
107: signal(SIGINT, SIG_DFL);
108:
109: #ifdef MASTER
110: if (wizard)
111: if (strcmp(prbuf, "names") == 0)
112: prflags = 1;
113: else if (strcmp(prbuf, "edit") == 0)
114: prflags = 2;
115: #endif
116: rd_score(top_ten);
117: /*
118: * Insert her in list if need be
119: */
120: sc2 = NULL;
121: if (!noscore)
122: {
123: uid = md_getuid();
124: for (scp = top_ten; scp < endp; scp++)
125: if (amount > scp->sc_score)
126: break;
127: else if (!allscore && /* only one score per nowin uid */
128: flags != 2 && scp->sc_uid == uid && scp->sc_flags != 2)
129: scp = endp;
130: if (scp < endp)
131: {
132: if (flags != 2 && !allscore)
133: {
134: for (sc2 = scp; sc2 < endp; sc2++)
135: {
136: if (sc2->sc_uid == uid && sc2->sc_flags != 2)
137: break;
138: }
139: if (sc2 >= endp)
140: sc2 = endp - 1;
141: }
142: else
143: sc2 = endp - 1;
144: while (sc2 > scp)
145: {
146: *sc2 = sc2[-1];
147: sc2--;
148: }
149: scp->sc_score = amount;
150: strncpy(scp->sc_name, whoami, MAXSTR);
151: scp->sc_flags = flags;
152: if (flags == 2)
153: scp->sc_level = max_level;
154: else
155: scp->sc_level = level;
156: scp->sc_monster = monst;
157: scp->sc_uid = uid;
158: sc2 = scp;
159: }
160: }
161: /*
162: * Print the list
163: */
164: if (flags != -1)
165: putchar('\n');
166: printf("Top %s %s:\n", Numname, allscore ? "Scores" : "Rogueists");
167: printf(" Score Name\n");
168: for (scp = top_ten; scp < endp; scp++)
169: {
170: if (scp->sc_score) {
171: if (sc2 == scp)
172: md_raw_standout();
173: printf("%2d %5d %s: %s on level %d", (int) (scp - top_ten + 1),
174: scp->sc_score, scp->sc_name, reason[scp->sc_flags],
175: scp->sc_level);
176: if (scp->sc_flags == 0 || scp->sc_flags == 3)
177: printf(" by %s", killname(scp->sc_monster, TRUE));
178: #ifdef MASTER
179: if (prflags == 1)
180: {
181: printf(" (%s)", md_getrealname(scp->sc_uid));
182: }
183: else if (prflags == 2)
184: {
185: fflush(stdout);
186: (void) fgets(prbuf,10,stdin);
187: if (prbuf[0] == 'd')
188: {
189: for (sc2 = scp; sc2 < endp - 1; sc2++)
190: *sc2 = *(sc2 + 1);
191: sc2 = endp - 1;
192: sc2->sc_score = 0;
193: for (i = 0; i < MAXSTR; i++)
194: sc2->sc_name[i] = (char) rnd(255);
195: sc2->sc_flags = RN;
196: sc2->sc_level = RN;
197: sc2->sc_monster = RN;
198: scp--;
199: }
200: }
201: else
202: #endif /* MASTER */
203: printf(".");
204: if (sc2 == scp)
205: md_raw_standend();
206: putchar('\n');
207: }
208: else
209: break;
210: }
211: /*
212: * Update the list file
213: */
214: if (sc2 != NULL)
215: {
216: if (lock_sc())
217: {
218: fp = signal(SIGINT, SIG_IGN);
219: wr_score(top_ten);
220: unlock_sc();
221: signal(SIGINT, fp);
222: }
223: }
224: }
225:
226: void writelog(int amount, int flags, int monst)
227: {
228: #ifdef LOGFILE
229: char logmessage[220], ltemp[80];
230:
231: if (logfi == NULL)
232: return;
233: #ifdef MASTER
234: if (wizard)
235: {
236: fclose(logfi);
237: return;
238: }
239: #endif
240: sprintf(logmessage, "%ld %d %.80s %d ", time(NULL), amount, whoami,
241: pstats.s_lvl);
242: if (flags == 0) /* dead */
243: {
244: sprintf(ltemp, "killed by %s on level %d\n", killname(monst, TRUE),
245: level);
246: strcat(logmessage, ltemp);
247: }
248: else if (flags == 1) /* quit */
249: {
250: if (amulet)
251: sprintf(ltemp, "quit on level %d [max %d] with the Amulet\n",
252: level, max_level);
253: else
254: sprintf(ltemp, "quit on level %d\n", level);
255: strcat(logmessage, ltemp);
256: }
257: else if (flags == 2) /* won */
258: {
259: sprintf(ltemp, "escaped with the Amulet [deepest level: %d]\n",
260: max_level);
261: strcat(logmessage, ltemp);
262: }
263: else if (flags == 3) /* killed with Amulet */
264: {
265: strcat(logmessage, "killed by ");
266: strcat(logmessage, killname(monst, TRUE));
267: sprintf(ltemp, " on level %d [max %d] with the Amulet\n",
268: level, max_level);
269: strcat(logmessage, ltemp);
270: }
271: else
272: {
273: fclose(logfi);
274: return;
275: }
276: fprintf(logfi, "%s", logmessage);
277: fclose(logfi);
278: #endif
279: return;
280: }
281:
282: /*
283: * death:
284: * Do something really fun when he dies
285: */
286:
287: void
288: death(int monst)
289: {
290: char **dp;
291: const char *killer;
292: struct tm *lt;
293: time_t date;
294:
295: signal(SIGINT, SIG_IGN);
296: purse -= purse / 10;
297: signal(SIGINT, leave);
298: clear();
299: killer = killname(monst, FALSE);
300: if (!tombstone)
301: {
302: mvprintw(LINES - 2, 0, "Killed by ");
303: killer = killname(monst, FALSE);
304: if (monst != 's' && monst != 'h')
305: printw("a%s ", vowelstr(killer));
306: printw("%s with %d gold", killer, purse);
307: }
308: else
309: {
310: time(&date);
311: lt = localtime(&date);
312: move(8, 0);
313: dp = rip;
314: while (*dp)
315: addstr(*dp++);
316: mvaddstr(17, center(killer), killer);
317: if (monst == 's' || monst == 'h')
318: mvaddch(16, 32, ' ');
319: else
320: mvaddstr(16, 33, vowelstr(killer));
321: mvaddstr(14, center(whoami), whoami);
322: sprintf(prbuf, "%d Au", purse);
323: move(15, center(prbuf));
324: addstr(prbuf);
325: sprintf(prbuf, "%4d", 1900+lt->tm_year);
326: mvaddstr(18, 26, prbuf);
327: }
328: move(LINES - 1, 0);
329: refresh();
330: writelog(purse, amulet ? 3 : 0, monst);
331: score(purse, amulet ? 3 : 0, monst);
332: /* Make sure the output gets through. */
333: printf("[Press return to exit]\n");
334: fflush(NULL);
335: getchar();
336: my_exit(0);
337: }
338:
339: /*
340: * center:
341: * Return the index to center the given string
342: */
343: int
344: center(const char *str)
345: {
346: return 28 - (((int)strlen(str) + 1) / 2);
347: }
348:
349: /*
350: * total_winner:
351: * Code for a winner
352: */
353:
354: void
355: total_winner(void)
356: {
357: THING *obj;
358: struct obj_info *op;
359: int worth = 0;
360: int oldpurse;
361:
362: clear();
363: standout();
364: addstr(" \n");
365: addstr(" @ @ @ @ @ @@@ @ @ \n");
366: addstr(" @ @ @@ @@ @ @ @ @ \n");
367: addstr(" @ @ @@@ @ @ @ @ @ @@@ @@@@ @@@ @ @@@ @ \n");
368: addstr(" @@@@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ \n");
369: addstr(" @ @ @ @ @ @ @ @@@@ @ @ @@@@@ @ @ @ \n");
370: addstr(" @ @ @ @ @ @@ @ @ @ @ @ @ @ @ @ @ \n");
371: addstr(" @@@ @@@ @@ @ @ @ @@@@ @@@@ @@@ @@@ @@ @ \n");
372: addstr(" \n");
373: addstr(" Congratulations, you have made it to the light of day! \n");
374: standend();
375: addstr("\nYou have joined the elite ranks of those who have escaped the\n");
376: addstr("Dungeons of Doom alive. You journey home and sell all your loot at\n");
377: addstr("a great profit and are admitted to the Fighters' Guild.\n");
378: mvaddstr(LINES - 1, 0, "--Press space to continue--");
379: refresh();
380: wait_for(stdscr, ' ');
381: clear();
382: mvaddstr(0, 0, " Worth Item\n");
383: oldpurse = purse;
384: for (obj = pack; obj != NULL; obj = next(obj))
385: {
386: switch (obj->o_type)
387: {
388: case FOOD:
389: worth = 2 * obj->o_count;
390: when WEAPON:
391: worth = weap_info[obj->o_which].oi_worth;
392: worth *= 3 * (obj->o_hplus + obj->o_dplus) + obj->o_count;
393: obj->o_flags |= ISKNOW;
394: when ARMOR:
395: worth = arm_info[obj->o_which].oi_worth;
396: worth += (9 - obj->o_arm) * 100;
397: worth += (10 * (a_class[obj->o_which] - obj->o_arm));
398: obj->o_flags |= ISKNOW;
399: when SCROLL:
400: worth = scr_info[obj->o_which].oi_worth;
401: worth *= obj->o_count;
402: op = &scr_info[obj->o_which];
403: if (!op->oi_know)
404: worth /= 2;
405: op->oi_know = TRUE;
406: when POTION:
407: worth = pot_info[obj->o_which].oi_worth;
408: worth *= obj->o_count;
409: op = &pot_info[obj->o_which];
410: if (!op->oi_know)
411: worth /= 2;
412: op->oi_know = TRUE;
413: when RING:
414: op = &ring_info[obj->o_which];
415: worth = op->oi_worth;
416: if (obj->o_which == R_ADDSTR || obj->o_which == R_ADDDAM ||
417: obj->o_which == R_PROTECT || obj->o_which == R_ADDHIT)
418: {
419: if (obj->o_arm > 0)
420: worth += obj->o_arm * 100;
421: else
422: worth = 10;
423: }
424: if (!(obj->o_flags & ISKNOW))
425: worth /= 2;
426: obj->o_flags |= ISKNOW;
427: op->oi_know = TRUE;
428: when STICK:
429: op = &ws_info[obj->o_which];
430: worth = op->oi_worth;
431: worth += 20 * obj->o_charges;
432: if (!(obj->o_flags & ISKNOW))
433: worth /= 2;
434: obj->o_flags |= ISKNOW;
435: op->oi_know = TRUE;
436: when AMULET:
437: worth = 1000;
438: }
439: if (worth < 0)
440: worth = 0;
441: printw("%c) %5d %s\n", obj->o_packch, worth, inv_name(obj, FALSE));
442: purse += worth;
443: }
444: printw(" %5d Gold Pieces ", oldpurse);
445: refresh();
446: writelog(purse, 2, ' ');
447: score(purse, 2, ' ');
448: printf("[Press return to exit]\n");
449: fflush(NULL);
450: getchar();
451: my_exit(0);
452: }
453:
454: /*
455: * killname:
456: * Convert a code to a monster name
457: */
458: const char *
459: killname(int monst, int doart)
460: {
461: struct h_list *hp;
462: const char *sp;
463: int article;
464: struct h_list nlist[] = {
465: {'a', "arrow", TRUE},
466: {'b', "bolt", TRUE},
467: {'d', "dart", TRUE},
468: {'h', "hypothermia", FALSE},
469: {'s', "starvation", FALSE},
470: {'\0'}
471: };
472:
473: if (isupper(monst))
474: {
475: sp = monsters[monst-'A'].m_name;
476: article = TRUE;
477: }
478: else
479: {
480: sp = "Wally the Wonder Badger";
481: article = FALSE;
482: for (hp = nlist; hp->h_ch; hp++)
483: if (hp->h_ch == monst)
484: {
485: sp = hp->h_desc;
486: article = hp->h_print;
487: break;
488: }
489: }
490: if (doart && article)
491: sprintf(prbuf, "a%s ", vowelstr(sp));
492: else
493: prbuf[0] = '\0';
494: strcat(prbuf, sp);
495: return prbuf;
496: }
497:
498: /*
499: * death_monst:
500: * Return a monster appropriate for a random death.
501: */
502: int
503: death_monst(void)
504: {
505: int poss[] =
506: {
507: 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
508: 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
509: 'Y', 'Z', 'a', 'b', 'h', 'd', 's',
510: ' ' /* This is provided to generate the "Wally the Wonder Badger"
511: message for killer */
512: };
513:
514: return poss[rnd(sizeof poss / sizeof (int))];
515: }
CVSweb