view arogue7/rip.c @ 186:85bd398cb96d

srogue: another unistd.h which should not be included on Windows.
author John "Elwin" Edwards
date Mon, 03 Aug 2015 06:30:09 -0400
parents 7faf4568c295
children ca876944b196
line wrap: on
line source

/*
 * rip.c - File for the fun ends Death or a total win
 *
 * Advanced Rogue
 * Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
 * All rights reserved.
 *
 * Based on "Rogue: Exploring the Dungeons of Doom"
 * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
 * All rights reserved.
 *
 * See the file LICENSE.TXT for full copyright and licensing information.
 */

/* Print flags for scoring */
#define REALLIFE 1	/* Print out machine and logname */
#define EDITSCORE 2	/* Edit the current score file */
#define ADDSCORE 3	/* Add a new score */

#define NAMELEN	80

/*
 * File for the fun ends
 * Death or a total win
 *
 */

#include "curses.h"
#ifdef BSD
#include <sys/time.h>
#else
#include <time.h>
#endif
#include <signal.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include "mach_dep.h"
#include "network.h"
#include "rogue.h"
#ifdef PC7300
#include "sys/window.h"
extern struct uwdata wdata, oldwin;
extern char oldtext[WTXTNUM][WTXTLEN];
#endif

extern int scorefd;
extern FILE *logfile;

#ifdef NUMNET
/* Network machines (for mutual score keeping) */
static struct network Network[NUMNET] = {
    { "ihwpt", "/t1/michael/bin/rg" },
};
#endif

/*
 * If you change this structure, change the compatibility routines
 * scoreout() and scorein() to reflect the change.  Also update SCORELEN.
 */
struct sc_ent {
    unsigned long	sc_score;
    char	sc_name[NAMELEN];
    char	sc_system[SYSLEN];
    char	sc_login[LOGLEN];
    short	sc_flags;
    short	sc_level;
    short	sc_ctype;
    short	sc_monster;
    short	sc_quest;
};
#define SCORELEN \
    (sizeof(unsigned long) + NAMELEN + SYSLEN + LOGLEN + 5*sizeof(short))

static char *rip[] = {
"                       __________",
"                      /          \\",
"                     /    REST    \\",
"                    /      IN      \\",
"                   /     PEACE      \\",
"                  /                  \\",
"                  |                  |",
"                  |                  |",
"                  |    killed by     |",
"                  |                  |",
"                  |       1984       |",
"                 *|     *  *  *      | *",
"         ________)/\\\\_//(\\/(/\\)/\\//\\/|_)_______",
    0
};

char	*killname();





void
byebye(sig)
int sig;
{
    if (!isendwin()) {
        clear();
	endwin();
    }
#ifdef PC7300
    endhardwin();
#endif
    printf("\n");
    exit(0);
}


/*
 * death:
 *	Do something really fun when he dies
 */

death(monst)
register short monst;
{
    register char **dp = rip, *killer;
    register struct tm *lt;
    time_t date;
    char buf[LINELEN];
    struct tm *localtime();

    time(&date);
    lt = localtime(&date);
    clear();
    move(8, 0);
    while (*dp)
	printw("%s\n", *dp++);
    mvaddstr(14, 28-((strlen(whoami)+1)/2), whoami);
    sprintf(buf, "%lu Points", pstats.s_exp );
    mvaddstr(15, 28-((strlen(buf)+1)/2), buf);
    killer = killname(monst);
    mvaddstr(17, 28-((strlen(killer)+1)/2), killer);
    mvaddstr(18, 26, (sprintf(prbuf, "%4d", 1900+lt->tm_year), prbuf));
    move(lines-1, 0);
    refresh();
    writelog(pstats.s_exp, KILLED, monst);
    score(pstats.s_exp, KILLED, monst);
    endwin();
#ifdef PC7300
    endhardwin();
#endif
    exit(0);
}

#ifdef PC7300
/*
 * Restore window characteristics on a hard window terminal (PC7300).
 */
