changeset 296:000b1c5b8d63

UltraRogue: fix inventory collision after save and restore. Inventory letters are based on "identifiers" stored in objects' o_ident field. Identifiers are allocated by get_ident(), which keeps a list of objects that have them, to avoid giving the same identifier to multiple objects. The list is not stored in the savefile, so after restore, get_ident() was not aware of existing identifiers. This resulted in picked-up objects having the same inventory letters as objects restored from the file. The restore code now adds all objects with identifiers to the list.
author John "Elwin" Edwards
date Mon, 15 Jan 2018 20:20:35 -0500
parents 1e1c81fbb533
children 317166b49d8a
files urogue/state.c
diffstat 1 files changed, 44 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/urogue/state.c	Fri Jan 12 18:02:39 2018 -0500
+++ b/urogue/state.c	Mon Jan 15 20:20:35 2018 -0500
@@ -415,6 +415,45 @@
         ur_write_object_stack(savef, o->next_obj);
 }
 
+/*
+ * Puts objects with identifiers into the global ident_list, keeping it sorted
+ * by type and identifier.
+ */
+void
+add_to_ident(struct object *o)
+{
+    extern linked_list *ident_list;
+    linked_list *obj_ll;
+    linked_list *list_p, *prev_p = NULL;
+    struct object *list_o;
+
+    obj_ll = new_list();
+    obj_ll->data.obj = o;
+
+    for (list_p = ident_list; list_p != NULL; list_p = next(list_p))
+    {
+        list_o = list_p->data.obj;
+        if (list_o->o_type == o->o_type)
+        {
+            if (list_o->o_ident > o->o_ident)
+            {
+                prev_p = list_p->l_prev;
+                break;
+            }
+            else if (next(list_p) && 
+                     next(list_p)->data.obj->o_type != o->o_type)
+            {
+                prev_p = list_p;
+                break;
+            }
+        }
+        if (!next(list_p))
+            prev_p = list_p;
+    }
+    _attach_after(&ident_list, prev_p, obj_ll);
+    return;
+}
+
 struct object *
 ur_read_object(FILE *savef)
 {
@@ -454,6 +493,11 @@
 
     other = ur_read_int(savef);
 
+    if (o->o_ident != 0) {
+        /* The object needs to be placed in the identifiers list. */
+        add_to_ident(o);
+    }
+
     if (other & 1)
         o->o_bag = ur_read_bag(savef);
     if (other & 2)