Mercurial > hg > early-roguelike
diff urogue/state.c @ 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 | ebf49a933e51 |
children | 0250220d8cdd |
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)