rogue

Ken Arnold's Rogue
git clone https://git.woozle.org/neale/rogue.git

Neale Pickett  ·  2013-07-18

inter.c

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