#include #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" #include "text.h" #include "vault.h" extern long curtime; extern lifeform_t *player; extern map_t *firstmap; extern knowledge_t *knowledge; extern region_t *firstregion,*lastregion; extern regionoutline_t *firstregionoutline,*lastregionoutline; extern long curtime, gamedays, gamesecs; extern enum GAMEMODE gamemode; int loadall(void) { DIR *dir; struct dirent *ent; int db = B_FALSE; gamemode = GM_LOADING; dir = opendir(MAPDIR); if (!dir) { dblog("Could not open map directory '%s'",MAPDIR); return B_TRUE; } // load region outlines if (loadregions()) { // this isn't an error - just means no savegames if (db) dblog("No region data found."); return B_FALSE; } // 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_FALSE; 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]; char line[BUFLEN]; int otid,known; char hiddenname[BUFLEN]; char *p,*dummy; 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); strcpy(line, buf); p = strtok_r(line, "^", &dummy); otid = atoi(p); p = strtok_r(NULL, "^", &dummy); strcpy(hiddenname, p); p = strtok_r(NULL, "^", &dummy); known = atoi(p); 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,newlevel; int db = B_TRUE; int matid; 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); fscanf(f, "newlevel: %d\n",&newlevel); // 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; l->newlevel = newlevel; // 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, "stamina: %f\n",&l->stamina); 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, "material: %d\n",&matid); l->material = findmaterial(matid); 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); fscanf(f, "eyeadj: %d\n",&l->eyeadjustment); if (db) dblog("--> Got hp=%d/%d. timespend=%d. sorted=%d. Now loading flags.",l->hp,l->maxhp,l->timespent,l->sorted); // clear existing flags from addlf while (l->flags->first) { killflag(l->flags->first); } // load 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; enum HABITAT habitatid; lifeform_t *l; object_t *o; map_t *m; cell_t *dummycell; int regionid; if (db) dblog("Loading map from %s...",basefile); snprintf(filename, BUFLEN, "%s/%s",MAPDIR,basefile); f = fopen(filename, "rt"); // create map m = addmap(); dummycell = malloc(sizeof(cell_t)); dummycell->obpile = addobpile(NULL, dummycell, NULL); 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, "region:%d\n",®ionid); // region id m->region = findregion(regionid); 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 *)&habitatid); // habitat m->habitat = findhabitat(habitatid); fscanf(f, "seed:%u\n",&m->seed); // seed fscanf(f, "lastplayervisit:%ld\n",&m->lastplayervisit); 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 room defs fscanf(f, "nrooms:%d\n",&m->nrooms); for (i = 0; i < m->nrooms; i++) { fscanf(f, "%d,%d,%d,%d,%d,%s\n",&m->room[i].id, &m->room[i].x1, &m->room[i].y1, &m->room[i].x2, &m->room[i].y2, buf); m->room[i].vault = findvault(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; int temphab; int roomid; //if (db) dblog("cell %d,%d...",x,y); // allocate this cell c = addcell(m, x, y); // cell info fscanf(f, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", &roomid, &celltypeid, &c->known, &c->knowntime, &c->knownglyph.ch, &c->knownglyph.colour, &c->visited, &c->lit, &c->origlit, &c->littimer,&temphab); c->habitat = findhabitat(temphab); c->room = findroom(m, roomid); 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; } } } // load flags loadflagpile(f, m->flags); 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, NULL, B_NOSTACK, B_FALSE, ot->id); // 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); fgets(buf, BUFLEN, f);// either 'obcontents:xx' or 'endob' if (strstarts(buf, "obcontents")) { // load this object's contents... char *p; char buf2[BUFLEN]; int ncontents; int i; //dblog("got obcontents"); // strip newline buf[strlen(buf)-1] = '\0'; p = readuntil(buf2, buf, ':'); // ignore bit before : p = readuntil(buf2, p, ')'); // ) will really be eol ncontents = atoi(buf2); for (i = 0 ; i < ncontents; i++) { loadob(f, o->contents, NULL); } fgets(buf, BUFLEN, f);// 'endobcontents' //dblog("want endobcontents, got: '%s'", buf); fgets(buf, BUFLEN, f);// 'endob' //dblog("want endob, got: '%s'", buf); } if (strstarts(buf, "endob")) { // we got 'endob' } else { dblog("ERROR loading objects - expecting 'endob' but got '%s'\n",buf); exit(1); } //fscanf(f, "endob\n"); return B_FALSE; } int loadregions(void) { FILE *f; char filename[BUFLEN]; int rtid,nthings,i,n; int numoutlines,numregions; int db = B_FALSE; // TODO: check that map dir exists snprintf(filename, BUFLEN, "%s/regions.dat",MAPDIR); f = fopen(filename, "rt"); if (!f) { return B_TRUE; } fscanf(f, "numoutlines:%d\n",&numoutlines); if (db) dblog("Found %d region outlines.\n",numoutlines); for (n = 0; n < numoutlines; n++) { fscanf(f, "startro\n"); fscanf(f, "rtypeid:%d\n",&rtid); // region type id addregionoutline(rtid); fscanf(f, "nthings:%d\n",&nthings); for (i = 0; i < nthings; i++) { int depth,x,y,val; enum REGIONTHING whatkind; char buf[BUFLEN],*p; fscanf(f, "startthing\n"); fscanf(f, " thingdepth:%d,%d,%d\n",&depth, &x, &y); fscanf(f, " thingkind:%d\n",(int *)&whatkind); fscanf(f, " thingval:%d\n",&val); fscanf(f, " thingwhat:%s\n",buf); fscanf(f, "endthing\n"); // replace ^ with ' ' in thingwhat for (p = buf ; *p; p++) { if (*p == '^') *p = ' '; } addregionthing(lastregionoutline, depth, x, y, whatkind, val, streq(buf, "NULL") ? NULL : buf); } fscanf(f, "endro\n"); if (db) dblog("Loaded regionoutline #%d / %d",n+1, numoutlines); } // now save out the actual region->outline mappings fscanf(f, "numregions:%d\n",&numregions); if (db) dblog("Found %d regions.\n",numregions); for (n = 0; n < numregions; n++) { region_t *r; enum REGIONTYPE rtid; int outlineid,parentid,nthings; fscanf(f, "startregion\n"); fscanf(f, " rtypeid:%d\n",(int *)&rtid); fscanf(f, " outline:%d\n",&outlineid); fscanf(f, " parentregion:%d\n",&parentid); fscanf(f, " nthings:%d\n",&nthings); fscanf(f, "endregion\n"); r = addregion(rtid, (parentid == -1) ? NULL : findregion(parentid), outlineid); r->nthings = nthings; if (db) dblog("Loaded region #%d / %d",n+1, numregions); } fclose(f); // successful load - kill the file now unlink(filename); 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") ) { snprintf(filename, BUFLEN, "%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); } // load world data if (loadworlddata(f)) { printf("Error load world data from file '%s'", ent->d_name); exit(1); } if (!loadlf(f, NULL)) { printf("Error loading player 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 loadworlddata(FILE *f) { fscanf(f, "timedata:%ld,%ld,%ld\n",&curtime,&gamedays,&gamesecs); 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); fprintf(f, "newlevel: %d\n",l->newlevel); // 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, "stamina: %f\n", l->stamina); fprintf(f, "alive: %d\n",l->alive); fprintf(f, "lastdamtype: %d\n",l->lastdamtype); fprintf(f, "lastdam: %s\n",l->lastdam); fprintf(f, "material: %d\n",l->material->id); 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); fprintf(f, "eyeadj: %d\n",l->eyeadjustment); // 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; rv = saveregions(); if (rv) { msg("Could not save region data."); return B_TRUE; } 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 snprintf(buf, BUFLEN, "%s/game.sav",SAVEDIR); f = fopen(buf, "wt"); if (!f) { msg("Could not open save file!"); return B_TRUE; } saveworlddata(f); 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 snprintf(filename, BUFLEN, "%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, "region:%d\n",m->region->id); // map region 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->id); // habitat fprintf(f, "seed:%u\n",m->seed); // seed fprintf(f, "lastplayervisit:%ld\n",m->lastplayervisit); 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"); // save room defs fprintf(f, "nrooms:%d\n",m->nrooms); for (i = 0; i < m->nrooms; i++) { fprintf(f, "%d,%d,%d,%d,%d,%s\n",m->room[i].id, m->room[i].x1, m->room[i].y1, m->room[i].x2, m->room[i].y2, m->room[i].vault ? m->room[i].vault->id : "^^^"); } // 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,%d,%d,%d,%d\n", c->room ? c->room->id : -1, c->type->id, c->known, c->knowntime, c->knownglyph.ch, c->knownglyph.colour, c->visited,c->lit,c->origlit,c->littimer,c->habitat->id ); // 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); } } } saveflagpile(f, m->flags); fclose(f); return B_FALSE; } int saveob(FILE *f, object_t *o) { object_t *oo; int ncontents; 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); // object contents... ncontents = countobs(o->contents, B_FALSE); if (ncontents) { fprintf(f, "obcontents:%d\n",ncontents); for (oo = o->contents->first ; oo ; oo = oo->next) { saveob(f, oo); } fprintf(f, "endobcontents\n"); } fprintf(f, "endob\n"); return B_FALSE; } int saveregions(void) { FILE *f; char filename[BUFLEN]; int i; regionoutline_t *ro; region_t *r; int numoutlines = 0,numregions = 0; // TODO: check that map dir exists snprintf(filename, BUFLEN, "%s/regions.dat",MAPDIR); f = fopen(filename, "wt"); for (ro = firstregionoutline ; ro ; ro = ro->next) { numoutlines++; } fprintf(f, "numoutlines:%d\n",numoutlines); for (ro = firstregionoutline ; ro ; ro = ro->next) { // save this outline fprintf(f, "startro\n"); fprintf(f, "rtypeid:%d\n",ro->rtype->id); // region type id fprintf(f, "nthings:%d\n",ro->nthings); for (i = 0; i < ro->nthings; i++) { fprintf(f, "startthing\n"); fprintf(f, " thingdepth:%d,%d,%d\n",ro->thing[i].depth, ro->thing[i].x, ro->thing[i].y); fprintf(f, " thingkind:%d\n",(int)ro->thing[i].whatkind); fprintf(f, " thingval:%d\n",(int)ro->thing[i].value); if (strlen(ro->thing[i].what)) { char localwhat[BUFLEN],*p; strcpy(localwhat,ro->thing[i].what); for (p = localwhat ; *p; p++) { if (*p == ' ') *p = '^'; } fprintf(f, " thingwhat:%s\n",localwhat); } else { fprintf(f, " thingwhat:NULL\n"); } fprintf(f, "endthing\n"); } fprintf(f, "endro\n"); } // now save out the actual region->outline mappings numregions = 0; for (r = firstregion ; r; r = r->next) { numregions++; } fprintf(f, "numregions:%d\n",numregions); for (r = firstregion ; r; r = r->next) { fprintf(f, "startregion\n"); fprintf(f, " rtypeid:%d\n",r->rtype->id); fprintf(f, " outline:%d\n",r->outline ? r->outline->id : -1); fprintf(f, " parentregion:%d\n",r->parentregion ? r->parentregion->id : -1); fprintf(f, " nthings:%d\n",r->nthings); fprintf(f, "endregion\n"); } fclose(f); return B_FALSE; } int saveworlddata(FILE *f) { fprintf(f, "timedata:%ld,%ld,%ld\n",curtime,gamedays,gamesecs); return B_FALSE; } int showhiscores(lifeform_t *lf, int min, int max) { sqlite3 *db; int rc; char filename[BUFLEN],*cmd; char *errmsg = NULL; char hilitescoretext[BUFLEN]; long hilitescore = -1; if (lf && !lfhasflag(lf, F_NOSCORE)) { hilitescore = calcscore(lf); } else { hilitescore = -1; } // open database snprintf(filename, BUFLEN, "%s/hiscores.db", DATADIR); rc = sqlite3_open(filename, &db); if (rc) { msg("error opening hiscore file '%s'.\n",filename); dblog("error opening hiscore file '%s'.\n",filename); return B_TRUE; } // show top ten //snprintf(cmd, BUFLEN, "select * from hiscores order by score desc limit 10;"); asprintf(&cmd, "select (select count(*) from hiscores b where b.score > a.score) + 1 as rank, score,name,job,killedby from hiscores a where (rank >= %d) and (rank <= %d) order by score desc limit 10;", min, max); snprintf(hilitescoretext, BUFLEN, "%ld",hilitescore); rc = sqlite3_exec(db, cmd, showhiscoreline, hilitescoretext, &errmsg); if (rc != SQLITE_OK) { msg("error writing hiscores: '%s'", errmsg); dblog("error writing hiscores: '%s'\n sql command: [%s]", errmsg, cmd); sqlite3_free(errmsg); } free(cmd); sqlite3_close(db); return B_FALSE; } // returns player's rank in 'rank' int writehiscore(lifeform_t *lf, int *rank) { sqlite3 *db; int rc; char filename[BUFLEN],*cmd; char pname[BUFLEN]; char jobname[BUFLEN]; char killedby[BUFLEN]; char *errmsg = NULL; sqlite3_stmt *smt; job_t *j; long minscore = 0; long score; score = calcscore(lf); // open database snprintf(filename, BUFLEN, "%s/hiscores.db", DATADIR); rc = sqlite3_open(filename, &db); if (rc) { msg("error opening hiscore file '%s'.\n",filename); dblog("error opening hiscore file '%s'.\n",filename); return B_TRUE; } getplayername(pname); j = getjob(player); snprintf(jobname, BUFLEN, "Lv%d %s", player->level, j->name); makekillertext(killedby, lf->lastdam, B_FALSE); if (!lfhasflag(lf, F_NOSCORE)) { asprintf(&cmd, "insert into 'hiscores' (score,name,job,killedby) VALUES (%ld, '%s', '%s', '%s')", score, pname, jobname, killedby); rc = sqlite3_exec(db, cmd, NULL, NULL, &errmsg); free(cmd); if (rc != SQLITE_OK) { msg("error writing hiscores: '%s'", errmsg); dblog("error writing hiscores: '%s'", errmsg); sqlite3_free(errmsg); } } if (rank) { if (lfhasflag(lf, F_NOSCORE)) { *rank = -1; } else { // find out the player's rank asprintf(&cmd, "select (select count(*) from hiscores b where b.score > a.score) + 1 as rank from hiscores a where score = %ld;",score); rc = sqlite3_prepare_v2(db, cmd, -1, &smt, 0); free(cmd); rc = sqlite3_step(smt); while (rc == SQLITE_ROW) { const char *p; p = (const char *)sqlite3_column_text(smt, 0); *rank = atoi(p); rc = sqlite3_step(smt); } } } // now delete all hiscore entries after 100 // find score number 100... asprintf(&cmd, "select score from hiscores order by score desc limit 100;"); rc = sqlite3_prepare_v2(db, cmd, -1, &smt, 0); free(cmd); rc = sqlite3_step(smt); while (rc == SQLITE_ROW) { const char *p; p = (const char *)sqlite3_column_text(smt, 0); minscore = atol(p); rc = sqlite3_step(smt); } if (minscore > 0) { // we now have a minimum score - delete everything lower than it. asprintf(&cmd, "delete from hiscores where score < %ld;", minscore); rc = sqlite3_exec(db, cmd, NULL, NULL, &errmsg); free(cmd); } sqlite3_close(db); return 0; }