/***************************************************************************
* Mordor Database Utilities:
* These functions allow for read/write access to Mordor MUD
* database files.
*
* (c) 1996 Brett Vickers & Brooke Paul
*/
#include "mstruct.h"
#include "mextern.h"
#include "utils.h"
/**********************************************************************/
/* count_obj */
/**********************************************************************/
/* Return the total number of objects contained within an object. */
/* If perm_only != 0, then only the permanent objects are counted. */
int count_obj(obj_ptr, perm_only)
object *obj_ptr;
char perm_only;
{
otag *op;
int total=0;
op = obj_ptr->first_obj;
while(op) {
if(!perm_only || (perm_only && (F_ISSET(op->obj, OPERMT) ||
F_ISSET(op->obj, OPERM2))))
total++;
op = op->next_tag;
}
return(total);
}
/**********************************************************************/
/* write_obj */
/**********************************************************************/
/* Save an object to a file that has already been opened and positioned. */
/* This function recursively saves the items that are contained inside */
/* the object as well. If perm_only != 0 then only permanent objects */
/* within the object are saved with it. */
int write_obj(fd, obj_ptr, perm_only)
int fd;
object *obj_ptr;
char perm_only;
{
int n, cnt, cnt2=0, error=0;
otag *op;
n = write(fd, obj_ptr, sizeof(object));
if(n < sizeof(object))
merror("write_obj", FATAL);
cnt = count_obj(obj_ptr, perm_only);
n = write(fd, &cnt, sizeof(int));
if(n < sizeof(int))
merror("write_obj", FATAL);
if(cnt > 0) {
op = obj_ptr->first_obj;
while(op) {
if(!perm_only || (perm_only &&
(F_ISSET(op->obj, OPERMT) ||
F_ISSET(op->obj, OPERM2)))) {
if(write_obj(fd, op->obj, perm_only) < 0)
error = 1;
cnt2++;
}
op = op->next_tag;
}
}
if(cnt != cnt2 || error)
return(-1);
else
return(0);
}
/**********************************************************************/
/* count_inv */
/**********************************************************************/
/* Returns the number of objects a creature has in his inventory. */
/* If perm_only != 0 then only those objects which are permanent */
/* will be counted. */
int count_inv(crt_ptr, perm_only)
creature *crt_ptr;
char perm_only;
{
otag *op;
int total=0;
op = crt_ptr->first_obj;
while(op) {
if(!perm_only || (perm_only && (F_ISSET(op->obj, OPERMT) ||
F_ISSET(op->obj, OPERM2))))
total++;
op = op->next_tag;
}
return(total);
}
/**********************************************************************/
/* write_crt */
/**********************************************************************/
/* Save a creature to an already open and positioned file. This function */
/* also saves all the items the creature is holding. If perm_only != 0 */
/* then only those items which the creature is carrying that are */
/* permanent will be saved. */
int write_crt(fd, crt_ptr, perm_only)
int fd;
creature *crt_ptr;
char perm_only;
{
int n, cnt, cnt2=0, error=0;
otag *op;
n = write(fd, crt_ptr, sizeof(creature));
if(n < sizeof(creature))
merror("write_crt", FATAL);
cnt = count_inv(crt_ptr, perm_only);
n = write(fd, &cnt, sizeof(int));
if(n < sizeof(int))
merror("write_crt", FATAL);
if(cnt > 0) {
op = crt_ptr->first_obj;
while(op) {
if(!perm_only || (perm_only &&
(F_ISSET(op->obj, OPERMT) ||
F_ISSET(op->obj, OPERM2)))) {
if(write_obj(fd, op->obj, perm_only) < 0)
error = 1;
cnt2++;
}
op = op->next_tag;
}
}
if(cnt != cnt2 || error)
return(-1);
else
return(0);
}
/**********************************************************************/
/* count_mon */
/**********************************************************************/
/* Returns the number of monsters in a given room. If perm_only is */
/* nonzero, then only the number of permanent monsters in the room */
/* is returned. */
int count_mon(rom_ptr, perm_only)
room *rom_ptr;
char perm_only;
{
ctag *cp;
int total=0;
cp = rom_ptr->first_mon;
while(cp) {
if(!perm_only || (perm_only && F_ISSET(cp->crt, MPERMT)))
total++;
cp = cp->next_tag;
}
return(total);
}
/**********************************************************************/
/* count_ite */
/**********************************************************************/
/* Returns the number of items in the room. If perm_only is nonzero */
/* then only the number of permanent items in the room is returned. */
int count_ite(rom_ptr, perm_only)
room *rom_ptr;
char perm_only;
{
otag *op;
int total=0;
op = rom_ptr->first_obj;
while(op) {
if(!perm_only || (perm_only && (F_ISSET(op->obj, OPERMT) ||
F_ISSET(op->obj, OPERM2))))
total++;
op = op->next_tag;
}
return(total);
}
/**********************************************************************/
/* count_ext */
/**********************************************************************/
/* Returns the number of exits in the room */
int count_ext(rom_ptr)
room *rom_ptr;
{
xtag *xp;
int total = 0;
xp = rom_ptr->first_ext;
while(xp) {
total++;
xp = xp->next_tag;
}
return(total);
}
/**********************************************************************/
/* count_ply */
/**********************************************************************/
/* Returns the number of players in the room */
int count_ply(rom_ptr)
room *rom_ptr;
{
ctag *pp;
int total = 0;
pp = rom_ptr->first_ply;
while(pp) {
total++;
pp = pp->next_tag;
}
return(total);
}
/**********************************************************************/
/* write_rom */
/**********************************************************************/
/* Saves the room pointed to by rom_ptr with all its contents. Its */
/* contents include exits, descriptions, items and monsters. If */
/* perm_only is nonzero, then only items and monsters in the room */
/* which are permanent will be saved. */
int write_rom(fd, rom_ptr, perm_only)
int fd;
room *rom_ptr;
char perm_only;
{
int n, cnt, error=0;
xtag *xp;
ctag *cp;
otag *op;
n = write(fd, rom_ptr, sizeof(room));
if(n < sizeof(room))
merror("write_rom", FATAL);
cnt = count_ext(rom_ptr);
n = write(fd, &cnt, sizeof(int));
if(n < sizeof(int))
merror("write_rom", FATAL);
xp = rom_ptr->first_ext;
while(xp) {
n = write(fd, xp->ext, sizeof(exit_));
if(n < sizeof(exit_))
merror("write_rom", FATAL);
xp = xp->next_tag;
}
cnt = count_mon(rom_ptr, perm_only);
n = write(fd, &cnt, sizeof(int));
if(n < sizeof(int))
merror("write_rom", FATAL);
cp = rom_ptr->first_mon;
while(cp) {
if(!perm_only || (perm_only && F_ISSET(cp->crt, MPERMT)))
if(write_crt(fd, cp->crt, 0) < 0)
error = 1;
cp = cp->next_tag;
}
cnt = count_ite(rom_ptr, perm_only);
n = write(fd, &cnt, sizeof(int));
if(n < sizeof(int))
merror("write_rom", FATAL);
op = rom_ptr->first_obj;
while(op) {
if(!perm_only || (perm_only && (F_ISSET(op->obj, OPERMT) ||
F_ISSET(op->obj, OPERM2))))
if(write_obj(fd, op->obj, perm_only) < 0)
error = 1;
op = op->next_tag;
}
if(!rom_ptr->short_desc)
cnt = 0;
else
cnt = strlen(rom_ptr->short_desc) + 1;
n = write(fd, &cnt, sizeof(int));
if(n < sizeof(int))
merror("write_rom", FATAL);
if(cnt) {
n = write(fd, rom_ptr->short_desc, cnt);
if(n < cnt)
merror("write_rom", FATAL);
}
if(!rom_ptr->long_desc)
cnt = 0;
else
cnt = strlen(rom_ptr->long_desc) + 1;
n = write(fd, &cnt, sizeof(int));
if(n < sizeof(int))
merror("write_rom", FATAL);
if(cnt) {
n = write(fd, rom_ptr->long_desc, cnt);
if(n < cnt)
merror("write_rom", FATAL);
}
if(!rom_ptr->obj_desc)
cnt = 0;
else
cnt = strlen(rom_ptr->obj_desc) + 1;
n = write(fd, &cnt, sizeof(int));
if(n < sizeof(int))
merror("write_rom", FATAL);
if(cnt) {
n = write(fd, rom_ptr->obj_desc, cnt);
if(n < cnt)
merror("write_rom", FATAL);
}
if(error)
return(-1);
else
return(0);
}
/**********************************************************************/
/* read_obj */
/**********************************************************************/
/* Loads the object from the open and positioned file described by fd */
/* and also loads every object which it might contain. Returns -1 if */
/* there was an error. */
int read_obj(fd, obj_ptr)
int fd;
object *obj_ptr;
{
int n, cnt, error=0;
otag *op;
otag **prev;
object *obj;
n = read(fd, obj_ptr, sizeof(object));
if(n < sizeof(object))
error = 1;
obj_ptr->first_obj = 0;
obj_ptr->parent_obj = 0;
obj_ptr->parent_rom = 0;
obj_ptr->parent_crt = 0;
if(obj_ptr->shotscur > obj_ptr->shotsmax)
obj_ptr->shotscur = obj_ptr->shotsmax;
n = read(fd, &cnt, sizeof(int));
if(n < sizeof(int)) {
error = 1;
cnt = 0;
}
prev = &obj_ptr->first_obj;
while(cnt > 0) {
cnt--;
op = (otag *)malloc(sizeof(otag));
if(op) {
obj = (object *)malloc(sizeof(object));
if(obj) {
if(read_obj(fd, obj) < 0)
error = 1;
obj->parent_obj = obj_ptr;
op->obj = obj;
op->next_tag = 0;
*prev = op;
prev = &op->next_tag;
}
else
merror("read_obj", FATAL);
}
else
merror("read_obj", FATAL);
}
if(error)
return(-1);
else
return(0);
}
/**********************************************************************/
/* read_crt */
/**********************************************************************/
/* Loads a creature from an open and positioned file. The creature is */
/* loaded at the mem location specified by the second parameter. In */
/* addition, all the creature's objects have memory allocated for them */
/* and are loaded as well. Returns -1 on fail. */
int read_crt(fd, crt_ptr)
int fd;
creature *crt_ptr;
{
int n, cnt, error=0;
otag *op;
otag **prev;
object *obj;
n = read(fd, crt_ptr, sizeof(creature));
if(n < sizeof(creature))
error = 1;
crt_ptr->first_obj = 0;
crt_ptr->first_fol = 0;
crt_ptr->first_enm = 0;
crt_ptr->parent_rom = 0;
crt_ptr->following = 0;
for(n=0; n<20; n++)
crt_ptr->ready[n] = 0;
if(crt_ptr->mpcur > crt_ptr->mpmax)
crt_ptr->mpcur = crt_ptr->mpmax;
if(crt_ptr->hpcur > crt_ptr->hpmax)
crt_ptr->hpcur = crt_ptr->hpmax;
n = read(fd, &cnt, sizeof(int));
if(n < sizeof(int)) {
error = 1;
cnt = 0;
}
prev = &crt_ptr->first_obj;
while(cnt > 0) {
cnt--;
op = (otag *)malloc(sizeof(otag));
if(op) {
obj = (object *)malloc(sizeof(object));
if(obj) {
if(read_obj(fd, obj) < 0) {
printf("error 3\n");
error = 1;
}
obj->parent_crt = crt_ptr;
op->obj = obj;
op->next_tag = 0;
*prev = op;
prev = &op->next_tag;
}
else
merror("read_crt", FATAL);
}
else
merror("read_crt", FATAL);
}
if(error)
return(-1);
else
return(0);
}
/**********************************************************************/
/* read_rom */
/**********************************************************************/
/* Loads a room from an already open and positioned file into the memory */
/* pointed to by the second parameter. Also loaded are all creatures, */
/* exits, objects and descriptions for the room. -1 is returned upon */
/* failure. */
int read_rom(fd, rom_ptr)
int fd;
room *rom_ptr;
{
int n, cnt, error=0;
xtag *xp;
xtag **xprev;
exit_ *ext;
ctag *cp;
ctag **cprev;
creature *crt;
otag *op;
otag **oprev;
object *obj;
char *sh, *lo, *ob;
n = read(fd, rom_ptr, sizeof(room));
if(n < sizeof(room))
error = 1;
rom_ptr->short_desc = 0;
rom_ptr->long_desc = 0;
rom_ptr->obj_desc = 0;
rom_ptr->first_ext = 0;
rom_ptr->first_obj = 0;
rom_ptr->first_mon = 0;
rom_ptr->first_ply = 0;
n = read(fd, &cnt, sizeof(int));
if(n < sizeof(int)) {
error = 1;
cnt = 0;
}
/* Load the exits */
xprev = &rom_ptr->first_ext;
while(cnt > 0) {
cnt--;
xp = (xtag *)malloc(sizeof(xtag));
if(xp) {
ext = (exit_ *)malloc(sizeof(exit_));
if(ext) {
n = read(fd, ext, sizeof(exit_));
if(n < sizeof(exit_))
error = 1;
xp->ext = ext;
xp->next_tag = 0;
*xprev = xp;
xprev = &xp->next_tag;
}
else
merror("read_rom", FATAL);
}
else
merror("read_rom", FATAL);
}
/* Read the monsters */
n = read(fd, &cnt, sizeof(int));
if(n < sizeof(int)) {
error = 1;
cnt = 0;
}
cprev = &rom_ptr->first_mon;
while(cnt > 0) {
cnt--;
cp = (ctag *)malloc(sizeof(ctag));
if(cp) {
crt = (creature *)malloc(sizeof(creature));
if(crt) {
if(read_crt(fd, crt) < 0)
error = 1;
crt->parent_rom = rom_ptr;
cp->crt = crt;
cp->next_tag = 0;
*cprev = cp;
cprev = &cp->next_tag;
}
else
merror("read_rom", FATAL);
}
else
merror("read_rom", FATAL);
}
/* Read the items */
n = read(fd, &cnt, sizeof(int));
if(n < sizeof(int)) {
error = 1;
cnt = 0;
}
oprev = &rom_ptr->first_obj;
while(cnt > 0) {
cnt--;
op = (otag *)malloc(sizeof(otag));
if(op) {
obj = (object *)malloc(sizeof(object));
if(obj) {
if(read_obj(fd, obj) < 0)
error = 1;
obj->parent_rom = rom_ptr;
op->obj = obj;
op->next_tag = 0;
*oprev = op;
oprev = &op->next_tag;
}
else
merror("read_rom", FATAL);
}
else
merror("read_rom", FATAL);
}
/* Read the descriptions */
n = read(fd, &cnt, sizeof(int));
if(n < sizeof(int)) {
error = 1;
cnt = 0;
}
if(cnt) {
sh = (char *)malloc(cnt);
if(sh) {
n = read(fd, sh, cnt);
if(n < cnt)
error = 1;
rom_ptr->short_desc = sh;
}
else
merror("read_rom", FATAL);
}
n = read(fd, &cnt, sizeof(int));
if(n < sizeof(int)) {
error = 1;
cnt = 0;
}
if(cnt) {
lo = (char *)malloc(cnt);
if(lo) {
n = read(fd, lo, cnt);
if(n < cnt)
error = 1;
rom_ptr->long_desc = lo;
}
else
merror("read_rom", FATAL);
}
n = read(fd, &cnt, sizeof(int));
if(n < sizeof(int)) {
error = 1;
cnt = 0;
}
if(cnt) {
ob = (char *)malloc(cnt);
if(ob) {
n = read(fd, ob, cnt);
if(n < cnt)
error = 1;
rom_ptr->obj_desc = ob;
}
else
merror("read_rom", FATAL);
}
if(error)
return(-1);
else
return(0);
}
/**********************************************************************/
/* free_obj */
/**********************************************************************/
/* This function is called to release the object pointed to by the first */
/* parameter from memory. All objects contained within it are also */
/* released from memory. */
void free_obj(obj_ptr)
object *obj_ptr;
{
otag *op, *temp;
op = obj_ptr->first_obj;
while(op) {
temp = op->next_tag;
free_obj(op->obj);
free(op);
op = temp;
}
free(obj_ptr);
}
/**********************************************************************/
/* free_crt */
/**********************************************************************/
/* This function releases the creature pointed to by the first parameter */
/* from memory. All items that creature has readied or carries will */
/* also be released. */
void free_crt(crt_ptr)
creature *crt_ptr;
{
otag *op, *temp;
op = crt_ptr->first_obj;
while(op) {
temp = op->next_tag;
free_obj(op->obj);
free(op);
op = temp;
}
free(crt_ptr);
}
/**********************************************************************/
/* free_rom */
/**********************************************************************/
/* This function releases the a room and its contents from memory. The */
/* function is passed the room's pointer as its parameter. The exits, */
/* descriptions, objects and monsters are all released from memory. */
void free_rom(rom_ptr)
room *rom_ptr;
{
xtag *xp, *xtemp;
otag *op, *otemp;
ctag *cp, *ctemp;
free(rom_ptr->short_desc);
free(rom_ptr->long_desc);
free(rom_ptr->obj_desc);
xp = rom_ptr->first_ext;
while(xp) {
xtemp = xp->next_tag;
free(xp->ext);
free(xp);
xp = xtemp;
}
op = rom_ptr->first_obj;
while(op) {
otemp = op->next_tag;
free_obj(op->obj);
free(op);
op = otemp;
}
cp = rom_ptr->first_mon;
while(cp) {
ctemp = cp->next_tag;
free_crt(cp->crt);
free(cp);
cp = ctemp;
}
free(rom_ptr);
}
int load_rom_from_file(num, rom_ptr)
int num;
room **rom_ptr;
{
int fd;
long n;
char file[80];
*rom_ptr = (room *)malloc(sizeof(room));
if(!*rom_ptr)
merror("load_from_file", FATAL);
zero(*rom_ptr, sizeof(room));
sprintf(file, "%s/r%05d", ROOMPATH, num);
fd = open(file, O_RDONLY | O_BINARY, 0);
if(fd < 0)
return(-1);
n = read_rom(fd, *rom_ptr);
if(n < 0) {
close(fd);
return(-1);
}
close(fd);
return(0);
}
void merror(str, errtype)
char *str;
int errtype;
{
printf("Error: %s\n", str);
if(errtype == FATAL)
exit(-1);
}
void zero(ptr, size)
void *ptr;
int size;
{
char *chptr;
int i;
chptr = (char *)ptr;
for(i=0; i<size; i++)
chptr[i] = 0;
}
int load_crt_from_file(num, crt_ptr)
int num;
creature **crt_ptr;
{
int fd;
long n;
char file[80];
*crt_ptr = (creature *)malloc(sizeof(creature));
if(!*crt_ptr)
merror("load_from_file", FATAL);
zero(*crt_ptr, sizeof(creature));
sprintf(file, "%s/m%02d", MONPATH, num/MFILESIZE);
fd = open(file, O_RDONLY | O_BINARY, 0);
if(fd < 0)
return(-1);
n = lseek(fd, (long)((num%MFILESIZE)*sizeof(creature)), 0);
if(n < 0L) {
close(fd);
return(-1);
}
n = read(fd, *crt_ptr, sizeof(creature));
if(n < sizeof(creature)) {
close(fd);
return(-1);
}
close(fd);
return(0);
}
int load_obj_from_file(num, obj_ptr)
int num;
object **obj_ptr;
{
int fd;
long n;
char file[80];
*obj_ptr = (object *)malloc(sizeof(object));
if(!*obj_ptr)
merror("load_from_file", FATAL);
zero(*obj_ptr, sizeof(object));
sprintf(file, "%s/o%02d", OBJPATH, num/OFILESIZE);
fd = open(file, O_RDONLY | O_BINARY, 0);
if(fd < 0)
return(-1);
n = lseek(fd, (long)((num%OFILESIZE)*sizeof(object)), 0);
if(n < 0L) {
close(fd);
return(-1);
}
n = read(fd, *obj_ptr, sizeof(object));
if(n < sizeof(object)) {
close(fd);
return(-1);
}
close(fd);
return(0);
}
int save_rom_to_file(num, rom_ptr)
int num;
room *rom_ptr;
{
int fd;
long n;
char file[80];
sprintf(file, "%s/r%05d", ROOMPATH, num);
unlink(file);
fd = open(file, O_RDWR | O_CREAT | O_BINARY, ACC);
if(fd < 0)
return(-1);
n = write_rom(fd, rom_ptr);
if(n < 0) {
close(fd);
return(-1);
}
close(fd);
return(0);
}
void posit(x, y)
int x,y;
{
printf("%c[%d;%df", 27, x, y);
}
void clearscreen()
{
printf("%c[2J",27);
}
void spin(x)
{
switch(x) {
case 1:
posit(8,10); printf("| \n");
break;
case 2:
posit(8,10); printf("/ \n");
break;
case 3:
posit(8,10); printf("\\ \n");
break;
default:
posit(8,10); printf("- \n");
break;
}
}
void message(str)
char str[80];
{
static int count=0;
int len, loc;
if(strlen(str)<79) {
len=79-strlen(str);
while(len) {
strcat(str, " ");
len -= 1;
}
}
count++;
if(count>10)
count=-1;
loc = count+13;
posit(loc, 10);
printf("%s", str);
}
int load_ply_from_file(str, ply_ptr)
char *str;
creature **ply_ptr;
{
int fd;
long n;
char file[80];
#ifdef COMPRESS
char *a_buf, *b_buf;
int size;
#endif
*ply_ptr = (creature *)malloc(sizeof(creature));
if(!*ply_ptr)
merror("load_from_file", FATAL);
zero(*ply_ptr, sizeof(creature));
sprintf(file, "%s/%s", PLAYERPATH, str);
fd = open(file, O_RDONLY | O_BINARY, 0);
if(fd < 0)
return(-1);
#ifdef COMPRESS
a_buf = (char *)malloc(30000);
if(!a_buf) merror(FATAL, "Memory allocation");
size = read(fd, a_buf, 30000);
if(size >= 30000) merror(FATAL, "Player too large");
if(size < 1) {
close(fd);
return(-1);
}
b_buf = (char *)malloc(80000);
if(!b_buf) merror(FATAL, "Memory allocation");
n = uncompress(a_buf, b_buf, size);
if(n > 80000) merror(FATAL, "Player too large");
n = read_crt_from_mem(b_buf, *ply_ptr, 0);
free(a_buf);
free(b_buf);
#else
n = read_crt(fd, *ply_ptr);
if(n < 0) {
close(fd);
return(-1);
}
#endif
close(fd);
return(0);
}
/************************************************************************/
/* write_crt_to_mem */
/************************************************************************/
/* Save a creature to memory. This function */
/* also saves all the items the creature is holding. If perm_only != 0 */
/* then only those items which the creature is carrying that are */
/* permanent will be saved. */
int write_crt_to_mem(buf, crt_ptr, perm_only)
char *buf;
creature *crt_ptr;
char perm_only;
{
int n, cnt, cnt2=0, error=0;
char *bufstart;
otag *op;
bufstart = buf;
memcpy(buf, crt_ptr, sizeof(creature));
buf += sizeof(creature);
cnt = count_inv(crt_ptr, perm_only);
memcpy(buf, &cnt, sizeof(int));
buf += sizeof(int);
if(cnt > 0) {
op = crt_ptr->first_obj;
while(op) {
if(!perm_only || (perm_only &&
(F_ISSET(op->obj, OPERMT) ||
F_ISSET(op->obj, OPERM2)))) {
if((n = write_obj_to_mem(buf, op->obj,
perm_only)) < 0)
error = 1;
else
buf += n;
cnt2++;
}
op = op->next_tag;
}
}
if(cnt != cnt2 || error)
return(-1);
else
return(buf - bufstart);
}
/************************************************************************/
/* read_crt_from_mem */
/************************************************************************/
/* Loads a creature from memory & returns bytes read. The creature is */
/* loaded at the mem location specified by the second parameter. In */
/* addition, all the creature's objects have memory allocated for them */
/* and are loaded as well. Returns -1 on fail. */
int read_crt_from_mem(buf, crt_ptr)
char *buf;
creature *crt_ptr;
{
int n, cnt, error=0;
char *bufstart;
otag *op;
otag **prev;
object *obj;
bufstart = buf;
memcpy(crt_ptr, buf, sizeof(creature));
buf += sizeof(creature);
crt_ptr->first_obj = 0;
crt_ptr->first_fol = 0;
crt_ptr->first_enm = 0;
crt_ptr->parent_rom = 0;
crt_ptr->following = 0;
for(n=0; n<20; n++)
crt_ptr->ready[n] = 0;
if(crt_ptr->mpcur > crt_ptr->mpmax)
crt_ptr->mpcur = crt_ptr->mpmax;
if(crt_ptr->hpcur > crt_ptr->hpmax)
crt_ptr->hpcur = crt_ptr->hpmax;
memcpy(&cnt, buf, sizeof(int));
buf += sizeof(int);
prev = &crt_ptr->first_obj;
while(cnt > 0) {
cnt--;
op = (otag *)malloc(sizeof(otag));
if(op) {
obj = (object *)malloc(sizeof(object));
if(obj) {
if((n = read_obj_from_mem(buf, obj)) < 0)
error = 1;
else
buf += n;
obj->parent_crt = crt_ptr;
op->obj = obj;
op->next_tag = 0;
*prev = op;
prev = &op->next_tag;
}
else
merror("read_crt", FATAL);
}
else
merror("read_crt", FATAL);
}
if(error)
return(-1);
else
return(buf - bufstart);
}
/************************************************************************/
/* write_obj_to_mem */
/************************************************************************/
/* Save an object to a block of memory. */
/* This function recursively saves the items that are contained inside */
/* the object as well. If perm_only != 0 then only permanent objects */
/* within the object are saved with it. This function returns the */
/* number of bytes that were written. */
int write_obj_to_mem(buf, obj_ptr, perm_only)
char *buf;
object *obj_ptr;
char perm_only;
{
int n, cnt, cnt2=0, error=0;
char *bufstart;
otag *op;
bufstart = buf;
memcpy(buf, obj_ptr, sizeof(object));
buf += sizeof(object);
cnt = count_obj(obj_ptr, perm_only);
memcpy(buf, &cnt, sizeof(int));
buf += sizeof(int);
if(cnt > 0) {
op = obj_ptr->first_obj;
while(op) {
if(!perm_only || (perm_only &&
(F_ISSET(op->obj, OPERMT) ||
F_ISSET(op->obj, OPERM2)))) {
if((n = write_obj_to_mem(buf,
op->obj, perm_only)) < 0)
error = 1;
else
buf += n;
cnt2++;
}
op = op->next_tag;
}
}
if(cnt != cnt2 || error)
return(-1);
else
return(buf - bufstart);
}
/************************************************************************/
/* read_obj_from_mem */
/************************************************************************/
/* Loads the object from memory, returns the number of bytes read, */
/* and also loads every object which it might contain. Returns -1 if */
/* there was an error. */
int read_obj_from_mem(buf, obj_ptr)
char *buf;
object *obj_ptr;
{
int n, cnt, error=0;
char *bufstart;
otag *op;
otag **prev;
object *obj;
bufstart = buf;
memcpy(obj_ptr, buf, sizeof(object));
buf += sizeof(object);
obj_ptr->first_obj = 0;
obj_ptr->parent_obj = 0;
obj_ptr->parent_rom = 0;
obj_ptr->parent_crt = 0;
if(obj_ptr->shotscur > obj_ptr->shotsmax)
obj_ptr->shotscur = obj_ptr->shotsmax;
memcpy(&cnt, buf, sizeof(int));
buf += sizeof(int);
prev = &obj_ptr->first_obj;
while(cnt > 0) {
cnt--;
op = (otag *)malloc(sizeof(otag));
if(op) {
obj = (object *)malloc(sizeof(object));
if(obj) {
if((n = read_obj_from_mem(buf, obj)) < 0)
error = 1;
else
buf += n;
obj->parent_obj = obj_ptr;
op->obj = obj;
op->next_tag = 0;
*prev = op;
prev = &op->next_tag;
}
else
merror("read_obj", FATAL);
}
else
merror("read_obj", FATAL);
}
if(error)
return(-1);
else
return(buf - bufstart);
}
int save_obj_to_file(num, obj_ptr)
int num;
object *obj_ptr;
{
int fd;
long n;
char file[80];
sprintf(file, "%s/o%02d", OBJPATH, num/OFILESIZE);
fd = open(file, O_RDWR | O_BINARY, 0);
if(fd < 0) {
fd = open(file, O_RDWR | O_CREAT | O_BINARY, ACC);
if(fd < 0)
return(-1);
}
n = lseek(fd, (long)((num%OFILESIZE)*sizeof(object)), 0);
if(n < 0L) {
close(fd);
return(-1);
}
n = write(fd, obj_ptr, sizeof(object));
if(n < sizeof(object)) {
close(fd);
return(-1);
}
close(fd);
return(0);
}
int save_crt_to_file(num, crt_ptr)
int num;
creature *crt_ptr;
{
int fd;
long n;
char file[80];
sprintf(file, "%s/m%02d", MONPATH, num/MFILESIZE);
fd = open(file, O_RDWR | O_BINARY, 0);
if(fd < 0) {
fd = open(file, O_RDWR | O_CREAT | O_BINARY, ACC);
if(fd < 0)
return(-1);
}
n = lseek(fd, (long)((num%MFILESIZE)*sizeof(creature)), 0);
if(n < 0L) {
close(fd);
return(-1);
}
n = write(fd, crt_ptr, sizeof(creature));
if(n < sizeof(creature)) {
close(fd);
return(-1);
}
close(fd);
return(0);
}
int save_ply_to_file(str, ply_ptr)
char *str;
creature *ply_ptr;
{
int fd;
long n;
char file[80];
#ifdef COMPRESS
char *a_buf, *b_buf;
int size;
#endif
sprintf(file, "%s/%s", PLAYERPATH, str);
unlink(file);
fd = open(file, O_RDWR | O_CREAT | O_BINARY, ACC);
if(fd < 0)
return(-1);
#ifdef COMPRESS
a_buf = (char *)malloc(80000);
if(!a_buf) merror(FATAL, "Memory allocation");
n = write_crt_to_mem(a_buf, ply_ptr, 0);
if(n > 80000) merror(FATAL, "Player too large");
b_buf = (char *)malloc(n);
if(!b_buf) merror(FATAL, "Memory allocation");
size = compress(a_buf, b_buf, n);
n = write(fd, b_buf, size);
free(a_buf);
free(b_buf);
#else
n = write_crt(fd, ply_ptr, 0);
if(n < 0) {
close(fd);
return(-1);
}
#endif
close(fd);
return(0);
}