Annotation of early-roguelike/urogue/rip.c, Revision 1.1.1.1
1.1 rubenllo 1: /*
2: rip.c - File for the fun ends Death or a total win
3:
4: UltraRogue: The Ultimate Adventure in the Dungeons of Doom
5: Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
6: All rights reserved.
7:
8: Based on "Advanced Rogue"
9: Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
10: All rights reserved.
11:
12: Based on "Rogue: Exploring the Dungeons of Doom"
13: Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
14: All rights reserved.
15:
16: See the file LICENSE.TXT for full copyright and licensing information.
17: */
18:
19: #include <string.h>
20: #include <stdlib.h>
21: #include <ctype.h>
22: #include <time.h>
23: #include "rogue.h"
24:
25: static struct sc_ent
26: {
27: int sc_lvl;
28: long sc_score;
29: char sc_name[76];
30: long sc_gold;
31: int sc_flags;
32: int sc_level;
33: int sc_artifacts;
34: int sc_monster;
35: } top_ten[10];
36:
37:
38: static const char *rip[] =
39: {
40: " __________",
41: " / \\",
42: " / REST \\",
43: " / IN \\",
44: " / PEACE \\",
45: " / \\",
46: " | |",
47: " | |",
48: " | killed by |",
49: " | |",
50: " | 1993 |",
51: " *| * * * | *",
52: " ________)/\\\\_//(\\/(/\\)/\\//\\/|_)_______",
53: 0
54: };
55:
56: void writelog(long amount, int lvl, int flags, int monst);
57:
58: /*
59: death()
60: Do something really fun when he dies
61: */
62:
63: void
64: death(int monst)
65: {
66: char **dp = (char **) rip, *killer;
67: struct tm *lt;
68: time_t date;
69: char buf[80];
70: int c;
71:
72: if (is_wearing(R_RESURRECT) || rnd(wizard ? 3 : 67) == 0)
73: {
74: int die = TRUE;
75:
76: if (resurrect-- == 0)
77: msg("You've run out of lives.");
78: else if (!save_resurrect(ring_value(R_RESURRECT)))
79: msg("Your attempt to return from the grave fails.");
80: else
81: {
82: struct linked_list *item;
83: struct linked_list *next_item;
84: struct object *obj;
85: int rm, flags;
86: coord pos;
87:
88: die = FALSE;
89: msg("You feel a sudden warmth and then nothingness.");
90: teleport();
91:
92: if (ring_value(R_RESURRECT) > 1 && rnd(10))
93: {
94: pstats.s_hpt = 2 * pstats.s_const;
95: pstats.s_const = max(pstats.s_const - 1, 3);
96: }
97: else
98: {
99: for (item = pack; item != NULL; item = next_item)
100: {
101: obj = OBJPTR(item);
102:
103: if (obj->o_flags & ISOWNED || obj->o_flags & ISPROT)
104: {
105: next_item = next(item);
106: continue;
107: }
108:
109: flags = obj->o_flags;
110: obj->o_flags &= ~ISCURSED;
111: dropcheck(obj);
112: obj->o_flags = flags;
113: next_item = next(item);
114: rem_pack(obj);
115:
116: if (obj->o_type == ARTIFACT)
117: has_artifact &= ~(1 << obj->o_which);
118:
119: do
120: {
121: rm = rnd_room();
122: rnd_pos(&rooms[rm], &pos);
123: }
124: while(winat(pos.y, pos.x) != FLOOR);
125:
126: obj->o_pos = pos;
127: add_obj(item, obj->o_pos.y, obj->o_pos.x);
128: }
129:
130: pstats.s_hpt = pstats.s_const;
131: pstats.s_const = max(pstats.s_const - roll(2, 2), 3);
132: }
133:
134: chg_str(roll(1, 4), TRUE, FALSE);
135: pstats.s_lvl = max(pstats.s_lvl, 1);
136: no_command += 2 + rnd(4);
137:
138: if (on(player, ISHUH))
139: lengthen_fuse(FUSE_UNCONFUSE, rnd(8) + HUHDURATION);
140: else
141: light_fuse(FUSE_UNCONFUSE, 0, rnd(8) + HUHDURATION, AFTER);
142:
143: turn_on(player, ISHUH);
144: light(&hero);
145: }
146:
147: if (die)
148: {
149: wmove(cw, mpos, 0);
150: waddstr(cw, morestr);
151: wrefresh(cw);
152: wait_for(' ');
153: }
154: else
155: return;
156: }
157:
158: time(&date);
159: lt = localtime(&date);
160: clear();
161: wclear(cw);
162: move(8, 0);
163:
164: while (*dp)
165: printw("%s\n", *dp++);
166:
167: mvaddstr(14, 28 - ((int)(strlen(whoami) + 1) / 2), whoami);
168: sprintf(buf, "%d+%ld Points", pstats.s_lvl, pstats.s_exp);
169: mvaddstr(15, 28 - ((int)(strlen(buf) + 1) / 2), buf);
170: killer = killname(monst,buf);
171: mvaddstr(17, 28 - ((int)(strlen(killer) + 1) / 2), killer);
172: mvaddstr(18, 26, (sprintf(prbuf, "%4d", 1900+lt->tm_year), prbuf));
173: move(LINES - 1, 0);
174:
175: mvaddstr(LINES - 1, 0, retstr);
176:
177: while ((c = readcharw(stdscr)) != '\n' && c != '\r')
178: continue;
179: idenpack();
180: wrefresh(cw);
181: refresh();
182:
183: score(pstats.s_exp, pstats.s_lvl, KILLED, monst);
184: byebye();
185: }
186:
187: /*
188: score()
189: figure score and post it.
190: */
191:
192: void
193: score(long amount, int lvl, int flags, int monst) /*ARGSUSED*/
194: {
195: struct sc_ent *scp=NULL, *sc2=NULL;
196: int i;
197: char *killer;
198: char buf[1024];
199:
200: static const char *reason[] =
201: {
202: "killed",
203: "quit",
204: "a winner",
205: "a total winner"
206: };
207:
208: char *packend;
209:
210: if (flags != SCOREIT)
211: writelog(amount, lvl, flags, monst);
212:
213: if (flags != WINNER && flags != TOTAL && flags != SCOREIT)
214: {
215: if (flags == CHICKEN)
216: packend = "when you quit";
217: else
218: packend = "at your untimely demise";
219:
220: noecho();
221: nl();
222: refresh();
223: showpack(packend);
224: }
225:
226: /* Open file and read list */
227:
228: if (fd_score == NULL)
229: {
230: printf("No score file opened\n");
231: return;
232: }
233:
234: for (scp = top_ten; scp < &top_ten[10]; scp++)
235: {
236: scp->sc_lvl = 0L;
237: scp->sc_score = 0L;
238:
239: for (i = 0; i < 76; i++)
240: scp->sc_name[i] = ucrnd(255);
241:
242: scp->sc_gold = 0L;
243: scp->sc_flags = rnd(10);
244: scp->sc_level = rnd(10);
245: scp->sc_monster = srnd(10);
246: scp->sc_artifacts = 0;
247: }
248:
249: if (flags != SCOREIT)
250: {
251: mvaddstr(LINES - 1, 0, retstr);
252: refresh();
253: fflush(stdout);
254: wait_for('\n');
255: }
256:
257: fseek(fd_score, 0L, SEEK_SET);
258: fread(top_ten, sizeof(top_ten), 1, fd_score);
259:
260: /* Insert player in list if need be */
261:
262: if (!waswizard)
263: {
264: for (scp = top_ten; scp < &top_ten[10]; scp++)
265: {
266: if (lvl > scp->sc_lvl)
267: break;
268:
269: if (lvl == scp->sc_lvl && amount > scp->sc_score)
270: break;
271: }
272:
273: if (scp < &top_ten[10])
274: {
275: if (flags == WINNER)
276: sc2 = &top_ten[9]; /* LAST WINNER ALWAYS MAKES IT */
277:
278: while (sc2 > scp)
279: {
280: *sc2 = sc2[-1];
281: sc2--;
282: }
283:
284: scp->sc_lvl = lvl;
285: scp->sc_gold = purse;
286: scp->sc_score = amount;
287: strcpy(scp->sc_name, whoami);
288: strcat(scp->sc_name,", ");
289: strcat(scp->sc_name, which_class(player.t_ctype));
290: scp->sc_flags = flags;
291:
292: if (flags == WINNER)
293: scp->sc_level = max_level;
294: else
295: scp->sc_level = level;
296:
297: scp->sc_monster = monst;
298: scp->sc_artifacts = has_artifact;
299:
300: sc2 = scp;
301: }
302: }
303:
304: if (flags != SCOREIT)
305: {
306: clear();
307: refresh();
308: endwin();
309: }
310:
311: /* Print the list */
312:
313: printf("\nTop Ten Adventurers:\n%4s %15s %10s %s\n",
314: "Rank", "Score", "Gold", "Name");
315:
316: for (scp = top_ten; scp < &top_ten[10]; scp++)
317: {
318: if (scp->sc_score)
319: {
320: char lev[20];
321:
322: sprintf(lev, "%ld+%ld", scp->sc_lvl, scp->sc_score);
323: printf("%4d %15s %10ld %s:", scp - top_ten + 1,
324: lev,
325: scp->sc_gold,
326: scp->sc_name);
327:
328: if (scp->sc_artifacts)
329: {
330: char thangs[80];
331: int n;
332: int first = TRUE;
333:
334: thangs[0] = '\0';
335:
336: for (n = 0; n <= maxartifact; n++)
337: {
338: if (scp->sc_artifacts & (1 << n))
339: {
340: if (strlen(thangs))
341: strcat(thangs, ", ");
342:
343: if (first)
344: {
345: strcat(thangs, "retrieved ");
346: first = FALSE;
347: }
348:
349: if (45 - strlen(thangs) < strlen(arts[n].ar_name))
350: {
351: printf("%s\n%32s", thangs," ");
352: thangs[0] = '\0';
353: }
354: strcat(thangs, arts[n].ar_name);
355: }
356: }
357:
358: if (strlen(thangs))
359: printf("%s,", thangs);
360:
361: printf("\n%32s"," ");
362: }
363:
364: printf("%s on level %d",reason[scp->sc_flags],scp->sc_level);
365:
366: if (scp->sc_flags == 0)
367: {
368: printf(" by \n%32s"," ");
369: killer = killname(scp->sc_monster, buf);
370: printf(" %s", killer);
371: }
372:
373: putchar('\n');
374: }
375: }
376:
377: if (sc2 != NULL)
378: {
379: fseek(fd_score, 0L, SEEK_SET);
380: /* Update the list file */
381: fwrite(top_ten, sizeof(top_ten), 1, fd_score);
382: }
383:
384: fclose(fd_score);
385:
386: if (flags != SCOREIT) {
387: printf("[Press RETURN to exit]\n");
388: fflush(stdout);
389: getchar();
390: }
391: }
392:
393: void
394: writelog(long amount, int lvl, int flags, int monst)
395: {
396: char fate[80];
397: if (file_log == NULL)
398: return;
399: if (flags == KILLED) {
400: strcpy(fate, "killed by ");
401: killname(monst, fate + 10);
402: }
403: else if (flags == CHICKEN) {
404: strcpy(fate, "quit");
405: }
406: else if (flags == WINNER || flags == TOTAL) {
407: strcpy(fate, "escaped");
408: }
409: else
410: return;
411: fprintf(file_log, "%ld %ld %s %d %s %d %d %d %s\n", time(NULL), amount,
412: whoami, lvl, which_class(player.t_ctype), level, max_level,
413: has_artifact, fate);
414: fclose(file_log);
415: return;
416: }
417:
418: void
419: total_winner(void)
420: {
421: struct linked_list *item;
422: struct object *obj;
423: int worth, oldpurse;
424: char c;
425: struct linked_list *bag = NULL;
426:
427: clear();
428: standout();
429: addstr(" \n");
430: addstr(" @ @ @ @ @ @@@ @ @ \n");
431: addstr(" @ @ @@ @@ @ @ @ @ \n");
432: addstr(" @ @ @@@ @ @ @ @ @ @@@ @@@@ @@@ @ @@@ @ \n");
433: addstr(" @@@@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ \n");
434: addstr(" @ @ @ @ @ @ @ @@@@ @ @ @@@@@ @ @ @ \n");
435: addstr(" @ @ @ @ @ @@ @ @ @ @ @ @ @ @ @ @ \n");
436: addstr(" @@@ @@@ @@ @ @ @ @@@@ @@@@ @@@ @@@ @@ @ \n");
437: addstr(" \n");
438: addstr(" Congratulations, you have made it to the light of day! \n");
439: standend();
440: addstr("\nYou have joined the elite ranks of those who have \n");
441: addstr("escaped the Dungeons of Doom alive. You journey home \n");
442: addstr("and sell all your loot at a great profit.\n");
443: addstr("The White Council approves the recommendation of\n");
444:
445: if (player.t_ctype == C_FIGHTER)
446: addstr("the fighters guild and appoints you Lord Protector\n");
447: else if (player.t_ctype == C_ASSASIN)
448: addstr("the assassins guild and appoints you Master Murderer\n");
449: else if (player.t_ctype == C_NINJA)
450: addstr("the ninja guild and appoints you Master of the Wind\n");
451: else if (player.t_ctype == C_ILLUSION)
452: addstr("the illusionists guild and appoints you Master Wizard\n");
453: else if (player.t_ctype == C_MAGICIAN)
454: addstr("the magicians guild and appoints you Master Wizard\n");
455: else if (player.t_ctype == C_CLERIC)
456: addstr("the temple priests and appoints you Master of the Flowers\n");
457: else if (player.t_ctype == C_DRUID)
458: addstr("the temple priests and appoints you Master of the Flowers\n");
459: else if (player.t_ctype == C_RANGER)
460: addstr("the rangers guild and appoints you Master Ranger\n");
461: else if (player.t_ctype == C_PALADIN)
462: addstr("the paladins guild and appoints you Master Paladin\n");
463: else if (player.t_ctype == C_THIEF)
464: {
465: addstr("the thieves guild under protest and appoints you\n");
466: addstr("Master of the Highways\n");
467: }
468:
469: addstr("of the Land Between the Mountains.\n");
470: mvaddstr(LINES - 1, 0, spacemsg);
471: refresh();
472: wait_for(' ');
473: clear();
474: idenpack();
475: oldpurse = purse;
476: mvaddstr(0, 0, " Worth Item");
477:
478: for (c = 'a', item = pack; item != NULL; c++, item = next(item))
479: {
480: obj = OBJPTR(item);
481: worth = get_worth(obj);
482: purse += worth;
483:
484: if (obj->o_type == ARTIFACT && obj->o_which == TR_PURSE)
485: bag = obj->o_bag;
486:
487: mvprintw(c - 'a' + 1, 0, "%c) %8d %s", c,
488: worth, inv_name(obj, UPPERCASE));
489: }
490:
491: if (bag != NULL)
492: {
493: mvaddstr(LINES - 1, 0, morestr);
494: refresh();
495: wait_for(' ');
496: clear();
497: mvprintw(0, 0, "Contents of the Magic Purse of Yendor:\n");
498:
499: for (c = 'a', item = bag; item != NULL; c++, item = next(item))
500: {
501: obj = OBJPTR(item);
502: worth = get_worth(obj);
503: whatis(item);
504: purse += worth;
505: mvprintw(c - 'a' + 1, 0, "%c) %8d %s\n", c,
506: worth, inv_name(obj, UPPERCASE));
507: }
508: }
509:
510: mvprintw(c - 'a' + 1, 0, " %6d Gold Pieces ", oldpurse);
511: refresh();
512:
513: if (has_artifact == 255)
514: score(pstats.s_exp, pstats.s_lvl, TOTAL, 0);
515: else
516: score(pstats.s_exp, pstats.s_lvl, WINNER, 0);
517:
518: byebye();
519: }
520:
521: char *
522: killname(int monst, char *buf)
523: {
524: if (buf == NULL)
525: return("A bug in UltraRogue #102");
526:
527: if (monst >= 0)
528: {
529: switch (monsters[monst].m_name[0])
530: {
531: case 'a':
532: case 'e':
533: case 'i':
534: case 'o':
535: case 'u':
536: sprintf(buf, "an %s", monsters[monst].m_name);
537: break;
538: default:
539: sprintf(buf, "a %s", monsters[monst].m_name);
540: }
541:
542: return(buf);
543: }
544: else
545: switch(monst)
546: {
547: case D_ARROW:
548: strcpy(buf, "an arrow"); break;
549: case D_DART:
550: strcpy(buf, "a dart"); break;
551: case D_BOLT:
552: strcpy(buf, "a bolt"); break;
553: case D_POISON:
554: strcpy(buf, "poison"); break;
555: case D_POTION:
556: strcpy(buf, "a cursed potion"); break;
557: case D_PETRIFY:
558: strcpy(buf, "petrification"); break;
559: case D_SUFFOCATION:
560: strcpy(buf, "suffocation"); break;
561: case D_INFESTATION:
562: strcpy(buf, "a parasite"); break;
563: case D_DROWN:
564: strcpy(buf, "drowning"); break;
565: case D_FALL:
566: strcpy(buf, "falling"); break;
567: case D_FIRE:
568: strcpy(buf, "slow boiling in oil"); break;
569: case D_SPELLFUMBLE:
570: strcpy(buf, "a botched spell"); break;
571: case D_DRAINLIFE:
572: strcpy(buf, "a drain life spell"); break;
573: case D_ARTIFACT:
574: strcpy(buf, "an artifact of the gods"); break;
575: case D_GODWRATH:
576: strcpy(buf, "divine retribution"); break;
577: case D_CLUMSY:
578: strcpy(buf, "excessive clumsyness"); break;
579: default:
580: strcpy(buf, "stupidity"); break;
581: }
582:
583: return(buf);
584: }
585:
586: /*
587: showpack()
588: Display the contents of the hero's pack
589: */
590:
591: void
592: showpack(char *howso)
593: {
594: char *iname;
595: unsigned int worth;
596: int cnt, ch, oldpurse;
597: struct linked_list *item;
598: struct object *obj;
599: struct linked_list *bag = NULL;
600:
601: cnt = 1;
602: clear();
603: mvprintw(0, 0, "Contents of your pack %s:\n", howso);
604: ch = 0;
605: oldpurse = purse;
606: purse = 0;
607:
608: for (item = pack; item != NULL; item = next(item))
609: {
610: obj = OBJPTR(item);
611: worth = get_worth(obj);
612: whatis(item);
613: purse += worth;
614:
615: if (obj->o_type == ARTIFACT && obj->o_which == TR_PURSE)
616: bag = obj->o_bag;
617:
618: iname = inv_name(obj, UPPERCASE);
619: mvprintw(cnt, 0, "%d) %s\n", ch, iname);
620: ch += 1;
621:
622: if (++cnt > LINES - 5 && next(item) != NULL)
623: {
624: cnt = 1;
625: mvaddstr(LINES - 1, 0, morestr);
626: refresh();
627: wait_for(' ');
628: clear();
629: }
630: }
631:
632: if (bag != NULL)
633: {
634: mvaddstr(LINES - 1, 0, morestr);
635: refresh();
636: wait_for(' ');
637: clear();
638: cnt = 1;
639: ch = 0;
640:
641: mvprintw(0, 0, "Contents of the Magic Purse of Yendor %s:\n", howso);
642:
643: for (item = bag; item != NULL; item = next(item))
644: {
645: obj = OBJPTR(item);
646: worth = get_worth(obj);
647: whatis(item);
648: purse += worth;
649: mvprintw(cnt, 0, "%d) %s\n", ch, inv_name(obj, UPPERCASE));
650: ch += 1;
651:
652: if (++cnt > LINES - 5 && next(item) != NULL)
653: {
654: cnt = 1;
655: mvaddstr(LINES - 1, 0, morestr);
656: refresh();
657: wait_for(' ');
658: clear();
659: }
660: }
661: }
662:
663: mvprintw(cnt + 1, 0, "Carrying %d gold pieces", oldpurse);
664: mvprintw(cnt + 2, 0, "Carrying objects worth %d gold pieces", purse);
665: purse += oldpurse;
666: refresh();
667: }
668:
669: void
670: byebye(void)
671: {
672: endwin();
673: printf("\n");
674: exit(0);
675: }
676:
677: /*
678: save_resurrect()
679: chance of resurrection according to modifed D&D probabilities
680: */
681:
682: int
683: save_resurrect(int bonus)
684: {
685: int need, adjust;
686:
687: adjust = pstats.s_const + bonus - luck;
688:
689: if (adjust > 17)
690: return(TRUE);
691: else if (adjust < 14)
692: need = 5 * (adjust + 5);
693: else
694: need = 90 + 2 * (adjust - 13);
695:
696: return(roll(1, 100) < need);
697: }
CVSweb