Commit Diff


commit - 8852ffaf302e1b19e8146f276c366dd75d701a4d
commit + fcb97c9fa11d1a3cd4f5e84b12a9685d44903dc1
blob - 92b8f27997fd3c7a32f5a32ec18c69b91e1c2f6c
blob + 3f43a18ae608cbd8c378bb355f116f4177070c0d
--- Makefile
+++ Makefile
@@ -6,7 +6,7 @@ LDFLAGS	= -lreadline
 
 all: adventure
 
-OBJ = match.o parseexec.o toggle.c inventory.o \
+OBJ = save.o match.o parseexec.o toggle.c inventory.o \
 	misc.o object.o io.o adventure.o
 
 # making every object depending on object.h may be too aggressive,
blob - 846be847d3726e9457eabed7f851477745194db2
blob + a73f572be254684609067d6ae2bd63721c78b64f
--- adventure.h
+++ adventure.h
@@ -75,4 +75,8 @@ const char	*toggle_backdoor(struct object*);
 const char	*toggle_box(struct object*);
 const char	*toggle_box_lock(struct object*);
 
+/* save.c */
+int		 save();
+int		 load();
+
 #endif
blob - 7024675111095183a845c5f5d7dd90c267278553
blob + 74bff1104b7812ad3022486c9820d356e422e1c8
--- parseexec.c
+++ parseexec.c
@@ -9,6 +9,23 @@ exec_quit(void)
 }
 
 int
+exec_load(void)
+{
+	if (load()) {
+		return exec_look_around();
+	} else {
+		return exec_quit();
+	}
+}
+
+int
+exec_save(void)
+{
+	save();
+	return 1;
+}
+
+int
 exec_no_match(void)
 {
 	struct param *par = param_by_letter('A');
@@ -161,6 +178,8 @@ parseexec(const char *input)
 	static const struct command commands[] = {
 		{ &exec_quit, "quit" },
 		{ &exec_quit, "bye" },
+		{ &exec_load, "load" },
+		{ &exec_save, "save" },
 		{ &exec_look_around, "look" },
 		{ &exec_look_around, "look around" },
 		{ &exec_look, "look at A?" },
blob - /dev/null
blob + 5497982265a69682d91bc1e49999a762ea68de72 (mode 644)
--- /dev/null
+++ save.c
@@ -0,0 +1,162 @@
+#include "adventure.h"
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <readline/readline.h>
+
+/* the last 32 bits are a version number to be increased on breaking changes.
+ */
+static const char magic[]
+	= { 0, 0, 0, 0, 'T', 'E', 'X', 'T', 'A', 'D', 'V', 0, 0, 0, 0 };
+
+#define MLEN sizeof(magic)
+
+/* Every object is serialized in a buffer with the following format:
+ *
+ *	| offset | location | weight | capacity | health |
+ *
+ * with each field 32 bits long, for a total of 160 bytes.  Each field is a
+ * SIGNED 32 bit integer.  The meaning of the fields is as follows:
+ *
+ * - offset : the current object, that is objs[offset]
+ * - location : the offset of the location, if NULL -1
+ * - weight, capacity, health : the propriety of the object.
+ *
+ * This should make cheating a little bit harder.
+ */
+
+int
+save(void)
+{
+	char *line;
+	FILE *f;
+	struct object *obj;
+
+	line = readline("Save to file: ");
+	if (!line || !*line) {
+		printf("Invalid filename\n");
+
+		if (line != NULL)
+			free(line);
+
+		return save();
+	}
+
+	/* b = binary mode, for windows compatibility I guess */
+	if ((f = fopen(line, "wb")) == NULL) {
+		printf("Cannot write file!\n");
+		return 0;
+	}
+
+	/* write magic header */
+	fwrite(magic, 1, MLEN, f);
+
+	/* write the objects */
+	for (obj = objs; obj < obj_end; ++obj) {
+		int32_t offset, location, weight, capacity, health;
+
+		offset = obj - objs;
+		if (obj->location == NULL)
+			location = -1;
+		else
+			location = obj->location - objs;
+		weight = obj->weight;
+		capacity = obj->capacity;
+		health = obj->health;
+
+		printf("saved: %d %d %d %d %d\n", offset, location, weight,
+			capacity, health);
+
+		fwrite(&offset, 4, 1, f);
+		fwrite(&location, 4, 1, f);
+		fwrite(&weight, 4, 1, f);
+		fwrite(&capacity, 4, 1, f);
+		fwrite(&health, 4, 1, f);
+	}
+
+	fclose(f);
+	free(line);
+	return 1;
+}
+
+int
+load(void)
+{
+	char *line, m[MLEN];
+	FILE *f;
+	ssize_t r;
+
+	line = readline("Load from file: ");
+	if (!line || !*line) {
+		printf("Invalid filename\n");
+
+		if (line != NULL)
+			free(line);
+
+		return load();
+	}
+
+	if ((f = fopen(line, "rb")) == NULL) {
+		printf("Cannot open file %s\n", line);
+		free(line);
+		return 0;
+	}
+
+	/* read the magic */
+	fread(m, MLEN, 1, f);
+	if (memcmp(m, magic, MLEN)) {
+		printf("Wrong magic in file, cannot load.\n");
+		goto err;
+	}
+
+	/* read all the objects */
+	while (1) {
+		int32_t offset, location, weight, capacity, health;
+
+		if ((r = fread(&offset, 1, 4, f)) != 4)
+			break;
+		if ((r = fread(&location, 1, 4, f)) != 4)
+			break;
+		if ((r = fread(&weight, 1, 4, f)) != 4)
+			break;
+		if ((r = fread(&capacity, 1, 4, f)) != 4)
+			break;
+		if ((r = fread(&health, 1, 4, f)) != 4)
+			break;
+
+		if (objs + offset >= obj_end)
+			goto err;
+
+		if (location == -1)
+			objs[offset].location = NULL;
+		else {
+			if (objs + location >= obj_end)
+				goto err;
+
+			objs[offset].location = objs + location;
+		}
+
+		objs[offset].weight = weight;
+		objs[offset].capacity = capacity;
+		objs[offset].health = health;
+	}
+
+	if (ferror(f)) {
+		perror(line);
+		goto err;
+	}
+
+	printf("OK!\n");
+	fclose(f);
+	free(line);
+	return 1;
+
+err:
+	printf("Error in loading file!\n");
+	fclose(f);
+	free(line);
+	return 0;
+}