endhardwin()
{
    register int i;
    struct utdata labelbuf;

    /* Restore the old window size */
    if (oldwin.uw_width) ioctl(1, WIOCSETD, &oldwin);

    /* Restore the old window text */
    for (i=0; i<WTXTNUM; i++) {
	labelbuf.ut_num = i;
	strcpy(labelbuf.ut_text, oldtext[i]);
	ioctl(1, WIOCSETTEXT, &labelbuf);
    }
}
#endif

char *
killname(monst)
register short monst;
{
    static char mons_name[LINELEN];
    int i;

    if (monst > NUMMONST) return("a strange monster");

    if (monst >= 0) {
	switch (monsters[monst].m_name[0]) {
	    case 'a':
	    case 'e':
	    case 'i':
	    case 'o':
	    case 'u':
		sprintf(mons_name, "an %s", monsters[monst].m_name);
		break;
	    default:
		sprintf(mons_name, "a %s", monsters[monst].m_name);
	}
	return(mons_name);
    }
    for (i = 0; i< DEATHNUM; i++) {
	if (deaths[i].reason == monst)
	    break;
    }
    if (i >= DEATHNUM)
	return ("strange death");
    return (deaths[i].name);
}

/* Writes an entry in the log file */

void 
writelog(unsigned long amount, int flags, short monst)
{
    char had_quest = '0';
    char fate[LINELEN];
    struct linked_list *item;
    struct object *obj;
#ifdef LOGFILE
    if (waswizard)
        return;
    if (logfile == NULL)
        return;
    /* Check for quest item */
    for (item = pack; item != NULL; item = next(item)) {
        obj = OBJPTR(item);
        if (obj->o_type == RELIC && obj->o_which == quest_item)
            had_quest = '1';
    }
    /* Describe what happened */
    if (flags == KILLED) {
        snprintf(fate, LINELEN, "killed by %s", killname(monst));
    }
    else if (flags == CHICKEN) {
        strcpy(fate, "quit");
    }
    else if (flags == WINNER) {
        strcpy(fate, "escaped");
    }
    else
        return;
    /* Write */
    fprintf(logfile, "%d %d %s %d %s %d %d %d %c %s\n", time(NULL), amount,
            whoami, pstats.s_lvl, char_class[char_type].name, level, max_level,
            quest_item, had_quest, fate);
    fclose(logfile);
#endif
    return;
}

/*
 * score -- figure score and post it.
 */

