commit - 8852ffaf302e1b19e8146f276c366dd75d701a4d
commit + fcb97c9fa11d1a3cd4f5e84b12a9685d44903dc1
blob - 92b8f27997fd3c7a32f5a32ec18c69b91e1c2f6c
blob + 3f43a18ae608cbd8c378bb355f116f4177070c0d
--- Makefile
+++ Makefile
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
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
}
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');
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
+#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;
+}