comparison 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
comparison
equal deleted inserted replaced
295:1e1c81fbb533 296:000b1c5b8d63
413 ur_write_bag(savef,o->o_bag); 413 ur_write_bag(savef,o->o_bag);
414 if (o->next_obj && (o->next_obj->l_prev == NULL) ) 414 if (o->next_obj && (o->next_obj->l_prev == NULL) )
415 ur_write_object_stack(savef, o->next_obj); 415 ur_write_object_stack(savef, o->next_obj);
416 } 416 }
417 417
418 /*
419 * Puts objects with identifiers into the global ident_list, keeping it sorted
420 * by type and identifier.
421 */
422 void
423 add_to_ident(struct object *o)
424 {
425 extern linked_list *ident_list;
426 linked_list *obj_ll;
427 linked_list *list_p, *prev_p = NULL;
428 struct object *list_o;
429
430 obj_ll = new_list();
431 obj_ll->data.obj = o;
432
433 for (list_p = ident_list; list_p != NULL; list_p = next(list_p))
434 {
435 list_o = list_p->data.obj;
436 if (list_o->o_type == o->o_type)
437 {
438 if (list_o->o_ident > o->o_ident)
439 {
440 prev_p = list_p->l_prev;
441 break;
442 }
443 else if (next(list_p) &&
444 next(list_p)->data.obj->o_type != o->o_type)
445 {
446 prev_p = list_p;
447 break;
448 }
449 }
450 if (!next(list_p))
451 prev_p = list_p;
452 }
453 _attach_after(&ident_list, prev_p, obj_ll);
454 return;
455 }
456
418 struct object * 457 struct object *
419 ur_read_object(FILE *savef) 458 ur_read_object(FILE *savef)
420 { 459 {
421 struct object *o; 460 struct object *o;
422 long id; 461 long id;
451 o->o_launch = ur_read_char(savef); 490 o->o_launch = ur_read_char(savef);
452 ur_read(savef, &o->o_mark[0], MARKLEN); 491 ur_read(savef, &o->o_mark[0], MARKLEN);
453 o->o_worth = ur_read_long(savef); 492 o->o_worth = ur_read_long(savef);
454 493
455 other = ur_read_int(savef); 494 other = ur_read_int(savef);
495
496 if (o->o_ident != 0) {
497 /* The object needs to be placed in the identifiers list. */
498 add_to_ident(o);
499 }
456 500
457 if (other & 1) 501 if (other & 1)
458 o->o_bag = ur_read_bag(savef); 502 o->o_bag = ur_read_bag(savef);
459 if (other & 2) 503 if (other & 2)
460 o->next_obj = ur_read_object_stack(savef); 504 o->next_obj = ur_read_object_stack(savef);