static void savetrapchn(struct memfile *mf, struct trap *trap, struct level *lev) { struct trap *trap2; unsigned short tflags; int count = 0; mfmagic_set(mf, TRAPCHAIN_MAGIC); for (trap2 = trap; trap2; trap2 = trap2->ntrap) count++; mwrite32(mf, count); for (; trap; trap = trap->ntrap) { /* To distinguish traps from each other in tags, we use x/y/z coords */ mtag(mf, ledger_no(&lev->z) + ((int)trap->tx << 8) + ((int)trap->ty << 16), MTAG_TRAP); mwrite8(mf, trap->tx); mwrite8(mf, trap->ty); mwrite8(mf, trap->dst.dnum); mwrite8(mf, trap->dst.dlevel); mwrite8(mf, trap->launch.x); mwrite8(mf, trap->launch.y); tflags = (trap->ttyp << 11) | (trap->tseen << 10) | (trap->once << 9) | (trap->madeby_u << 8); mwrite16(mf, tflags); mwrite16(mf, trap->vl.v_launch_otyp); } }
/** * save_regions : */ void save_regions(struct memfile *mf, struct level *lev) { int i, j; unsigned len1, len2; struct region *r; mfmagic_set(mf, REGION_MAGIC); mtag(mf, ledger_no(&lev->z), MTAG_REGION); mwrite32(mf, save_encode_32(moves, moves, moves)); /* timestamp */ mwrite32(mf, lev->n_regions); /* Note: level regions don't have ID numbers, so we can't tag individual regions; instead, diff efficiency depends on the fact that regions tend to stay in the order and are typically inserted or deleted near the end of the list */ for (i = 0; i < lev->n_regions; i++) { r = lev->regions[i]; save_rect(mf, r->bounding_box); mwrite32(mf, r->attach_2_m); mwrite32(mf, r->effect_id); mwrite32(mf, r->arg); mwrite16(mf, r->nrects); for (j = 0; j < r->nrects; j++) save_rect(mf, r->rects[j]); mwrite16(mf, r->ttl); mwrite16(mf, r->expire_f); mwrite16(mf, r->can_enter_f); mwrite16(mf, r->enter_f); mwrite16(mf, r->can_leave_f); mwrite16(mf, r->leave_f); mwrite16(mf, r->inside_f); mwrite16(mf, r->n_monst); mwrite8(mf, r->player_flags); mwrite8(mf, r->attach_2_u); mwrite8(mf, r->visible); for (j = 0; j < r->n_monst; j++) mwrite32(mf, r->monsters[j]); len1 = r->enter_msg ? strlen(r->enter_msg) + 1 : 0; mwrite16(mf, len1); len2 = r->leave_msg ? strlen(r->leave_msg) + 1 : 0; mwrite16(mf, len2); if (len1 > 0) mwrite(mf, r->enter_msg, len1); if (len2 > 0) mwrite(mf, r->leave_msg, len2); } }
/* * save_rooms : Save all the rooms on disk! */ void save_rooms(struct memfile *mf, struct level *lev) { short i; mfmagic_set(mf, ROOMS_MAGIC); /* "RDAT" */ mtag(mf, ledger_no(&lev->z), MTAG_ROOMS); /* First, write the number of rooms */ mwrite32(mf, lev->nroom); for (i = 0; i < lev->nroom; i++) save_room(mf, &lev->rooms[i]); }
void save_obj(struct memfile *mf, struct obj *obj) { unsigned int oflags; oflags = (obj->cursed << 31) | (obj->blessed << 30) | (obj->unpaid << 29) | (obj->no_charge << 28) | (obj->known << 27) | (obj->dknown << 26) | (obj->bknown << 25) | (obj->rknown << 24) | (obj->oeroded << 22) | (obj->oeroded2 << 20) | (obj->oerodeproof << 19) | (obj->olocked << 18) | (obj->obroken << 17) | (obj->otrapped << 16) | (obj->recharged << 13) | (obj->lamplit << 12) | (obj->greased << 11) | (obj->oattached << 9) | (obj->in_use << 8) | (obj->was_thrown << 7) | (obj->bypass << 6); mfmagic_set(mf, OBJ_MAGIC); mwrite32(mf, obj->onamelth); mwrite32(mf, obj->o_id); mwrite32(mf, obj->owt); mwrite32(mf, obj->quan); mwrite32(mf, obj->corpsenm); mwrite32(mf, obj->oeaten); mwrite32(mf, obj->age); mwrite32(mf, obj->owornmask); mwrite32(mf, oflags); mwrite16(mf, obj->otyp); mwrite8(mf, obj->ox); mwrite8(mf, obj->oy); mwrite8(mf, obj->spe); mwrite8(mf, obj->oclass); mwrite8(mf, obj->invlet); mwrite8(mf, obj->oartifact); mwrite8(mf, obj->where); mwrite8(mf, obj->timed); /* no need to save the value of the cobj pointer, but we will need to know * if there is something in here that needs to be restored */ mwrite8(mf, obj->cobj ? 1 : 0); if (obj->onamelth) mwrite(mf, ONAME(obj), obj->onamelth); if (obj->oattached == OATTACHED_MONST) save_mon(mf, (struct monst*)obj->oextra); else if (obj->oattached == OATTACHED_M_ID) mwrite32(mf, *(unsigned int*)obj->oextra); }
void save_history(struct memfile *mf) { int i, len; mfmagic_set(mf, HISTORY_MAGIC); mtag(mf, 0, MTAG_HISTORY); mwrite32(mf, histcount); /* don't need tags for individual history events, because they're always added at the end of the list */ for (i = 0; i < histcount; i++) { mwrite32(mf, histevents[i].when); mwrite32(mf, histevents[i].hidden); len = strlen(histevents[i].what) + 1; mwrite32(mf, len); mwrite(mf, histevents[i].what, len); } }
/* save all the fruit names and ID's; this is used only in saving whole games * (not levels) and in saving bones levels. When saving a bones level, * we only want to save the fruits which exist on the bones level; the bones * level routine marks nonexistent fruits by making the fid negative. */ void savefruitchn(struct memfile *mf) { struct fruit *f1; unsigned int count = 0; mfmagic_set(mf, FRUITCHAIN_MAGIC); for (f1 = ffruit; f1; f1 = f1->nextf) if (f1->fid >= 0) count++; mwrite32(mf, count); for (f1 = ffruit; f1; f1 = f1->nextf) { if (f1->fid >= 0) { mwrite(mf, f1->fname, sizeof(f1->fname)); mwrite32(mf, f1->fid); } } }
static void saveobjchn(struct memfile *mf, struct obj *otmp) { int count = 0; struct obj *otmp2; mfmagic_set(mf, OBJCHAIN_MAGIC); for (otmp2 = otmp; otmp2; otmp2 = otmp2->nobj) count++; mwrite32(mf, count); while (otmp) { save_obj(mf, otmp); if (Has_contents(otmp)) saveobjchn(mf, otmp->cobj); otmp = otmp->nobj; } }
static void savemonchn(struct memfile *mf, struct monst *mtmp) { struct monst *mtmp2; unsigned int count = 0; mfmagic_set(mf, MONCHAIN_MAGIC); for (mtmp2 = mtmp; mtmp2; mtmp2 = mtmp2->nmon) count++; mwrite32(mf, count); while (mtmp) { mtmp2 = mtmp->nmon; save_mon(mf, mtmp); if (mtmp->minvent) saveobjchn(mf, mtmp->minvent); mtmp = mtmp2; } }
static void savegamestate(struct memfile *mf) { unsigned book_id; mtag(mf, 0, MTAG_GAMESTATE); mfmagic_set(mf, STATE_MAGIC); /* must come before migrating_objs and migrating_mons are freed */ save_timers(mf, level, RANGE_GLOBAL); save_light_sources(mf, level, RANGE_GLOBAL); saveobjchn(mf, invent); savemonchn(mf, migrating_mons); save_mvitals(mf); save_quest_status(mf); save_spellbook(mf); save_artifacts(mf); save_oracles(mf); mwrite(mf, pl_character, sizeof pl_character); mwrite(mf, pl_fruit, sizeof pl_fruit); mwrite32(mf, current_fruit); savefruitchn(mf); savenames(mf); save_waterlevel(mf); mwrite32(mf, lastinvnr); save_mt_state(mf); save_track(mf); save_food(mf); save_steal(mf); save_dig_status(mf); book_id = book ? book->o_id : 0; mwrite32(mf, book_id); mwrite32(mf, stetho_last_used_move); mwrite32(mf, stetho_last_used_movement); mwrite32(mf, multi); save_rndmonst_state(mf); save_history(mf); }
static void savetrapchn(struct memfile *mf, struct trap *trap) { struct trap *trap2; unsigned short tflags; int count = 0; mfmagic_set(mf, TRAPCHAIN_MAGIC); for (trap2 = trap; trap2; trap2 = trap2->ntrap) count++; mwrite32(mf, count); for (; trap; trap = trap->ntrap) { mwrite8(mf, trap->tx); mwrite8(mf, trap->ty); mwrite8(mf, trap->dst.dnum); mwrite8(mf, trap->dst.dlevel); mwrite8(mf, trap->launch.x); mwrite8(mf, trap->launch.y); tflags = (trap->ttyp << 11) | (trap->tseen << 10) | (trap->once << 9) | (trap->madeby_u << 8); mwrite16(mf, tflags); mwrite16(mf, trap->vl.v_launch_otyp); } }
void savelev(struct memfile *mf, xchar levnum) { int x, y; unsigned int lflags; struct level *lev = levels[levnum]; if (iflags.purge_monsters) { /* purge any dead monsters (necessary if we're starting * a panic save rather than a normal one, or sometimes * when changing levels without taking time -- e.g. * create statue trap then immediately level teleport) */ dmonsfree(lev); } mfmagic_set(mf, LEVEL_MAGIC); mwrite8(mf, lev->z.dnum); mwrite8(mf, lev->z.dlevel); mwrite(mf, lev->levname, sizeof(lev->levname)); for (x = 0; x < COLNO; x++) for (y = 0; y < ROWNO; y++) save_location(mf, &lev->locations[x][y]); mwrite32(mf, lev->lastmoves); mwrite(mf, &lev->upstair, sizeof(stairway)); mwrite(mf, &lev->dnstair, sizeof(stairway)); mwrite(mf, &lev->upladder, sizeof(stairway)); mwrite(mf, &lev->dnladder, sizeof(stairway)); mwrite(mf, &lev->sstairs, sizeof(stairway)); mwrite(mf, &lev->updest, sizeof(dest_area)); mwrite(mf, &lev->dndest, sizeof(dest_area)); mwrite8(mf, lev->flags.nfountains); mwrite8(mf, lev->flags.nsinks); lflags = (lev->flags.has_shop << 31) | (lev->flags.has_vault << 30) | (lev->flags.has_zoo << 29) | (lev->flags.has_court << 28) | (lev->flags.has_morgue << 27) | (lev->flags.has_beehive << 26) | (lev->flags.has_barracks << 25) | (lev->flags.has_temple << 24) | (lev->flags.has_swamp << 23) | (lev->flags.noteleport << 22) | (lev->flags.hardfloor << 21) | (lev->flags.nommap << 20) | (lev->flags.hero_memory << 19) | (lev->flags.shortsighted << 18) | (lev->flags.graveyard << 17) | (lev->flags.is_maze_lev << 16) | (lev->flags.is_cavernous_lev << 15) | (lev->flags.arboreal << 14) | (lev->flags.forgotten << 13); mwrite32(mf, lflags); mwrite(mf, lev->doors, sizeof(lev->doors)); save_rooms(mf, lev); /* no dynamic memory to reclaim */ /* must be saved before mons, objs, and buried objs */ save_timers(mf, lev, RANGE_LEVEL); save_light_sources(mf, lev, RANGE_LEVEL); savemonchn(mf, lev->monlist); save_worm(mf, lev); /* save worm information */ savetrapchn(mf, lev->lev_traps); saveobjchn(mf, lev->objlist); saveobjchn(mf, lev->buriedobjlist); saveobjchn(mf, lev->billobjs); save_engravings(mf, lev); savedamage(mf, lev); save_regions(mf, lev); }