/* VARARGS2 */
score(amount, flags, monst)
unsigned long amount;
short monst;
{
    static struct sc_ent top_ten[NUMSCORE];
    register struct sc_ent *scp;
    register int i;
    register struct sc_ent *sc2;
    register int outfd;
    register char *killer;
    register int prflags = 0;
    register int fd;
    short upquest, wintype, uplevel, uptype;	/* For network updating */
    char upsystem[SYSLEN], uplogin[LOGLEN];
    char *thissys;	/* Holds the name of this system */
    char *compatstr=NULL; /* Holds scores for writing compatible score files */
    char scoreline[100];
#define REASONLEN 3
    static char *reason[] = {
	"killed",
	"quit",
	"A total winner",
	"somehow left",
    };
    char *packend;

    signal(SIGINT, byebye);
    if (flags != WINNER && flags != SCOREIT && flags != UPDATE) {
	if (flags == CHICKEN)
	    packend = "when you quit";
	else
	{
	    packend = "at your untimely demise";
	    mvaddstr(lines - 1, 0, retstr);
	    refresh();
	    getstr(prbuf);
	}
	 showpack(packend);
    }
    purse = 0;	/* Steal all the gold */

    /*
     * Open file and read list
     */

    if ((fd = scorefd) < 0) return;
    outfd = fd;

#ifndef SYSTEM
    thissys = md_gethostname();
#else
    thissys = SYSTEM;
#endif

    for (scp = top_ten; scp <= &top_ten[NUMSCORE-1]; scp++)
    {
	scp->sc_score = 0L;
	for (i = 0; i < NAMELEN; i++)
	    scp->sc_name[i] = rnd(255);
	scp->sc_quest= RN;
	scp->sc_flags = RN;
	scp->sc_level = RN;
	scp->sc_monster = RN;
	scp->sc_ctype = 0;
	strncpy(scp->sc_system, thissys, SYSLEN);
	scp->sc_login[0] = '\0';
    }

    /*
     * If this is a SCOREIT optin (rogue -s), don't call byebye.  The
     * endwin() call in byebye() will result in a core dump.
     */
    if (flags == SCOREIT) signal(SIGINT, SIG_DFL);
    else signal(SIGINT, byebye);

    if (flags != SCOREIT && flags != UPDATE)
    {
	mvaddstr(lines - 1, 0, retstr);
	refresh();
	fflush(stdout);
	getstr(prbuf);
    }

    /* Check for special options */
    if (strcmp(prbuf, "names") == 0)
	prflags = REALLIFE;
#ifdef WIZARD
    else if (wizard) {
	if (strcmp(prbuf, "edit") == 0) prflags = EDITSCORE;
	else if (strcmp(prbuf, "add") == 0) {
	    prflags = ADDSCORE;
	    waswizard = FALSE;	/* We want the new score recorded */
	}
    }
#endif

    /* Read the score and convert it to a compatible format */
    for(i = 0; i < NUMSCORE; i++)
    {
	encread(top_ten[i].sc_name, NAMELEN, fd);
	encread(top_ten[i].sc_system, SYSLEN, fd);
	encread(top_ten[i].sc_login, LOGLEN, fd);
	encread(scoreline, 100, fd);
	sscanf(scoreline, " %lu %hd %hd %hd %hd %hd \n",
	    &top_ten[i].sc_score, &top_ten[i].sc_flags, 
	    &top_ten[i].sc_level, &top_ten[i].sc_ctype,
	    &top_ten[i].sc_monster, &top_ten[i].sc_quest
	    );
    }

    /* Get some values if this is an update */
    if (flags == UPDATE) {
	unsigned long netread();
	int errcheck, errors = 0;

	upquest = (short) netread(&errcheck, sizeof(short), stdin);
	if (errcheck) errors++;

	if (fread(whoami, 1, NAMELEN, stdin) != NAMELEN) errors++;

	wintype = (short) netread(&errcheck, sizeof(short), stdin);
	if (errcheck) errors++;

	uplevel = (short) netread(&errcheck, sizeof(short), stdin);
	if (errcheck) errors++;

	uptype = (short) netread(&errcheck, sizeof(short), stdin);
	if (errcheck) errors++;

	if (fread(upsystem, 1, SYSLEN, stdin) != SYSLEN)
		errors++;
	if (fread(uplogin, 1, LOGLEN, stdin) != LOGLEN)
		errors++;
	
	if (errors) {
	    close(outfd);
	    free(compatstr);
	    return;
	}
    }

    /*
     * Insert player in list if need be
     */
    if (!waswizard) {
	char *login;

	if (flags != UPDATE) {
            login = md_getusername();
	}

	if (flags == UPDATE)
	    (void) update(top_ten, amount, upquest, whoami, wintype,
		   uplevel, monst, uptype, upsystem, uplogin);
	else {
#ifdef WIZARD
	    if (prflags == ADDSCORE) {	/* Overlay characteristic by new ones */
	 	char buffer[LINELEN];

		clear();
		mvaddstr(1, 0, "Score: ");
		mvaddstr(2, 0, "Quest (number): ");
		mvaddstr(3, 0, "Name: ");
		mvaddstr(4, 0, "System: ");
		mvaddstr(5, 0, "Login: ");
		mvaddstr(6, 0, "Level: ");
		mvaddstr(7, 0, "Char type: ");
		mvaddstr(8, 0, "Result: ");

		/* Get the score */
		move(1, 7);