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.
This commit is contained in:
John "Elwin" Edwards 2018-01-15 20:20:35 -05:00
parent 82dca01969
commit 5e44d8334d

View file

@ -415,6 +415,45 @@ ur_write_object(FILE *savef, struct object *o)
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 @@ ur_read_object(FILE *savef)
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)