#include #include #include #include #include #include #include "defs.h" #include "flag.h" #include "io.h" #include "lf.h" #include "map.h" #include "move.h" #include "nexus.h" #include "objects.h" #include "save.h" extern long curtime; extern lifeform_t *player; extern map_t *firstmap; extern knowledge_t *knowledge; extern enum GAMEMODE gamemode; int loadall(void) { DIR *dir; struct dirent *ent; gamemode = GM_LOADING; dir = opendir(MAPDIR); if (!dir) { dblog("Could not open map directory '%s'",MAPDIR); return B_TRUE; } // for each map file in directory while ((ent = readdir(dir)) != NULL) { char *p; // ie. start of 4 char prefix p = ent->d_name + strlen(ent->d_name) - 4; // load this map if (!strcmp(p, ".map") ) { if (!loadmap(ent->d_name)) { printf("Error loading map from file '%s'",ent->d_name); exit(1); } } } closedir(dir); loadsavegame(); gamemode = GM_LOADED; return B_FALSE; } int loadflagpile(FILE *f, flagpile_t *fp) { flag_t tempflag; flag_t *fl; char buf[BUFLEN]; int rv; int db = B_TRUE; rv = fscanf(f, "%d,%d,%d,%d,%d,%d,%d,%ld\n", &tempflag.id, &tempflag.nvals, &tempflag.val[0], &tempflag.val[1], &tempflag.val[2],&tempflag.lifetime, &tempflag.known,&tempflag.obfrom); while (tempflag.id != -1) { dblog("got flag id=%d\n",tempflag.id); // get flag text fgets(buf, BUFLEN, f); buf[strlen(buf)-1] = '\0'; // strip newline fl = addflag_real(fp, tempflag.id, tempflag.val[0], tempflag.val[1], tempflag.val[2], strcmp(buf, "^^^") ? buf : NULL, tempflag.lifetime, tempflag.known, tempflag.obfrom); if (db) { dblog("--> added flag id=%d. v0=%d, v1=%d, v2=%d, text=%s, lifetime=%d, known=%d, obfrom=%ld\n",fl->id, fl->val[0], fl->val[1], fl->val[2], fl->text ? fl->text : "(null)", fl->lifetime, fl->known,fl->obfrom); } // load next one rv = fscanf(f, "%d,%d,%d,%d,%d,%d,%d,%ld\n", &tempflag.id, &tempflag.nvals, &tempflag.val[0], &tempflag.val[1], &tempflag.val[2],&tempflag.lifetime, &tempflag.known,&tempflag.obfrom); //dblog("fscanf returned %d\n",rv); } return B_FALSE; } int loadknowledge(FILE *f) { int db = B_FALSE; char buf[BUFLEN]; int otid,known; char hiddenname[BUFLEN]; if (db) dblog("--> Loading knowledge...\n"); fscanf(f, "startknowledge\n"); fgets(buf, BUFLEN, f); buf[strlen(buf)-1] = '\0'; // strip newline while (strcmp(buf, "endknowledge")) { sscanf(buf, "%d^%s^%d",&otid, hiddenname, &known); addknowledge(otid, hiddenname, known); // get next line fgets(buf, BUFLEN, f); buf[strlen(buf)-1] = '\0'; // strip newline } return B_FALSE; } int loadvars(FILE *f) { int db = B_FALSE; if (db) dblog("--> Loading knowledge...\n"); fscanf(f, "startvars\n"); fscanf(f, "curtime:%ld\n",&curtime); fscanf(f, "endvars\n"); return B_FALSE; } // load and allocate one lifeform from given file lifeform_t *loadlf(FILE *f, cell_t *where) { lifeform_t *l; int lfid, lfraceid; long obid; int rv; int i; char buf[BUFLEN]; int obcount; int mapid; map_t *m; int x,y,level; int db = B_TRUE; if (db) dblog("--> Loading lifeform...\n"); fscanf(f, "startlf\n"); fscanf(f, "lfid: %d\n",&lfid); fscanf(f, "race: %d\n",&lfraceid); fscanf(f, "map: %d\n",&mapid); fscanf(f, "pos: %d,%d\n",&x, &y); fscanf(f, "level: %d\n",&level); // find the map m = findmap(mapid); if (!m) { dblog("ERROR loading lf id %d: can't find map id %d\n",lfid,mapid); exit(1); } if (where == NULL) { where = getcellat(m, x, y); } if (!m) { dblog("ERROR loading lf id %d: can't find cell at %d,%d on map id %d\n",lfid,x,y,mapid); exit(1); } l = addlf(where, lfraceid,level); l->id = lfid; l->x = x; l->y = y; // load rest of this lf fscanf(f, "str: %d/%d\n",&l->att[A_STR],&l->baseatt[A_STR]); fscanf(f, "dex: %d/%d\n",&l->att[A_DEX],&l->baseatt[A_DEX]); fscanf(f, "int: %d/%d\n",&l->att[A_IQ],&l->baseatt[A_IQ]); fscanf(f, "xp: %ld\n",&l->xp); fscanf(f, "skp: %d\n",&l->skillpoints); fscanf(f, "contr: %d\n",&l->controller); fscanf(f, "hp: %d/%d\n",&l->hp, &l->maxhp); fscanf(f, "mp: %d/%d\n",&l->mp, &l->maxmp); fscanf(f, "alive: %d\n",&l->alive); fscanf(f, "lastdamtype: %d\n",(int *)&l->lastdamtype); fgets(buf, BUFLEN, f); // lastdam buf[strlen(buf)-1] = '\0'; // strip newline l->lastdam = strdup(buf + 9); // after 'lastdam: ' fscanf(f, "timespent: %d\n",&l->timespent); fscanf(f, "sorted: %d\n",&l->sorted); fscanf(f, "polyrevert: %d\n",&l->polyrevert); fscanf(f, "forgettimer: %f\n",&l->forgettimer); if (db) dblog("--> Got hp=%d/%d. timespend=%d. sorted=%d. Now loading flags.",l->hp,l->maxhp,l->timespent,l->sorted); // lf flags loadflagpile(f, l->flags); if (db) dblog("--> now loading objects"); // load object list obcount = 0; obid = 9999; // for testing rv = fscanf(f, "ob:%ld\n",&obid); while (obid != -1) { if (db) dblog("--> Load ob id %d into list...",obid); l->pack->oblist[obcount] = obid; obcount++; fscanf(f, "ob:%ld\n",&obid); } // terminate with -1s! for (i = obcount ; i < MAXPILEOBS; i++) { l->pack->oblist[i] = -1; } if (db) dblog("--> Finished oblist. Found %d objects.",obcount); // now load load object defs for this player! fscanf(f, "obdefs\n"); for (i = 0; i < obcount; i++) { long thisid; if (db) dblog("--> Creating ob #%d for lf.",i); //if (db) dblog("-----> ob %d/%d...\n",i+1,obcount); if (loadob(f, l->pack, &thisid)) { dblog("Error - can't create object %d/%d!\n",i+1,obcount); exit(1); } if (db) dblog("----> done (id=%ld)",thisid); } // is this the player? if (l->controller == C_PLAYER) { player = l; } sortlf(l->cell->map, l); return l; } map_t *loadmap(char *basefile) { FILE *f; char filename[BUFLEN]; char buf[BUFLEN]; int obcount; int i; int x,y; int db = B_TRUE; lifeform_t *l; object_t *o; map_t *m; cell_t *dummycell; if (db) dblog("Loading map from %s...",basefile); sprintf(filename, "%s/%s",MAPDIR,basefile); f = fopen(filename, "rt"); // create map m = addmap(); dummycell = malloc(sizeof(cell_t)); dummycell->obpile = addobpile(NULL, dummycell); dummycell->map = m; dummycell->type = (celltype_t *)DUMMYCELLTYPE; // for debugging if (!m) { dblog("Error creating map while loading file '%s'",filename); return NULL; } // load map info if (db) dblog("--> Loading map info...\n"); fscanf(f, "id:%d\n",&m->id); // map id fscanf(f, "depth:%d\n",&m->depth); // map depth fgets(buf, BUFLEN, f); // map name buf[strlen(buf)-1] = '\0'; // strip newline m->name = strdup(buf + 5); // after 'name:' fscanf(f, "habitat:%d\n",(int *)&m->habitat); // habitat fscanf(f, "seed:%d\n",&m->seed); // seed fscanf(f, "dims:%d,%d\n",&m->w, &m->h); // map dimensons fscanf(f, "nextmaps:\n"); for (i = 0; i < MAXDIR_ORTH; i++) { fscanf(f, "%d\n",&m->nextmap[i]); // map dimensons } if (db) dblog("--> Finished map info. name='%s', dims=%d x %d\n",m->name, m->w, m->h); fscanf(f, "beingcreated:%d\n",&m->beingcreated); fscanf(f, "id:%d\n",&m->id); // map id // load lifeforms if (db) dblog("--> Loading lifeforms...\n"); fscanf(f, "lifeforms:\n"); fscanf(f, "%s\n",buf); while (!strcmp(buf ,"startlf")) { loadlf(f, dummycell); // check for more lifeforms... fscanf(f, "%s\n",buf); } // load cells if (db) dblog("--> Loading map cells...\n"); fscanf(f, "cells:\n"); for (y = 0; y < m->h; y++) { for (x = 0; x < m->w; x++) { cell_t *c; celltype_t *ct; int celltypeid; long obid; //if (db) dblog("cell %d,%d...",x,y); // allocate this cell c = addcell(m, x, y); /* c = m->cell[y * m->w + x]; c->map = m; c->obpile = addobpile(NULL, c); c->lf = NULL; c->x = x; c->y = y; c->roomid = -1; */ // cell info fscanf(f, "%d,%d,%d,%d,%d,%d,%d\n", &c->roomid, &celltypeid, &c->known, &c->visited, &c->lit, &c->origlit, &c->littimer); ct = findcelltype(celltypeid); if (ct) { c->type = ct; } else { dblog("ERROR loading map cells - can't find celltype id %ld\n",celltypeid); exit(1); } // cell objects obcount = 0; fscanf(f, "ob:%ld\n",&obid); while (obid != -1) { c->obpile->oblist[obcount] = obid; obcount++; fscanf(f, "ob:%ld\n",&obid); } // terminate with -1s! for (i = obcount ; i < MAXPILEOBS; i++) { c->obpile->oblist[i] = -1; } } } // load object definitions if (db) dblog("--> Loading object definitions for map obs...\n"); fscanf(f, "MAPOBS:%d\n",&obcount); // how many obs? // create all objects in a dummy cell for (i = 0; i < obcount; i++) { long thisid; if (db) dblog("-----> loading into dummycell: mapob %d/%d...\n",i+1,obcount); if (loadob(f, dummycell->obpile, &thisid)) { dblog("Error - can't create object %d/%d!\n",i+1,obcount); exit(1); } if (db) dblog("----------> got obid %ld\n",thisid); // check! if (!hasobid(dummycell->obpile, thisid)) { dblog("Error: after loading obid %ld, can't find it in dummycell!\n",thisid); exit(1); } } // hand out the objects to lifeforms... /* for (l = m->lf ; l ; l = l->next) { int curob = 0; long obid; obid = l->pack->oblist[curob]; while (obid != -1) { int found = B_FALSE; // find this ob id in the dummycell for (o = dummycell->obpile->first ; o ; o = nexto) { nexto = o->next; if (o->id == obid) { relinkob(o, l->pack); found = B_TRUE; break; } } if (!found) { dblog("Error loading obs - lf %d should have obid %ld but can't find it in dummycell.\n",l->id, obid); exit(1); } // next one curob++; obid = l->pack->oblist[curob]; } // clear the oblist for (i = 0; i < MAXPILEOBS; i++) { l->pack->oblist[i] = -1; } } */ // hand out objects to cells for (y = 0; y < m->h; y++) { for (x = 0; x < m->w; x++) { cell_t *c; long obid; int curob = 0; c = m->cell[y * m->w + x]; obid = c->obpile->oblist[curob]; dblog("Handing out objects to cell %d,%d\n",x,y); while (obid != -1) { dblog(" Looking for obid %ld in dummycell...",obid); // find this ob id in the dummycell o = hasobid(dummycell->obpile, obid); if (o) { dblog(" Got it."); relinkob(o, c->obpile); } else { dblog(" Error loading obs - cell %d,%d should have obid %ld but can't find it.\n",x,y, obid); exit(1); } // next one curob++; obid = c->obpile->oblist[curob]; } // clear the oblist for (i = 0; i < MAXPILEOBS; i++) { c->obpile->oblist[i] = -1; } } } fclose(f); // move lifeforms to their proper locations for (l = m->lf ; l ; l = l->next) { cell_t *c; c = getcellat(m, l->x, l->y); if (!c) { dblog("Error loading map - Can't find cell at %d,%d to place lifeform id %d.\n", l->x, l->y, l->id); exit(1); } movelf(l, c); //dblog("Moving lf %d to %d,%d\n",l->id, l->x, l->y); } free(dummycell); // successful load - kill the map now unlink(filename); return m; } int loadob(FILE *f, obpile_t *op, long *id) { objecttype_t *ot; object_t *o; material_t *mat; long obid; int otid,matid; char buf[BUFLEN]; int db = B_TRUE; fscanf(f, "id:%ld\n",&obid); fscanf(f, "type:%d\n",&otid); if (db) dblog("... loading object id %ld",obid); if (id) { *id = obid; } ot = findot(otid); if (!ot) { dblog("ERROR loading objects - can't find obtype id %d (obj id %ld)\n",otid,obid); return B_TRUE; } // create the object o = addobject(op, ot->name, B_NOSTACK); // no stacking! // overwrite ob parameters o->id = obid; fscanf(f, "material:%d\n",&matid); mat = findmaterial(matid); if (!mat) { dblog("ERROR loading objects - can't find material %d\n",matid); return B_TRUE; } o->material = mat; fscanf(f, "weight:%f\n",&o->weight); fgets(buf, BUFLEN, f); // inscription buf[strlen(buf)-1] = '\0'; // strip newline o->inscription = strdup(buf + 6); // after 'inscr:' if (!strcmp(o->inscription, "^^^")) { // ie. if equal to ^^^... free(o->inscription); o->inscription = NULL; } fscanf(f, "letter:%c\n",&o->letter); fscanf(f, "bless:%d\n",&o->blessed); fscanf(f, "blessknown:%d\n",&o->blessknown); fscanf(f, "amt:%d\n",&o->amt); fscanf(f, "birthtime:%ld\n",&o->birthtime); // now remove ALL obejct flags (which were inherited // from the obtype during addobject() ). these will be // loaded in instead. while (o->flags->first) { killflag(o->flags->first); } fscanf(f, "flags:\n"); dblog("About to start loading object flags..."); loadflagpile(f, o->flags); fscanf(f, "endob\n"); return B_FALSE; } int loadsavegame(void) { DIR *dir; struct dirent *ent; char filename[BUFLEN]; FILE *f; // now see if there is a savegame... dir = opendir(SAVEDIR); if (!dir) { dblog("Could not open savegame directory '%s'",SAVEDIR); return B_TRUE; } ent = readdir(dir); while ((ent = readdir(dir)) != NULL) { char *p; // ie. start of 4 char prefix p = ent->d_name + strlen(ent->d_name) - 4; // load this savegame if (!strcmp(p, ".sav") ) { sprintf(filename, "%s/%s",SAVEDIR,ent->d_name); dblog("Trying to load from %s\n",filename); f = fopen(filename, "rt"); if (!f) { printf("Error opening savegame file '%s'",ent->d_name); exit(1); } if (!loadlf(f, NULL)) { printf("Error loading savegame from file '%s'",ent->d_name); exit(1); } if (loadknowledge(f)) { printf("Error loading knowledge from file '%s'",ent->d_name); exit(1); } if (loadvars(f)) { printf("Error loading game variables from file '%s'",ent->d_name); exit(1); } fclose(f); // successful load - kill the savegame now unlink(filename); break; } } closedir(dir); return B_FALSE; } int savevars(FILE *f) { int db = B_FALSE; if (db) dblog("--> Saving knowledge...\n"); fprintf(f, "startvars\n"); fprintf(f, "curtime:%ld\n",curtime); fprintf(f, "endvars\n"); return B_FALSE; } int saveflagpile(FILE *f, flagpile_t *fp) { flag_t *fl; fprintf(f, "flags:\n"); for (fl = fp->first ; fl ; fl = fl->next) { fprintf(f, "%d,%d,%d,%d,%d,%d,%d,%ld\n", fl->id, fl->nvals, fl->val[0], fl->val[1], fl->val[2],fl->lifetime,fl->known,fl->obfrom); if (!fl->text || !strcmp(fl->text, "")) { fprintf(f, "%s\n","^^^"); } else { fprintf(f, "%s\n",fl->text); } } fprintf(f, "-1,-1,-1,-1,-1,-1,-1,-1\n"); return B_FALSE; } int saveknowledge(FILE *f) { int db = B_FALSE; knowledge_t *k; if (db) dblog("--> Saving knowledge...\n"); fprintf(f, "startknowledge\n"); for (k = knowledge; k ; k = k->next) { fprintf(f, "%d^%s^%d\n",k->id, k->hiddenname, k->known); } fprintf(f, "endknowledge\n"); return B_FALSE; } int savelf(FILE *f, lifeform_t *l) { object_t *o; int obcount = 0; // save this lf fprintf(f, "startlf\n"); fprintf(f, "lfid: %d\n",l->id); fprintf(f, "race: %d\n",l->race->id); fprintf(f, "map: %d\n",l->cell->map->id); fprintf(f, "pos: %d,%d\n",l->cell->x, l->cell->y); fprintf(f, "level: %d\n",l->level); // liefform will be created after loading the above. fprintf(f, "str: %d/%d\n",l->att[A_STR],l->baseatt[A_STR]); fprintf(f, "dex: %d/%d\n",l->att[A_DEX],l->baseatt[A_DEX]); fprintf(f, "int: %d/%d\n",l->att[A_IQ],l->baseatt[A_IQ]); fprintf(f, "xp: %ld\n",l->xp); fprintf(f, "skp: %d\n",l->skillpoints); fprintf(f, "contr: %d\n",l->controller); fprintf(f, "hp: %d/%d\n",l->hp, l->maxhp); fprintf(f, "mp: %d/%d\n",l->mp, l->maxmp); fprintf(f, "alive: %d\n",l->alive); fprintf(f, "lastdamtype: %d\n",l->lastdamtype); fprintf(f, "lastdam: %s\n",l->lastdam); fprintf(f, "timespent: %d\n",l->timespent); fprintf(f, "sorted: %d\n",l->sorted); fprintf(f, "polyrevert: %d\n",l->polyrevert); fprintf(f, "forgettimer: %f\n",l->forgettimer); // lf flags saveflagpile(f, l->flags); // lifeform objects obcount = 0; for (o = l->pack->first ; o ; o = o->next) { fprintf(f, "ob:%ld\n",o->id); obcount++; } fprintf(f, "ob:-1\n"); fprintf(f, "obdefs\n"); // now save our object definitions for (o = l->pack->first ; o ; o = o->next) { saveob(f, o); } return B_FALSE; } int savegame(void) { map_t *m; FILE *f; char buf[BUFLEN]; int rv; for (m = firstmap; m ; m = m->next) { // save world rv = savemap(m); if (rv) { msg("Could not save map '%s'",m->name); return B_TRUE; } // save player + their objects sprintf(buf, "%s/game.sav",SAVEDIR); f = fopen(buf, "wt"); if (!f) { msg("Could not open save file!"); return B_TRUE; } savelf(f, player); saveknowledge(f); savevars(f); fclose(f); } return B_FALSE; } int savemap(map_t *m) { FILE *f; char filename[BUFLEN]; int i; object_t *o; lifeform_t *l; int x,y; int obcount = 0; // TODO: check that map dir exists sprintf(filename, "%s/map%d.map",MAPDIR, m->id); f = fopen(filename, "wt"); // save map info fprintf(f, "id:%d\n",m->id); // map id fprintf(f, "depth:%d\n",m->depth); // map depth fprintf(f, "name:%s\n",m->name); // map name fprintf(f, "habitat:%d\n",m->habitat); // habitat fprintf(f, "seed:%d\n",m->seed); // seed fprintf(f, "dims:%d,%d\n",m->w, m->h); // map dimensons fprintf(f, "nextmaps:\n"); for (i = 0; i < MAXDIR_ORTH; i++) { fprintf(f, "%d\n",m->nextmap[i] ); // map dimensons } fprintf(f, "beingcreated:%d\n",m->beingcreated); // save all non-player lifeforms (includes their objects) fprintf(f, "lifeforms:\n"); for (l = m->lf ; l ; l = l->next) { if (l->controller != C_PLAYER) { // don't save the player! savelf(f, l); } } fprintf(f, "endlifeforms\n"); // cells fprintf(f, "cells:\n"); for (y = 0; y < m->h; y++) { for (x = 0; x < m->w; x++) { cell_t *c; c = getcellat(m, x, y); // cell info fprintf(f, "%d,%d,%d,%d,%d,%d,%d\n", c->roomid, c->type->id, c->known, c->visited,c->lit,c->origlit,c->littimer); // cell objects for (o = c->obpile->first ; o ; o = o->next) { fprintf(f, "ob:%ld\n",o->id); obcount++; } fprintf(f, "ob:-1\n"); } } // save object definitions from map cells fprintf(f, "MAPOBS:%d\n",obcount); for (y = 0; y < m->h; y++) { for (x = 0; x < m->w; x++) { cell_t *c; c = getcellat(m, x, y); // cell objects for (o = c->obpile->first ; o ; o = o->next) { saveob(f, o); } } } fclose(f); return B_FALSE; } int saveob(FILE *f, object_t *o) { fprintf(f, "id:%ld\n",o->id); fprintf(f, "type:%d\n",o->type->id); fprintf(f, "material:%d\n",o->material->id); fprintf(f, "weight:%f\n",o->weight); fprintf(f, "inscr:%s\n",o->inscription ? o->inscription : "^^^"); fprintf(f, "letter:%c\n",o->letter); fprintf(f, "bless:%d\n",o->blessed); fprintf(f, "blessknown:%d\n",o->blessknown); fprintf(f, "amt:%d\n",o->amt); fprintf(f, "birthtime:%ld\n",o->birthtime); saveflagpile(f, o->flags); fprintf(f, "endob\n"); return B_FALSE; }