]>
git.cameronkatri.com Git - bsdgames-darwin.git/blob - hack/hack.end.c
1 /* $NetBSD: hack.end.c,v 1.11 2009/06/07 18:30:39 dholland Exp $ */
4 * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
12 * - Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
15 * - Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * - Neither the name of the Stichting Centrum voor Wiskunde en
20 * Informatica, nor the names of its contributors may be used to endorse or
21 * promote products derived from this software without specific prior
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
27 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
28 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
39 * All rights reserved.
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 * 3. The name of the author may not be used to endorse or promote products
50 * derived from this software without specific prior written permission.
52 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
53 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
54 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
55 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
56 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
57 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
58 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
59 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
60 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
61 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64 #include <sys/cdefs.h>
66 __RCSID("$NetBSD: hack.end.c,v 1.11 2009/06/07 18:30:39 dholland Exp $");
74 #define Sprintf (void) sprintf
90 (void) signal(SIGINT
, SIG_IGN
);
91 pline("Really quit?");
92 if (readchar() != 'y') {
93 (void) signal(SIGINT
, done1
);
95 (void) fflush(stdout
);
109 done_intr(int n __unused
)
112 (void) signal(SIGINT
, SIG_IGN
);
113 (void) signal(SIGQUIT
, SIG_IGN
);
120 (void) signal(SIGHUP
, SIG_IGN
);
125 done_in_by(struct monst
*mtmp
)
127 static char buf
[BUFSZ
];
128 pline("You die ...");
129 if (mtmp
->data
->mlet
== ' ') {
130 Sprintf(buf
, "the ghost of %s", (char *) mtmp
->mextra
);
132 } else if (mtmp
->mnamelth
) {
133 Sprintf(buf
, "%s called %s",
134 mtmp
->data
->mname
, NAME(mtmp
));
136 } else if (mtmp
->minvis
) {
137 Sprintf(buf
, "invisible %s", mtmp
->data
->mname
);
140 killer
= mtmp
->data
->mname
;
145 * called with arg "died", "drowned", "escaped", "quit", "choked",
146 * "panicked", "burned", "starved" or "tricked"
148 /* Be careful not to call panic from here! */
150 done(const char *st1
)
154 if (wizard
&& *st1
== 'd') {
157 u
.uhpmax
= 100; /* arbitrary */
159 pline("For some reason you are still alive.");
169 (void) signal(SIGINT
, done_intr
);
170 (void) signal(SIGQUIT
, done_intr
);
171 (void) signal(SIGHUP
, done_hangup
);
172 if (*st1
== 'q' && u
.uhp
< 1) {
174 killer
= "quit while already on Charon's boat";
177 killer
= "starvation";
178 else if (*st1
== 'd' && st1
[1] == 'r')
180 else if (*st1
== 'p')
182 else if (*st1
== 't')
184 else if (!strchr("bcd", *st1
))
188 if (flags
.toplin
== 1)
190 if (strchr("bcds", *st1
)) {
195 if (!flags
.notombstone
)
199 killer
= st1
; /* after outrip() */
200 settty((char *) 0); /* does a clear_screen() */
202 printf("Goodbye %s %s...\n\n", pl_character
, plname
);
205 tmp
= u
.ugold
- u
.ugold0
;
208 if (*st1
== 'd' || *st1
== 'b')
211 u
.urexp
+= 50 * maxdlevel
;
213 u
.urexp
+= 1000 * ((maxdlevel
> 30) ? 10 : maxdlevel
- 20);
219 unsigned worthlessct
= 0;
220 boolean has_amulet
= FALSE
;
230 printf(" and %s", monnam(mtmp
));
232 u
.urexp
+= mtmp
->mhp
;
236 printf("\nescaped from the dungeon with %ld points,\n",
238 } else if (!done_stopprint
)
239 printf("You escaped from the dungeon with %ld points,\n",
241 for (otmp
= invent
; otmp
; otmp
= otmp
->nobj
) {
242 if (otmp
->olet
== GEM_SYM
) {
243 objects
[otmp
->otyp
].oc_name_known
= 1;
244 i
= otmp
->quan
* objects
[otmp
->otyp
].g_val
;
246 worthlessct
+= otmp
->quan
;
251 printf("\t%s (worth %d Zorkmids),\n",
253 } else if (otmp
->olet
== AMULET_SYM
) {
255 i
= (otmp
->spe
< 0) ? 2 : 5000;
258 printf("\t%s (worth %d Zorkmids),\n",
260 if (otmp
->spe
>= 0) {
262 killer
= "escaped (with amulet)";
268 printf("\t%u worthless piece%s of coloured glass,\n",
269 worthlessct
, plur(worthlessct
));
272 } else if (!done_stopprint
)
273 printf("You %s on dungeon level %d with %ld points,\n",
274 st1
, dlevel
, u
.urexp
);
276 printf("and %ld piece%s of gold, after %ld move%s.\n",
277 u
.ugold
, plur(u
.ugold
), moves
, plur(moves
));
279 printf("You were level %u with a maximum of %d hit points when you %s.\n",
280 u
.ulevel
, u
.uhpmax
, st1
);
281 if (*st1
== 'e' && !done_stopprint
) {
282 getret(); /* all those pieces of coloured glass ... */
294 #define newttentry() (struct toptenentry *) alloc(sizeof(struct toptenentry))
298 #define POINTSMIN 1 /* must be > 0 */
299 #define ENTRYMAX 100 /* must be >= 10 */
300 #define PERS_IS_UID /* delete for PERSMAX per name; now per uid */
302 struct toptenentry
*tt_next
;
304 int level
, maxlvl
, hp
, maxhp
;
308 char name
[NAMSZ
+ 1];
309 char death
[DTHSZ
+ 1];
310 char date
[7];/* yymmdd */
317 int rank
, rank0
= -1, rank1
= 0;
318 int occ_cnt
= PERSMAX
;
319 struct toptenentry
*t0
, *t1
, *tprev
;
320 const char *recfile
= RECORD
;
321 const char *reclock
= "record_lock";
325 #define HUP if(!done_hup)
326 while (link(recfile
, reclock
) == -1) {
329 HUP
puts("I give up. Sorry.");
330 HUP
puts("Perhaps there is an old record_lock around?");
333 HUP
printf("Waiting for access to record file. (%d)\n",
335 HUP(void) fflush(stdout
);
338 if (!(rfile
= fopen(recfile
, "r"))) {
339 HUP
puts("Cannot open record file!");
342 HUP(void) putchar('\n');
344 /* create a new 'topten' entry */
347 t0
->maxlvl
= maxdlevel
;
349 t0
->maxhp
= u
.uhpmax
;
350 t0
->points
= u
.urexp
;
351 t0
->plchar
= pl_character
[0];
352 t0
->sex
= (flags
.female
? 'F' : 'M');
354 (void) strncpy(t0
->name
, plname
, NAMSZ
);
355 (t0
->name
)[NAMSZ
] = 0;
356 (void) strncpy(t0
->death
, killer
, DTHSZ
);
357 (t0
->death
)[DTHSZ
] = 0;
358 (void) strcpy(t0
->date
, getdatestr());
360 /* assure minimum number of points */
361 if (t0
->points
< POINTSMIN
)
364 t1
= tt_head
= newttentry();
366 /* rank0: -1 undefined, 0 not_on_list, n n_th on list */
368 if (fscanf(rfile
, "%6s %d %d %d %d %d %ld %c%c %[^,],%[^\n]",
370 &t1
->level
, &t1
->maxlvl
,
371 &t1
->hp
, &t1
->maxhp
, &t1
->points
,
372 &t1
->plchar
, &t1
->sex
, t1
->name
, t1
->death
) != 11
373 || t1
->points
< POINTSMIN
)
375 if (rank0
< 0 && t1
->points
< t0
->points
) {
383 flg
++; /* ask for a rewrite */
390 t1
->uid
== t0
->uid
&&
392 strncmp(t1
->name
, t0
->name
, NAMSZ
) == 0 &&
393 #endif /* PERS_IS_UID */
394 t1
->plchar
== t0
->plchar
&& --occ_cnt
<= 0) {
398 HUP
printf("You didn't beat your previous score of %ld points.\n\n",
406 if (rank
<= ENTRYMAX
) {
407 t1
= t1
->tt_next
= newttentry();
410 if (rank
> ENTRYMAX
) {
415 if (flg
) { /* rewrite record file */
416 (void) fclose(rfile
);
417 if (!(rfile
= fopen(recfile
, "w"))) {
418 HUP
puts("Cannot write record file\n");
424 puts("You made the top ten list!\n");
426 printf("You reached the %d%s place on the top %d list.\n\n",
427 rank0
, ordin(rank0
), ENTRYMAX
);
437 for (rank
= 1; t1
->points
!= 0; rank
++, t1
= t1
->tt_next
) {
439 fprintf(rfile
, "%6s %d %d %d %d %d %ld %c%c %s,%s\n",
441 t1
->level
, t1
->maxlvl
,
442 t1
->hp
, t1
->maxhp
, t1
->points
,
443 t1
->plchar
, t1
->sex
, t1
->name
, t1
->death
);
446 if (rank
> (int)flags
.end_top
&&
447 (rank
< rank0
- (int)flags
.end_around
|| rank
> rank0
+ (int)flags
.end_around
)
448 && (!flags
.end_own
||
452 strncmp(t1
->name
, t0
->name
, NAMSZ
)))
453 #endif /* PERS_IS_UID */
455 if (rank
== rank0
- (int)flags
.end_around
&&
456 rank0
> (int)flags
.end_top
+ (int)flags
.end_around
+ 1 &&
458 (void) putchar('\n');
460 (void) outentry(rank
, t1
, 0);
462 (void) outentry(rank
, t1
, 1);
464 int t0lth
= outentry(0, t0
, -1);
465 int t1lth
= outentry(rank
, t1
, t0lth
);
468 (void) outentry(0, t0
, t0lth
);
473 (void) outentry(0, t0
, 1);
474 (void) fclose(rfile
);
477 (void) unlink(reclock
);
485 (void) strcpy(linebuf
, "Number Points Name");
487 while (bp
< linebuf
+ COLNO
- 9)
489 (void) strcpy(bp
, "Hp [max]");
493 /* so>0: standout line; so=0: ordinary line; so<0: no output, return lth */
495 outentry(int rank
, struct toptenentry
*t1
, int so
)
497 boolean quit
= FALSE
, gotkilled
= FALSE
, starv
= FALSE
;
502 Sprintf(eos(linebuf
), "%3d", rank
);
504 Sprintf(eos(linebuf
), " ");
505 Sprintf(eos(linebuf
), " %6ld %8s", t1
->points
, t1
->name
);
506 if (t1
->plchar
== 'X')
507 Sprintf(eos(linebuf
), " ");
509 Sprintf(eos(linebuf
), "-%c ", t1
->plchar
);
510 if (!strncmp("escaped", t1
->death
, 7)) {
511 if (!strcmp(" (with amulet)", t1
->death
+ 7))
512 Sprintf(eos(linebuf
), "escaped the dungeon with amulet");
514 Sprintf(eos(linebuf
), "escaped the dungeon [max level %d]",
517 if (!strncmp(t1
->death
, "quit", 4)) {
519 if (t1
->maxhp
< 3 * t1
->hp
&& t1
->maxlvl
< 4)
520 Sprintf(eos(linebuf
), "cravenly gave up");
522 Sprintf(eos(linebuf
), "quit");
523 } else if (!strcmp(t1
->death
, "choked"))
524 Sprintf(eos(linebuf
), "choked on %s food",
525 (t1
->sex
== 'F') ? "her" : "his");
526 else if (!strncmp(t1
->death
, "starv", 5))
527 Sprintf(eos(linebuf
), "starved to death"), starv
= TRUE
;
529 Sprintf(eos(linebuf
), "was killed"), gotkilled
= TRUE
;
530 Sprintf(eos(linebuf
), " on%s level %d",
531 (gotkilled
|| starv
) ? "" : " dungeon", t1
->level
);
532 if (t1
->maxlvl
!= t1
->level
)
533 Sprintf(eos(linebuf
), " [max %d]", t1
->maxlvl
);
534 if (quit
&& t1
->death
[4])
535 Sprintf(eos(linebuf
), t1
->death
+ 4);
538 Sprintf(eos(linebuf
), " by %s%s",
539 (!strncmp(t1
->death
, "trick", 5) || !strncmp(t1
->death
, "the ", 4))
541 strchr(vowels
, *t1
->death
) ? "an " : "a ",
543 Sprintf(eos(linebuf
), ".");
545 char *bp
= eos(linebuf
);
548 Sprintf(hpbuf
, (t1
->hp
> 0) ? itoa(t1
->hp
) : "-");
549 hppos
= COLNO
- 7 - strlen(hpbuf
);
550 if (bp
<= linebuf
+ hppos
) {
551 while (bp
< linebuf
+ hppos
)
553 (void) strcpy(bp
, hpbuf
);
554 Sprintf(eos(bp
), " [%d]", t1
->maxhp
);
560 char *bp
= eos(linebuf
);
563 while (bp
< linebuf
+ so
)
567 fputs(linebuf
, stdout
);
569 (void) putchar('\n');
571 return (strlen(linebuf
));
578 Sprintf(buf
, "%d", a
);
587 return ((dg
== 0 || dg
> 3 || n
/ 10 == 1) ? "th" : (dg
== 1) ? "st" :
588 (dg
== 2) ? "nd" : "rd");
595 (void) signal(SIGHUP
, SIG_IGN
);
596 for (x
= maxdlevel
; x
>= 0; x
--) {
598 (void) unlink(lock
); /* not all levels need be present */
602 #ifdef NOSAVEONHANGUP
605 hangup(int n __unused
)
607 (void) signal(SIGINT
, SIG_IGN
);
611 #endif /* NOSAVEONHANGUP */
621 /* it is the callers responsibility to check that there is room for c */
623 charcat(char *s
, int c
)
632 * Called with args from main if argc >= 0. In this case, list scores as
633 * requested. Otherwise, find scores for the current player (and list them
637 prscore(int argc
, char **argv
)
639 char **players
= NULL
;
642 struct toptenentry
*t1
, *t2
;
643 const char *recfile
= RECORD
;
648 long total_score
= 0L;
651 #endif /* nonsense */
652 int outflg
= (argc
>= -1);
657 #endif /* PERS_IS_UID */
659 if (!(rfile
= fopen(recfile
, "r"))) {
660 puts("Cannot open record file!");
663 if (argc
> 1 && !strncmp(argv
[1], "-s", 2)) {
667 } else if (!argv
[1][3] && strchr("CFKSTWX", argv
[1][2])) {
680 player0
= "hackplayer";
683 #endif /* PERS_IS_UID */
691 t1
= tt_head
= newttentry();
692 for (rank
= 1;; rank
++) {
693 if (fscanf(rfile
, "%6s %d %d %d %d %d %ld %c%c %[^,],%[^\n]",
695 &t1
->level
, &t1
->maxlvl
,
696 &t1
->hp
, &t1
->maxhp
, &t1
->points
,
697 &t1
->plchar
, &t1
->sex
, t1
->name
, t1
->death
) != 11)
702 if (!playerct
&& t1
->uid
== uid
)
705 #endif /* PERS_IS_UID */
706 for (i
= 0; i
< playerct
; i
++) {
707 if (strcmp(players
[i
], "all") == 0 ||
708 strncmp(t1
->name
, players
[i
], NAMSZ
) == 0 ||
709 (players
[i
][0] == '-' &&
710 players
[i
][1] == t1
->plchar
&&
711 players
[i
][2] == 0) ||
712 (digit(players
[i
][0]) && rank
<= atoi(players
[i
])))
715 t1
= t1
->tt_next
= newttentry();
717 (void) fclose(rfile
);
720 printf("Cannot find any entries for ");
726 for (i
= 0; i
< playerct
; i
++)
727 printf("%s%s", players
[i
], (i
< playerct
- 1) ? ", " : ".\n");
728 printf("Call is: %s -s [playernames]\n", hname
);
736 for (rank
= 1; t1
->points
!= 0; rank
++, t1
= t2
) {
739 if (!playerct
&& t1
->uid
== uid
)
742 #endif /* PERS_IS_UID */
743 for (i
= 0; i
< playerct
; i
++) {
744 if (strcmp(players
[i
], "all") == 0 ||
745 strncmp(t1
->name
, players
[i
], NAMSZ
) == 0 ||
746 (players
[i
][0] == '-' &&
747 players
[i
][1] == t1
->plchar
&&
748 players
[i
][2] == 0) ||
749 (digit(players
[i
][0]) && rank
<= atoi(players
[i
]))) {
752 (void) outentry(rank
, t1
, 0);
754 total_score
+= t1
->points
;
755 if (totcharct
< sizeof(totchars
) - 1)
756 totchars
[totcharct
++] = t1
->plchar
;
757 #endif /* nonsense */
764 totchars
[totcharct
] = 0;
767 * We would like to determine whether he is experienced. However, the
768 * information collected here only tells about the scores/roles that
769 * got into the topten (top 100?). We should maintain a .hacklog or
770 * something in his home directory.
772 flags
.beginner
= (total_score
< 6000);
773 for (i
= 0; i
< 6; i
++)
774 if (!strchr(totchars
, "CFKSTWX"[i
])) {
776 if (!pl_character
[0])
777 pl_character
[0] = "CFKSTWX"[i
];
780 #endif /* nonsense */