diff rogue5/save.c @ 33:f502bf60e6e4

Import Rogue 5.4 from the Roguelike Restoration Project (r1490)
author elwin
date Mon, 24 May 2010 20:10:59 +0000
parents
children 655c317b6237
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue5/save.c	Mon May 24 20:10:59 2010 +0000
@@ -0,0 +1,423 @@
+/*
+ * save and restore routines
+ *
+ * @(#)save.c	4.33 (Berkeley) 06/01/83
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <curses.h>
+#include "rogue.h"
+#include "score.h"
+
+/*
+ * save_game:
+ *	Implement the "save game" command
+ */
+
+void
+save_game(void)
+{
+    FILE *savef;
+    int c;
+    char buf[MAXSTR];
+    struct stat sbuf;
+    /*
+     * get file name
+     */
+    mpos = 0;
+over:
+    if (file_name[0] != '\0')
+    {
+	for (;;)
+	{
+	    msg("save file (%s)? ", file_name);
+	    c = readchar();
+	    mpos = 0;
+	    if (c == ESCAPE)
+	    {
+		msg("");
+		return;
+	    }
+	    else if (c == 'n' || c == 'N' || c == 'y' || c == 'Y')
+		break;
+	    else
+		msg("please answer Y or N");
+	}
+	if (c == 'y' || c == 'Y')
+	{
+	    addstr("Yes\n");
+	    refresh();
+	    strcpy(buf, file_name);
+	    goto gotfile;
+	}
+    }
+
+    do
+    {
+	mpos = 0;
+	msg("file name: ");
+	buf[0] = '\0';
+	if (get_str(buf, stdscr) == QUIT)
+	{
+quit_it:
+	    msg("");
+	    return;
+	}
+	mpos = 0;
+gotfile:
+	/*
+	 * test to see if the file exists
+	 */
+	if (stat(buf, &sbuf) >= 0)
+	{
+	    for (;;)
+	    {
+		msg("File exists.  Do you wish to overwrite it?");
+		mpos = 0;
+		if ((c = readchar()) == ESCAPE)
+		    goto quit_it;
+		if (c == 'y' || c == 'Y')
+		    break;
+		else if (c == 'n' || c == 'N')
+		    goto over;
+		else
+		    msg("Please answer Y or N");
+	    }
+	    msg("file name: %s", buf);
+	    md_unlink(file_name);
+	}
+	strcpy(file_name, buf);
+	if ((savef = fopen(file_name, "w")) == NULL)
+	    msg(strerror(errno));
+    } while (savef == NULL);
+    msg("");
+    save_file(savef);
+    /* NOTREACHED */
+}
+
+/*
+ * auto_save:
+ *	Automatically save a file.  This is used if a HUP signal is
+ *	recieved
+ */
+
+void
+auto_save(int sig)
+{
+    FILE *savef;
+    NOOP(sig);
+
+    md_ignoreallsignals();
+    if (file_name[0] != '\0' && ((savef = fopen(file_name, "w")) != NULL ||
+	(md_unlink_open_file(file_name, savef) >= 0 && (savef = fopen(file_name, "w")) != NULL)))
+	    save_file(savef);
+    exit(0);
+}
+
+/*
+ * save_file:
+ *	Write the saved game on the file
+ */
+
+void
+save_file(FILE *savef)
+{
+    char buf[80];
+    mvcur(0, COLS - 1, LINES - 1, 0); 
+    putchar('\n');
+    endwin();
+    resetltchars();
+    md_chmod(file_name, 0400);
+    encwrite(version, strlen(version)+1, savef);
+    sprintf(buf,"%d x %d\n", LINES, COLS);
+    encwrite(buf,80,savef);
+    rs_save_file(savef);
+    fflush(savef);
+    fclose(savef);
+    exit(0);
+}
+
+/*
+ * restore:
+ *	Restore a saved game from a file with elaborate checks for file
+ *	integrity from cheaters
+ */
+int
+restore(const char *file)
+{
+    FILE *inf;
+    int syml;
+    char buf[MAXSTR];
+    struct stat sbuf2;
+    int lines, cols;
+
+    if (strcmp(file, "-r") == 0)
+	file = file_name;
+
+	md_tstphold();
+
+	if ((inf = fopen(file,"r")) == NULL)
+    {
+	perror(file);
+	return FALSE;
+    }
+    stat(file, &sbuf2);
+    syml = is_symlink(file);
+
+    fflush(stdout);
+    encread(buf, strlen(version) + 1, inf);
+    if (strcmp(buf, version) != 0)
+    {
+	printf("Sorry, saved game is out of date.\n");
+	return FALSE;
+    }
+    encread(buf,80,inf);
+    (void) sscanf(buf,"%d x %d\n", &lines, &cols);
+
+    initscr();                          /* Start up cursor package */
+    keypad(stdscr, 1);
+
+    if (lines > LINES)
+    {
+        endwin();
+        printf("Sorry, original game was played on a screen with %d lines.\n",lines);
+        printf("Current screen only has %d lines. Unable to restore game\n",LINES);
+        return(FALSE);
+    }
+    if (cols > COLS)
+    {
+        endwin();
+        printf("Sorry, original game was played on a screen with %d columns.\n",cols);
+        printf("Current screen only has %d columns. Unable to restore game\n",COLS);
+        return(FALSE);
+    }
+
+    hw = newwin(LINES, COLS, 0, 0);
+    setup();
+
+    rs_restore_file(inf);
+    /*
+     * we do not close the file so that we will have a hold of the
+     * inode for as long as possible
+     */
+
+    if (
+#ifdef MASTER
+	!wizard &&
+#endif
+        md_unlink_open_file(file, inf) < 0)
+    {
+	printf("Cannot unlink file\n");
+	return FALSE;
+    }
+    mpos = 0;
+/*    printw(0, 0, "%s: %s", file, ctime(&sbuf2.st_mtime)); */
+/*
+    printw("%s: %s", file, ctime(&sbuf2.st_mtime));
+*/
+    clearok(stdscr,TRUE);
+    /*
+     * defeat multiple restarting from the same place
+     */
+#ifdef MASTER
+    if (!wizard)
+#endif
+	if (sbuf2.st_nlink != 1 || syml)
+	{
+	    endwin();
+	    printf("\nCannot restore from a linked file\n");
+	    return FALSE;
+	}
+
+    if (pstats.s_hpt <= 0)
+    {
+	endwin();
+	printf("\n\"He's dead, Jim\"\n");
+	return FALSE;
+    }
+
+	md_tstpresume();
+
+    strcpy(file_name, file);
+    clearok(curscr, TRUE);
+    srand(md_getpid());
+    msg("file name: %s", file);
+    playit();
+    /*NOTREACHED*/
+    return(0);
+}
+
+static int encerrno = 0;
+
+int
+encerror()
+{
+    return encerrno;
+}
+
+void
+encseterr(int err)
+{
+    encerrno = err;
+}
+
+int
+encclearerr()
+{
+    int n = encerrno;
+
+    encerrno = 0;
+
+    return(n);
+}
+
+/*
+ * encwrite:
+ *	Perform an encrypted write
+ */
+
+size_t
+encwrite(const char *start, size_t size, FILE *outf)
+{
+    const char *e1, *e2;
+    char fb;
+    int temp;
+    size_t o_size = size;
+    e1 = encstr;
+    e2 = statlist;
+    fb = 0;
+
+    if (encerrno) {
+	errno = encerrno;
+	return 0;
+    }
+
+    while(size)
+    {
+	if (putc(*start++ ^ *e1 ^ *e2 ^ fb, outf) == EOF)
+	{
+	    encerrno = errno;
+            break;
+	}
+
+	temp = *e1++;
+	fb = fb + ((char) (temp * *e2++));
+	if (*e1 == '\0')
+	    e1 = encstr;
+	if (*e2 == '\0')
+	    e2 = statlist;
+	size--;
+    }
+
+    return(o_size - size);
+}
+
+/*
+ * encread:
+ *	Perform an encrypted read
+ */
+size_t
+encread(char *start, size_t size, FILE *inf)
+{
+    const char *e1, *e2;
+    char fb;
+    int temp;
+    size_t read_size;
+    size_t items;
+    fb = 0;
+
+    if (encerrno) {
+	errno = encerrno;
+	return 0;
+    }
+
+    items = read_size = fread(start,1,size,inf);
+
+    e1 = encstr;
+    e2 = statlist;
+
+    while (read_size--)
+    {
+	*start++ ^= *e1 ^ *e2 ^ fb;
+	temp = *e1++;
+	fb = fb + (char)(temp * *e2++);
+	if (*e1 == '\0')
+	    e1 = encstr;
+	if (*e2 == '\0')
+	    e2 = statlist;
+    }
+
+    if (items != size)
+	encerrno = errno;
+
+    return(items);
+}
+
+/*
+ * read_scrore
+ *	Read in the score file
+ */
+void
+rd_score(SCORE *top_ten)
+{
+    char scoreline[100];
+    int i;
+
+    if (scoreboard == NULL)
+	return;
+
+    rewind(scoreboard); 
+
+    for(i = 0; i < numscores; i++)
+    {
+        encread(top_ten[i].sc_name, MAXSTR, scoreboard);
+	scoreline[0] = '\0';
+        encread(scoreline, 100, scoreboard);
+        (void) sscanf(scoreline, " %u %d %u %d %d %x \n",
+            &top_ten[i].sc_uid, &top_ten[i].sc_score,
+            &top_ten[i].sc_flags, &top_ten[i].sc_monster,
+            &top_ten[i].sc_level, &top_ten[i].sc_time);
+    }
+
+    rewind(scoreboard); 
+}
+
+/*
+ * write_scrore
+ *	Read in the score file
+ */
+void
+wr_score(SCORE *top_ten)
+{
+    char scoreline[100];
+    int i;
+
+    if (scoreboard == NULL)
+	return;
+
+    rewind(scoreboard);
+
+    for(i = 0; i < numscores; i++)
+    {
+          memset(scoreline,0,100);
+          encwrite(top_ten[i].sc_name, MAXSTR, scoreboard);
+          sprintf(scoreline, " %u %d %u %u %d %x \n",
+              top_ten[i].sc_uid, top_ten[i].sc_score,
+              top_ten[i].sc_flags, top_ten[i].sc_monster,
+              top_ten[i].sc_level, top_ten[i].sc_time);
+          encwrite(scoreline,100,scoreboard);
+    }
+
+    rewind(scoreboard); 
+}