Error Compile

0

cześć próbuję jedną gierke skompilować i wywala mi taki dziwny error

 1>saverestore.cpp(87): error C2466: cannot allocate an array of constant size 0
1>saverestore.cpp(118): error C2466: cannot allocate an array of constant size 0

pierwszy raz się spotykam z takim błędem
saverestore.cpp

/* copyright (c) 2009 S. Gilles <[email protected]>
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE. 
 */

/*
 * this is for saving games.  It is designed to make a full
 * record of the level (ex/including the player, complicated) into a file on disk,
 * complete with visibility and links to other levels.  the actual
 * data about the game is stored in another file which contains
 * a link to the current world. When that file is loaded, then world
 * is restored recursively.  This could allow odd things, like
 * the same bit of the world being used in multiple games,
 * as long as the player hasn't landed on it.  good?
 */



#include "saverestore.h"
//this gets all the nice #define's in there.

#include "event.h"
#include "constants.h"
#include "worldlet.h"
#include "usr_cntrl_actor.h"
#include "item.h"
#include "monster.h"
#include <string>
#include <vector>
#include <fstream>
#include <istream>
#include <stdlib.h>
#include <sstream>
#include <sys/stat.h>

extern void tell(const char *info); //in main.cpp - grumble

#define GET_ACTOR_VAR(x); {getline(i,a_stmp,LS_SEP); atmp->x = ival(a_stmp); }
#define GET_PLAYER_VAR(x); {getline(i,a_stmp,LS_SEP); player->x = ival(a_stmp);}
#define GET_ACTOR_IPOINTER(x); {getline(i, a_stmp,LS_SEP); if (a_stmp==s(LS_NUL_INDEX)){atmp->x=NULL; } else { atmp->x=(*l_i_table)[ival(a_stmp)]; }}
#define GET_PLAYER_IPOINTER(x); {getline(i, a_stmp,LS_SEP); if (a_stmp==s(LS_NUL_INDEX)){player->x=NULL;} else { player->x=(*l_i_table)[ival(a_stmp)];}}
//the ';' is there because the way it is defined, the macro looks like a function
//and emacs insists on being upset unless I 'properly' end the 'function'

/**********************function identifiers*****************************/
//when you create a function that is designed to be used as event, you must register it in the appropriate function.
//it's a pain in the neck, but it's the only portable way to have save files work correctly

void (*f_voids[])() = 
{
  &standard_health_restore,
  &gen_monster_r,
};

int id_of_function(void (*t_f)())
{
  for (unsigned int x=0; x<(sizeof f_voids)/(sizeof f_voids[0]); ++x){
    if (f_voids[x]==t_f){
      return x;
    }
  }
  return -1; 
}

void(*f_items[])(item *) = 
{
	//???
};

int id_of_function(void (*t_f)(item *))
{
 for (unsigned int x=0; x<(sizeof f_items)/(sizeof f_items[0]); ++x){
    if (f_items[x]==t_f){
      return x;
    }
  }
  return -1;
}

void (*f_actors[])(actor *) = {
  &poison_damage_low,
  &poison_damage_mid,
  &poison_damage_high,
};

int id_of_function(void (*t_f)(actor *))
{
 for (unsigned int x=0; x<(sizeof f_actors)/(sizeof f_actors[0]); ++x){
    if (f_actors[x]==t_f){
      return x;
    }
  }
  return -1;
}

void (*f_grounds[])(ground *) =
{
  //??? don't have any functions for this yet
};
int id_of_function(void (*t_f)(ground *))
{
  return -1;
}

void (*f_int_int_items[])(int, int, item *) = {
  &zombificate_corpse,
};
int id_of_function(void (*t_f)(int, int, item *))
{
  for (unsigned int x=0; x<(sizeof f_int_int_items)/(sizeof f_int_int_items[0]); ++x){
    if (f_int_int_items[x]==t_f){
      return x;
    }
  }
  return -1;;
}

void (*f_int_int_actor_item_grounds[])(int, int, actor *, item *, ground *) = {
  &modify_stat,
};
int id_of_function(void (*t_f)(int, int, actor*, item*, ground*))
{
  for (unsigned int x=0; x<(sizeof f_int_int_actor_item_grounds)/(sizeof f_int_int_actor_item_grounds[0]); ++x){
    if (f_int_int_actor_item_grounds[x]==t_f){
      return x;
    }
  }
  return -1;;

}

//as opposed to the above, which give general indecies of universal functions,
//these functions give local indicies of 
//yes, yes, this should be done with templates.
int index_of(item *tmp, std::vector<item *> *table){
  for (unsigned int x=0; x<table->size(); ++x){
    if ((*table)[x]==tmp){ return x; }
  }
  return LS_NUL_INDEX;
}

int index_of(ground *tmp, std::vector<ground *> *table){
  for (unsigned int x=0; x<table->size(); ++x){
    if ((*table)[x]==tmp){ return x; }
  }
  return LS_NUL_INDEX;
}

int index_of(actor *tmp, std::vector<actor *> *table){
  if (is_player(tmp)){ return LS_PLAYER_INDEX; }
  for (unsigned int x=0; x<table->size(); ++x){
    if ((*table)[x]==tmp){ return x; }
  }
  return LS_NUL_INDEX;
}

/***********************************************************************/


//because each dumplevel() function populates tables for 
//actors, ground, and items, a master list is needed when the events
//which are universal, try and access those events.  So there
//are three vectors of pointers to vectors here, which will eventually
//contain records of ALL items, grounds, actors, etc.

std::vector<std::vector<item *> *> all_i_table;
std::vector<std::vector<ground *> *> all_g_table;
std::vector<std::vector<actor *> *> all_a_table;
std::vector<worldlet *> all_w_table; //allows world-id's to be generated that match the id's in tables.

//tables for loading are needed too (pointer's, etc).  Unfortunately, they can't
//be the same as the above four tables because when a game is loaded, these tables
//become semi-permanent storage for things that existed in previous sessions.
//they must remain clean and existant.  If the two tables overlap, bad things will 
//happen when a games is started->saved[quit]loaded->saved again, up to and including
//SEGFAULTS and complete loss/scrambling of data from different erae.
std::vector<std::vector<item *> *> l_all_i_table;
std::vector<std::vector<ground *> *> l_all_g_table;
std::vector<std::vector<actor *> *> l_all_a_table;
std::vector<worldlet *> l_all_w_table;


//now, the functions that ACTUALLY save the game

//each of these functions should be heavily documented.  The dumpXXXX ones are underoptimized (templates should be used)
//but reading all of them should provide insight.
void dumpgame()
{
  std::string name=player->name+".sav";
  std::ofstream o(name.c_str());

  //clear the globals...  It might be that there can be multiple saves per session.
  all_i_table.clear();
  all_g_table.clear();
  all_a_table.clear();
  all_w_table.clear();

  //first, dump all levels
  dumplevel(current_world);

  //store version and current world number
  o<<VERSION<<LS_SEP<<"l."+player->name+"."+s(current_world->level_number)+"."+s(current_world->id)+".lvl"<<LS_SEP;
  o<<action_timer<<LS_SEP<<player->x<<LS_SEP<<player->y<<LS_SEP; //store current time, player x, player y.
  
  //todo:  insert happenings here.  Store them in the form:

  for (unsigned int q=0; q<new_happenings.size(); ++q){ 
    happenings.push_back(new_happenings[q]); //make sure all happenings are up-to-date
  }

  std::vector<event *>::iterator etmp=happenings.begin();
  while(etmp!=happenings.end()){
    dumpevent(&o, *etmp);
    etmp++;
  }
  o<<LS_NUL;
  //don't dump player's data, he is now dumped in with regular monsters as a special index
}

void dumplevel(worldlet *wtmp)
{
  //first, get level name (uninspired)
  //l.<playername>.<depth>.<id>.lvl
  //first dump VERSION;depth;lighting;X_SIZE;Y_SIZE
  //dump all ground:
  // TYPE;item;item;item...NULL;<name_of_connected_world>
  //the next name can be calculated easily, so it's okay.
  //dump all actors;
  //stat;stat;stat;stat...;stat;item;item...NULL
  

  //there are a lot of strange pointers used, mostly in happenings.
  //to expedite recreating them, a table of item/ground/actor pointers
  //is embedded in the file.  At the start of i/g/r definition, an index, 
  //enclosed in LS_MARK is placed.  When restoring this file, a table of 
  //actors, ground, whatever is built up.  Happenings store their arguments as
  //these indecies.  

  //TODO:  (Like, really soon.  If you're reading this, you should probably email soluphobe NOW)
  //note that happenings can (and should, in a lot of cases) contain pointers to objects
  //and places on other levels.  To get around this, happenings should store their arguments as 
  //a reference to the level where the thing is stored, and it's index there.  This means that there will
  //need to be a 2D vector of items reconstructed as the game loads - one vector per level, holding indicies

  //the whole thing should probably be encrypted too.  yeah.  Try a Vinagere XOR cipher - like ROT13 but harder to read.

  if (wtmp==NULL){ return; } //wtf?
  for (unsigned int x=0; x<all_w_table.size(); ++x){
    if (wtmp==all_w_table[x]){ return; } //dumping level that has/is already been/being dumped
  }
  std::string lv_name="l."+player->name+"."+s(wtmp->level_number)+"."+s(wtmp->id)+".lvl";

  std::ofstream o(lv_name.c_str());

  //basic information
  o<<VERSION<<LS_SEP<<wtmp->level_number<<LS_SEP<<wtmp->id;
  o<<LS_SEP<<wtmp->lighting<<LS_SEP<<X_SIZE<<LS_SEP<<Y_SIZE<<LS_SEP;

  all_w_table.push_back(wtmp);

  //items...  The dumpitem function is called by dumpground and dumpactor, but the table must
  //be set up ahead of time
  std::vector<item *> *all_item = new std::vector<item *>();
  all_i_table.push_back(all_item);
  all_item->reserve(X_SIZE*Y_SIZE); //this is probably a good approximation of the number of items in the level, no?

  //ground
  std::vector<ground *> *all_ground = new std::vector<ground *>();
  all_g_table.push_back(all_ground);
  all_ground->reserve(X_SIZE*Y_SIZE);
  for (unsigned int a=0; a<X_SIZE; ++a){
    for (unsigned int b=0; b<Y_SIZE; ++b){
      dumpground(&o, wtmp->ground_at(a,b), all_ground, all_item);
    }
  }

  //actors
  std::vector<actor *> *all_actor = new std::vector<actor *>();
  all_a_table.push_back(all_actor);
  all_actor->reserve(X_SIZE*Y_SIZE/3);
  for (unsigned int a=0; a<X_SIZE; ++a){
    for (unsigned int b=0; b<Y_SIZE; ++b){
      dumpactor(&o, wtmp->actor_at(a,b), all_actor, all_item);
    }
  }
}

void dumpground(std::ofstream *o, ground *gtmp, std::vector<ground *> *table, std::vector<item *> *i_table)
{

  unsigned int x=0;
  for (x=0; x<table->size(); ++x){
    if (gtmp==(*table)[x]){ return; }
  }
  table->push_back(gtmp);
  (*o)<<LS_MARK<<x<<LS_MARK;

  (*o)<<gtmp->type()<<LS_SEP<<((gtmp->visible)?"1":"0")<<LS_SEP;
  std::vector<item *>::iterator itmp=gtmp->stuff.begin();
  while (itmp != gtmp->stuff.end()){
    dumpitem(o, (*itmp), i_table);
    itmp++;
  }
  (*o)<<LS_NUL; //cue the end of this ground's items
  if (gtmp->conn_world != NULL){
    (*o)<<"l."+player->name+"."+s(gtmp->conn_world->level_number)+"."+s(gtmp->conn_world->id)+".lvl"<<LS_SEP;
    dumplevel(gtmp->conn_world); //unless dumplevel is correct, this will cause infinite loop
  } else {
    (*o)<<LS_NUL<<LS_SEP;
  }
}

void dumpitem(std::ofstream *o, item *itmp, std::vector<item *> *table)
{
  //get correct index to dump.  the item should NOT have been saved before, but check if it has.
  //if it has already been saved, bail.  If not, add it to the collection and save it under the correct mark

  unsigned int x=0;
  for (x=0; x<table->size(); ++x){
    if (itmp==(*table)[x]){ return; } //this may take some time, but it prevents really bad screwups that somehow might occur otherwise.
  }
  //now the index is correct for what it's position _will_ be...
  table->push_back(itmp); //...now.

  (*o)<<LS_MARK<<x<<LS_MARK;  //and store the item's index.  Now actually save the data

  //items _should_ be restorable based on name and bonus/subs, and visibility
  (*o)<<itmp->data.name<<LS_SEP<<itmp->data.bonus<<LS_SEP;
  (*o)<<id_of_sub(itmp->data.sub_equip)<<LS_SEP<<id_of_sub(itmp->data.sub_attack)<<LS_SEP<<id_of_sub(itmp->data.sub_use);
  (*o)<<LS_SEP<<((itmp->visible)?"1":"0")<<LS_SEP;
  

}

void dumpactor(std::ofstream *o, actor *atmp, std::vector<actor *> *table, std::vector<item *> *i_table)
{ //can ignore fragility because, when saving, every monster is unfragile - player's turn has started.  So it's okay
  if (atmp==NULL){ (*o)<<LS_NUL; return; }
  if (is_player(atmp)){ dumpplayer(o, i_table); return; }//player doesn't show up in world normally, but still exists.
  unsigned int x=0;
  for (x=0; x<table->size(); ++x){
    if (atmp==(*table)[x]){ return; }
  }
  table->push_back(atmp);
  (*o)<<LS_MARK<<x<<LS_MARK;

  //save every field of m_stat except face_tile because the configuration file could change. (color doesn't matter)
  //face_tile should be restorable from name, except in the case of modified monsters (most zombies).
  //so when loading, search name for "zombie" and if it exists, force-replace the face tile.  Otherwise, just create a new
  //monster based on name, then overwrite all data.
  (*o)<<atmp->data.name<<LS_SEP<<atmp->data.plural<<LS_SEP<<atmp->data.speed<<LS_SEP<<atmp->data.lvl<<LS_SEP<<atmp->data.str;
  (*o)<<LS_SEP<<atmp->data.dex<<LS_SEP<<atmp->data.con<<LS_SEP<<atmp->data.itl<<LS_SEP<<atmp->data.wis<<LS_SEP<<atmp->data.cha;
  (*o)<<LS_SEP<<atmp->data.nat_atk<<LS_SEP<<atmp->data.nat_def<<LS_SEP<<atmp->data.dmg_bas<<LS_SEP<<atmp->data.dmg_var;
  (*o)<<LS_SEP<<atmp->data.color<<LS_SEP<<atmp->data.status<<LS_SEP<<atmp->max_health<<LS_SEP<<atmp->current_health;
  (*o)<<LS_SEP<<atmp->time_offset<<LS_SEP;
  //make sure to forceset their x-y coords when loading, because otherwise they will imagine they are at position 0,0

  //now inventory.  Losing what it was wearing/wielding should be okay, because it should try and wear it again as soon as it moves
  std::vector<item *>::iterator itmp=atmp->inventory.begin();
  while (itmp != atmp->inventory.end()){
    if ((*itmp)->data.name != blank_item.name){
    dumpitem(o, (*itmp), i_table);
    }
    itmp++;
  }
  (*o)<<LS_NUL;

  //end of inventory, now dump a small selection that shows what actor is wielding/carrying
  (*o)<<index_of(atmp->wielded, i_table)<<LS_SEP<<index_of(atmp->offwielded, i_table)<<LS_SEP;
  (*o)<<index_of(atmp->a_helm, i_table)<<LS_SEP<<index_of(atmp->a_mail, i_table)<<LS_SEP;
  (*o)<<index_of(atmp->a_boots, i_table)<<LS_SEP<<index_of(atmp->a_bracers, i_table)<<LS_SEP;
  (*o)<<index_of(atmp->a_greaves, i_table)<<LS_SEP<<index_of(atmp->a_fullplate, i_table)<<LS_SEP;  
}


void dumpplayer(std::ofstream *o, std::vector<item *> *i_table)
{
  //this is designed to go right in with dumpactor.  The player will be distinguished from normal actors
  //by a LS_MARK of -1, corresponding to no real index.  Therefore, this can dump a bit more information than
  //normal actors can, including two sets of stats.
  (*o)<<LS_MARK<<LS_PLAYER_INDEX<<LS_MARK;
 
  (*o)<<LS_SEP<<player->data.speed<<LS_SEP<<player->data.lvl<<LS_SEP<<player->data.str;
  (*o)<<LS_SEP<<player->data.dex<<LS_SEP<<player->data.con<<LS_SEP<<player->data.itl<<LS_SEP<<player->data.wis<<LS_SEP<<player->data.cha;
  (*o)<<LS_SEP<<player->data.nat_atk<<LS_SEP<<player->data.nat_def<<LS_SEP<<player->data.dmg_bas<<LS_SEP<<player->data.dmg_var<<LS_SEP;
  (*o)<<player->data.color<<LS_SEP<<player->data.status<<LS_SEP<<player->max_health<<LS_SEP<<player->current_health<<LS_SEP;
  (*o)<<player->time_offset<<LS_SEP; 

  //and base data
  (*o)<<LS_SEP<<player->base_data.speed<<LS_SEP<<player->base_data.lvl<<LS_SEP<<player->base_data.str;
  (*o)<<LS_SEP<<player->base_data.dex<<LS_SEP<<player->base_data.con<<LS_SEP<<player->base_data.itl<<LS_SEP<<player->base_data.wis<<LS_SEP;
  (*o)<<player->base_data.cha<<LS_SEP<<player->base_data.nat_atk<<LS_SEP<<player->base_data.nat_def<<LS_SEP<<player->base_data.dmg_bas;
  (*o)<<LS_SEP<<player->base_data.dmg_var<<LS_SEP<<player->base_data.color<<LS_SEP<<player->base_data.status<<LS_SEP;

  //and inventory
  for (int x=0; x<52; ++x){
    if (player->inventory[x]!=NULL){
      dumpitem(o, player->inventory[x], i_table);
    } else {
      (*o)<<LS_NUL<<LS_SEP;
    }
  }

  //and wielded/carried
  (*o)<<index_of(player->wielded, i_table)<<LS_SEP<<index_of(player->offwielded, i_table)<<LS_SEP;
  (*o)<<index_of(player->a_helm, i_table)<<LS_SEP<<index_of(player->a_mail, i_table)<<LS_SEP;
  (*o)<<index_of(player->a_boots, i_table)<<LS_SEP<<index_of(player->a_bracers, i_table)<<LS_SEP;
  (*o)<<index_of(player->a_greaves, i_table)<<LS_SEP<<index_of(player->a_fullplate, i_table)<<LS_SEP;

}

void dumpevent(std::ofstream *o, event *etmp)
{
  //events are universal, not tied to levels.  So we need level identifiers on events to tell them which table to look in 
  //when restoring pointers.  so.

  //dump format is:
  //[world_targets_found_on];my_type;timer;actor_target_id;ground_target_id;item_target_id;int_target_1;int_target_2;[id of function]
  unsigned int world=0;
  for (world=0; world<all_w_table.size(); ++world){
    if ((etmp->my_type==E_NOARGS) ||
	(index_of(etmp->actor_target, all_a_table[world])!=LS_NUL_INDEX) || 
	(index_of(etmp->item_target, all_i_table[world])!=LS_NUL_INDEX) || 	
	(index_of(etmp->ground_target, all_g_table[world])!=LS_NUL_INDEX)){
      break; //this is the major timesink.  ah, well.
    }
  }
  //now world points to the index of where (if anywhere) the event's targets are located
  (*o)<<"l."+player->name+"."+s(all_w_table[world]->level_number)+"."+s(all_w_table[world]->id)+".lvl"<<LS_SEP; //world_targets_found_on
  (*o)<<etmp->my_type<<LS_SEP;
  (*o)<<etmp->timer<<LS_SEP;
  (*o)<<(index_of(etmp->actor_target, all_a_table[world]))<<LS_SEP;
  (*o)<<(index_of(etmp->ground_target, all_g_table[world]))<<LS_SEP;
  (*o)<<(index_of(etmp->item_target, all_i_table[world]))<<LS_SEP;
  (*o)<<etmp->int_target_1<<LS_SEP<<etmp->int_target_2<<LS_SEP;
  if (etmp->my_type==E_NOARGS){
    (*o)<<id_of_function(etmp->f_no_args);
  } else if (etmp->my_type==E_ITEM_TARGET){
    (*o)<<id_of_function(etmp->f_item_target);
  } else if (etmp->my_type==E_ACTOR_TARGET){
    (*o)<<id_of_function(etmp->f_actor_target);
  } else if (etmp->my_type==E_GROUND_TARGET){
    (*o)<<id_of_function(etmp->f_ground_target);
  } else if (etmp->my_type==E_INT_INT_ITEM_TARGET){
    (*o)<<id_of_function(etmp->f_ground_item_target);
  } else if (etmp->my_type==E_INT_INT_ACTOR_ITEM_GROUND_TARGET){
    (*o)<<id_of_function(etmp->f_int_int_actor_item_ground_target);
  }
  (*o)<<LS_SEP;
}


/***************************************************************/
/***************************************************************/
//now comes level LOADING
/***************************************************************/
/***************************************************************/

worldlet *restorelevel(std::string filename)
{
#ifdef DEBUG
  tell(("restoring "+filename).c_str());
#endif
  /*
   * this is a more hideously monolithic function than usual, because dumping items
   * only requires passing pointers, while restoring items involves creating them.
   * there might be issues with that, which this eliminates by sacrificing elegance.
   * 
   */  
  std::filebuf fb;
  fb.open(filename.c_str(), std::ios::in);  
  std::istream i(&fb); 
  std::vector<worldlet *>::iterator wtmp=l_all_w_table.begin();
  //std::cout<<"::::::::::::";
  while (wtmp!=l_all_w_table.end()){
    std::string tmp="l."+player->name+"."+s((*wtmp)->level_number)+"."+s((*wtmp)->id)+".lvl";
    if (filename==tmp){  return &(**wtmp); } 
    //check all other levels that are/might be being restored.  if the strings match, kill and get out.
    ++wtmp;
  }
  worldlet *new_w = new worldlet();
  std::vector<ground *> *l_g_table=new std::vector<ground *>();
  std::vector<item *> *l_i_table=new std::vector<item *>();
  std::vector<actor *> *l_a_table=new std::vector<actor *>();

  //now a skeleton level needs to be constructed such that it will fill the above criteria.
  //specifically, it needs level_number and id.  those can be extracted from the filename.
  //then the file is opened and restoration starts by reading in the ground.

  //of course, it would be easy to just treat the entire file as a stream and parse bits of it into
  //correct places - completely cutting out the getline dances.  if you're reading this, then it was
  //written still in the debugging stage and someone forgot to go back and do that.
  std::string s_version, s_level_number, s_id, s_x_size, s_y_size, s_lighting, s_dump;
  getline(i,s_version,LS_SEP);
  getline(i,s_level_number,LS_SEP);
  getline(i,s_id,LS_SEP);
  getline(i,s_lighting,LS_SEP);
  getline(i,s_dump,LS_SEP); //x_size
  getline(i,s_dump,LS_SEP); //y_size - not used here
  new_w->level_number=ival(s_level_number.c_str());
  new_w->id=ival(s_id.c_str());
  if (new_w->id >= latest_id){
    latest_id=new_w->id+2;
  }
  //ignore X_SIZE/Y_SIZE. they should only be used when splicing levels to determine compatibility.
  
  new_w->lighting=ival(s_lighting);  
  l_all_w_table.push_back(new_w); //id is already restorable, and index table must be built quickly to prevent infiniloops
  l_all_g_table.push_back(l_g_table);
  l_all_i_table.push_back(l_i_table);
  l_all_a_table.push_back(l_a_table);
  //restore ground.
  std::string g_index, g_type, g_visible, g_conn;
  int ig_index=0, ig_type;

  std::string i_index, i_name, i_bonus, i_csub, i_vis;
  int ii_index;
  
  l_g_table->reserve((X_SIZE*Y_SIZE)+1);
  unsigned int cx;
  unsigned int cy;
  for (cx=0; cx<X_SIZE; cx++){
    for (cy=0; cy<Y_SIZE; cy++){
#ifdef DEBUG
      tell(("restoring ground at "+s(cx)+","+s(cy)).c_str());
#endif
      getline(i,s_dump,LS_MARK);//should return NULL.  check here for errors    
      getline(i,g_index,LS_MARK);      
   
      ig_index=ival(g_index); //local index - where the ground should be created
      getline(i,g_type,LS_SEP); 
      ig_type=ival(g_type); //type of ground.  Now the skeleton can be made where it needs to go
 
      (*l_g_table)[ig_index] = new ground(static_cast<ground_type>(ig_type));
 
      new_w->floorplan[cy][cx]=(*l_g_table)[ig_index];
      getline(i,g_visible,LS_SEP);
            
      if (g_visible.c_str()[0]=='1'){
	(*l_g_table)[ig_index]->visible=true; //true==1
      } else {
	(*l_g_table)[ig_index]->visible=false; //false==0
      }
      
      //now start reading in items until LS_NUL is hit
  
      while (i.peek()!=LS_NUL){ //next character MUST be a LS_MARK, indicating beginning of an item block
	getline(i,s_dump,LS_MARK);//first mark begins, so will be NUL stored.
	getline(i,i_index,LS_MARK);
	//read to next mark, store as ii_index
	ii_index=ival(i_index);
	getline(i,i_name,LS_SEP);

	std::vector<item *>::iterator it=l_i_table->begin();
	for (int intmp=0; intmp<ii_index; ++intmp){
	  if(it==l_i_table->end()){
	    l_i_table->push_back(NULL);
	    it=l_i_table->end();
	  } else {
	    ++it;
	  }
	  
	}
	if (ii_index==0){
	  l_i_table->push_back(new item(i_name));
	} else {
	  l_i_table->insert(it, new item(i_name));
	}

	/*
	  l_i_table->reserve(ii_index+1); 
	  (*l_i_table)[ii_index] = new item(i_name);
	*/
	getline(i,i_bonus,LS_SEP);
	
	(*l_i_table)[ii_index]->data.bonus=ival(i_bonus);

	//get onequip sub
	getline(i,i_csub,LS_SEP);	
	(*l_i_table)[ii_index]->data.sub_equip=equip_sub_of_id(ival(i_csub));
	//get onattack sub
	getline(i,i_csub,LS_SEP);
	(*l_i_table)[ii_index]->data.sub_attack=attack_sub_of_id(ival(i_csub));

	//get onuse sub
	getline(i,i_csub,LS_SEP);
	(*l_i_table)[ii_index]->data.sub_use=use_sub_of_id(ival(i_csub));

	//read and store visible
	getline(i,i_vis,LS_SEP);
	
	
	if (i_vis.c_str()[0]=='1'){
	  (*l_i_table)[ii_index]->visible=true;
	} else {
	  (*l_i_table)[ii_index]->visible=false;
	}	
	
	(*l_g_table)[ig_index]->drop_upon((*l_i_table)[ii_index]);
	
      }//at this point, all items have been read in, and next char is an LS_NUL

      getline(i,s_dump,LS_NUL); //skip the nul.  now either [<new world>LS_SEP] or [LS_NUL LS_SEP].
      if (i.peek()!=LS_NUL){ //must be a new level!
	getline(i,g_conn,LS_SEP);
      	(*l_g_table)[ig_index]->conn_world=restorelevel(g_conn);
      } else {
	getline(i,s_dump,LS_SEP); //it's a null anyway.
      }      
    }
  }
  //now all ground for this level has been read in.  Time to bring in the actors.
  std::string a_index, a_stmp;
  int ia_index;
  actor *atmp=NULL;
  for (cx=0; cx<X_SIZE; ++cx){
    for (cy=0; cy<Y_SIZE; ++cy){
      if (i.peek()==LS_NUL){
	getline(i,s_dump,LS_NUL);
      } else {
	getline(i,s_dump,LS_MARK);
	getline(i,a_index,LS_MARK); 
	if (a_index!=s(LS_PLAYER_INDEX)){//normal monster
	  ia_index=ival(a_index);
	  getline(i,a_stmp,LS_SEP);//name
#ifdef DEBUG
	  tell(("restoring a "+a_stmp).c_str());
#endif	  
	  std::vector<actor *>::iterator it=l_a_table->begin();
	  for (int intmp=0; intmp<ia_index; ++intmp){
	    if(it==l_a_table->end()){
	      l_a_table->push_back(NULL);
	      ++it;
	    } else {
	      ++it;
	    }
	  }
	  if (ia_index==0){
	    l_a_table->push_back(new monster(a_stmp));
	  } else{
	    l_a_table->insert(it, new monster(a_stmp));
	  }

	  atmp=(*l_a_table)[ia_index];
	  if (atmp->data.face_tile==F_BLANK){ //zombies are sometimes dynamically generated
	    atmp->data.face_tile=F_ZOMBIE; //see dumpactor
	  }
	  new_w->ins_actr(cx, cy, (*l_a_table)[ia_index]);

	  GET_ACTOR_VAR(data.plural);
	  GET_ACTOR_VAR(data.speed);
	  GET_ACTOR_VAR(data.lvl);
	  GET_ACTOR_VAR(data.str);
	  GET_ACTOR_VAR(data.dex);
	  GET_ACTOR_VAR(data.con);
	  GET_ACTOR_VAR(data.itl);
	  GET_ACTOR_VAR(data.wis);
	  GET_ACTOR_VAR(data.cha);
	  GET_ACTOR_VAR(data.nat_atk);
	  GET_ACTOR_VAR(data.nat_def);
	  GET_ACTOR_VAR(data.dmg_bas);
	  GET_ACTOR_VAR(data.dmg_var);
	  GET_ACTOR_VAR(data.color);
 
	  getline(i,a_stmp,LS_SEP); //todo:  rewrite this so that it takes in only one character
	  atmp->data.status=a_stmp.c_str()[0];

	  GET_ACTOR_VAR(max_health);
	  GET_ACTOR_VAR(current_health);
	  GET_ACTOR_VAR(time_offset);
	  atmp->fragile=false;
	  //now inventory...  same as ground's

#ifdef DEBUG
	  tell(("restoring items of "+a_stmp).c_str());
#endif
	  while (i.peek()==LS_MARK){ //next character MUST be a LS_MARK, indicating beginning of an item block
	    
	    getline(i,s_dump,LS_MARK);//first mark begins, so will be NUL stored.
	    getline(i,i_index,LS_MARK);

	    //read to next mark, store as ii_index
	    ii_index=ival(i_index);
	    getline(i,i_name,LS_SEP);
	   
	    std::vector<item *>::iterator it=l_i_table->begin();
	    for (int intmp=0; intmp<ii_index; ++intmp){
	      if(it==l_i_table->end()){
		l_i_table->push_back(NULL);
		++it;
	      } else {
		++it;
	      }
	    }
	    if (ii_index==0){
	      l_i_table->push_back(new item(i_name));
	    } else {
	      l_i_table->insert(it, new item(i_name));
	    }

	    getline(i,i_bonus,LS_SEP);	
	    (*l_i_table)[ii_index]->data.bonus=ival(i_bonus);
	    //get onequip sub
	    getline(i,i_csub,LS_SEP);	
	    (*l_i_table)[ii_index]->data.sub_equip=equip_sub_of_id(ival(i_csub));
	    //get onattack sub
	    getline(i,i_csub,LS_SEP);
	    (*l_i_table)[ii_index]->data.sub_attack=attack_sub_of_id(ival(i_csub));
	    //get onuse sub
	    getline(i,i_csub,LS_SEP);
	    (*l_i_table)[ii_index]->data.sub_use=use_sub_of_id(ival(i_csub));
	    //read and store visible
	    getline(i,i_vis,LS_SEP);	
	   
	    if (i_vis.c_str()[0]=='1'){
	      (*l_i_table)[ii_index]->visible=true;
	    } else {
	      (*l_i_table)[ii_index]->visible=false; 
	    }
	    
	  }//at this point, all items have been read in, and next char is an LS_NUL
#ifdef DEBUG
	  tell(("read in items of "+a_stmp).c_str());
#endif
	  getline(i,s_dump,LS_NUL); //skip the nul.
	  
	  //now comes what it's carrying.
	  	  
	  GET_ACTOR_IPOINTER(wielded);
	  GET_ACTOR_IPOINTER(offwielded);
	  GET_ACTOR_IPOINTER(a_helm);
	  GET_ACTOR_IPOINTER(a_mail);
	  GET_ACTOR_IPOINTER(a_boots);
	  GET_ACTOR_IPOINTER(a_bracers);
	  GET_ACTOR_IPOINTER(a_greaves);	  
	  GET_ACTOR_IPOINTER(a_fullplate);
	  
	  new_w->ins_actr(cx, cy, (*l_a_table)[ia_index]); //for some reason, doesn't work as intended.  why?
	  
	} else { //player is dumped differently, 2 stat blocks &c.
	  getline(i,s_dump,LS_SEP);
	  current_world=new_w;
	  current_world->ins_actr(cx, cy, player);
	  a_index="0";//if a_index is untouched, some sort of bug currently exists that elevates issues with actor restoration
	  GET_PLAYER_VAR(data.speed);
	  GET_PLAYER_VAR(data.lvl);
	  GET_PLAYER_VAR(data.str);
	  GET_PLAYER_VAR(data.dex);
	  GET_PLAYER_VAR(data.con);
	  GET_PLAYER_VAR(data.itl);
	  GET_PLAYER_VAR(data.wis);
	  GET_PLAYER_VAR(data.cha);
	  GET_PLAYER_VAR(data.nat_atk);
	  GET_PLAYER_VAR(data.nat_def);
	  GET_PLAYER_VAR(data.dmg_bas);
	  GET_PLAYER_VAR(data.dmg_var);
	  GET_PLAYER_VAR(data.color);
	  getline(i,a_stmp,LS_SEP); //todo:  rewrite this so that it takes in only one character
	  player->data.status=a_stmp.c_str()[0];
	 
	  GET_PLAYER_VAR(max_health);
	  GET_PLAYER_VAR(current_health);
	  GET_PLAYER_VAR(time_offset);
	  //-----------------------------------//
	  getline(i,s_dump,LS_SEP);
	  GET_PLAYER_VAR(base_data.speed);
	  GET_PLAYER_VAR(base_data.lvl);
	  GET_PLAYER_VAR(base_data.str);
	  GET_PLAYER_VAR(base_data.dex);
	  GET_PLAYER_VAR(base_data.con);
	  GET_PLAYER_VAR(base_data.itl);
	  GET_PLAYER_VAR(base_data.wis);
	  GET_PLAYER_VAR(base_data.cha);
	  GET_PLAYER_VAR(base_data.nat_atk);
	  GET_PLAYER_VAR(base_data.nat_def);
	  GET_PLAYER_VAR(base_data.dmg_bas);
	  GET_PLAYER_VAR(base_data.dmg_var);
	  GET_PLAYER_VAR(base_data.color);

	  getline(i,a_stmp,LS_SEP); //todo:  rewrite this so that it takes in only one character
	  player->base_data.status=a_stmp.c_str()[0];

	  for (int x=0; x<52; ++x){	    
	    if (i.peek()!=LS_NUL){
	      getline(i,s_dump,LS_MARK);//first mark begins, so will be NUL stored.
	      getline(i,i_index,LS_MARK);
	      //read to next mark, store as ii_index
	      ii_index=ival(i_index);
	      

	      getline(i,i_name,LS_SEP);

	      std::vector<item *>::iterator it=l_i_table->begin();
	      for (int intmp=0; intmp<ii_index; ++intmp){
		if(it==l_i_table->end()){
		  l_i_table->push_back(NULL);
		  ++it;
		} else {
		  ++it;
		}
	      }
	      l_i_table->insert(it, new item(i_name));

	      getline(i,i_bonus,LS_SEP);	
	      (*l_i_table)[ii_index]->data.bonus=ival(i_bonus);
	      //get onequip sub
	      getline(i,i_csub,LS_SEP);	
	      (*l_i_table)[ii_index]->data.sub_equip=equip_sub_of_id(ival(i_csub));
	      //get onattack sub
	      getline(i,i_csub,LS_SEP);
	      (*l_i_table)[ii_index]->data.sub_attack=attack_sub_of_id(ival(i_csub));
	      //get onuse sub
	      getline(i,i_csub,LS_SEP);
	      (*l_i_table)[ii_index]->data.sub_use=use_sub_of_id(ival(i_csub));
	      //read and store visible
	      getline(i,i_vis,LS_SEP);	
	      //hack alert!
	      if (i_vis.c_str()[0]=='1'){
		(*l_i_table)[ii_index]->visible=true; //true=1
	      } else {
		(*l_i_table)[ii_index]->visible=false; //and false=0
	      }
	      player->inventory[x]=((*l_i_table)[ii_index]);
	    } else {
	      getline(i,s_dump,LS_SEP);//player always dumps nul to maintain inv order
	    }
	  }
	  GET_PLAYER_IPOINTER(wielded);
	  GET_PLAYER_IPOINTER(offwielded);
	  GET_PLAYER_IPOINTER(a_helm);
	  GET_PLAYER_IPOINTER(a_mail);
	  GET_PLAYER_IPOINTER(a_boots);
	  GET_PLAYER_IPOINTER(a_bracers);
	  GET_PLAYER_IPOINTER(a_greaves);
	  GET_PLAYER_IPOINTER(a_fullplate);
	}
      }

    }

  }
#ifdef DEBUG
  tell("world should be restored now");
#endif
  return new_w;
}


bool restoregame() //this should be complete name of file, but relative pathing is allowed
{
  struct stat fileInfo;
  std::string filename = player->name+".sav"; //todo:  point this to /var/games/tzar/save or something...
  if (stat(filename.c_str(), &fileInfo)!=0){ //savefile doesn't exists...
    return false;
  }

  /////////////////
  tell("Restoring save file...");
  /////////////////
  if (LS_MARK==LS_NUL || LS_MARK==LS_SEP || LS_SEP==LS_NUL){
    tell("This executable has been compiled in a way that precludes level loading.  To correct this, make sure the values LS_MARK, LS_SEP, and LS_NUL in saverestore.h are UNIQUE, then recompile.");
    return false;
  }
  std::string s_dump;
  std::filebuf fb;
  fb.open(filename.c_str(), std::ios::in);
  std::istream i(&fb);
  l_all_i_table.clear();
  l_all_g_table.clear();
  l_all_a_table.clear();
  l_all_w_table.clear();
#ifdef DEBUG
  tell("now checking versioning");
#endif
  std::string t_version="";
  getline(i,t_version,LS_SEP);
  bool compatible_file=(t_version==VERSION);
  for (unsigned int qq=0; (qq<(sizeof( compat_versions)/sizeof( compat_versions[0])) && !compatible_file); ++qq){
    if (t_version==compat_versions[qq]){ compatible_file=true; }
  }
  if (!compatible_file){
    std::string a="Current version: "+VERSION+".  Load save file from version "+t_version+"?";
    if (!(confirm(a.c_str()))){ register_msg("Fine."); return false; }
  }
  //first, restore the player's name.  A few other algorithms try and recreate save names for 
  //redundancy checking, so the player's name needs to be extracted
  std::string start_world="";
  getline(i,start_world,LS_SEP);
 
  restorelevel(start_world);
  std::string s_timer;
  getline(i,s_timer,LS_SEP);
  action_timer=ival(s_timer);

  getline(i,s_dump,LS_SEP);//player x
  getline(i,s_dump,LS_SEP);//player y
  
  //now come events/
#ifdef DEBUG
  tell("reading in events now.");
#endif
  std::string right_world, test_world, e_stmp;
  event *e_tmp = new event;
  int w_index=0;
  std::vector<worldlet *>::iterator wtmp=l_all_w_table.begin();
  
  while (i.peek()!=LS_NUL){
    getline(i,right_world,LS_SEP); //should be impossible for a LS_SEP to be _in_ world name
    while (wtmp!=l_all_w_table.end()){
      test_world="l."+player->name+"."+s((*wtmp)->level_number)+"."+s((*wtmp)->id)+".lvl";
      if (right_world==test_world){ 
	wtmp=l_all_w_table.end();
      } else {
	wtmp++;
	w_index++;
      }
    }//now w_index has the correct index for all top-level vectors.  lower level indicies will now be read in.
#ifdef DEBUG
    tell(("got right world for an event, id-->"+right_world).c_str());
#endif

    getline (i,e_stmp,LS_SEP); //type
   
    e_tmp->my_type=static_cast<event_type>(ival(e_stmp));
    getline (i,e_stmp,LS_SEP); //timer
    e_tmp->timer=ival(e_stmp);
    getline(i,e_stmp,LS_SEP); //actor target
    if (e_tmp->my_type==E_ACTOR_TARGET){
      e_tmp->actor_target=((ival(e_stmp)==LS_NUL_INDEX)?NULL:l_all_a_table[w_index]->at(ival(e_stmp)));
    }
    getline(i,e_stmp,LS_SEP); //ground target
    if (e_tmp->my_type==E_GROUND_TARGET){
      e_tmp->ground_target=((ival(e_stmp)==LS_NUL_INDEX)?NULL:l_all_g_table[w_index]->at(ival(e_stmp)));
    }
    getline(i,e_stmp,LS_SEP); //item target
    if (e_tmp->my_type==E_ITEM_TARGET || e_tmp->my_type==E_INT_INT_ITEM_TARGET){
      e_tmp->item_target=((ival(e_stmp)==LS_NUL_INDEX)?NULL:l_all_i_table[w_index]->at(ival(e_stmp)));
    }
    getline(i,e_stmp,LS_SEP); //int1 target
    e_tmp->int_target_1=ival(e_stmp);
    getline(i,e_stmp,LS_SEP); //int2 target
    e_tmp->int_target_2=ival(e_stmp);
    getline(i,e_stmp,LS_SEP); //function target
       
    //of course, etmp can't get pushed back because it will get recreated next run-through.  this is the next-best thing.
#ifdef DEBUG
    tell("got an event, adding it now.  timer->");
#endif
    if (ival(e_stmp)>=0){ 
      if (e_tmp->my_type==E_NOARGS){
	new_happenings.push_back(mk_event(e_tmp->timer, f_voids[ival(e_stmp)]));
      } else if (e_tmp->my_type==E_ITEM_TARGET){
	new_happenings.push_back(mk_event(e_tmp->timer, f_items[ival(e_stmp)], e_tmp->item_target));
      } else if (e_tmp->my_type==E_ACTOR_TARGET){
	new_happenings.push_back(mk_event(e_tmp->timer, f_actors[ival(e_stmp)], e_tmp->actor_target));
      } else if (e_tmp->my_type==E_GROUND_TARGET){
	new_happenings.push_back(mk_event(e_tmp->timer, f_grounds[ival(e_stmp)], e_tmp->ground_target));
      } else if (e_tmp->my_type==E_INT_INT_ITEM_TARGET){
	new_happenings.push_back(mk_event(e_tmp->timer, f_int_int_items[ival(e_stmp)], e_tmp->int_target_1, e_tmp->int_target_2, e_tmp->item_target));
      } else if (e_tmp->my_type==E_INT_INT_ACTOR_ITEM_GROUND_TARGET){
	new_happenings.push_back(mk_event(e_tmp->timer, f_int_int_actor_item_grounds[ival(e_stmp)], e_tmp->int_target_1, e_tmp->int_target_2, e_tmp->actor_target, e_tmp->item_target, e_tmp->ground_target));
      }
    }
  } 
#ifdef DEBUG
  tell("restore successful.");
#endif
  return true;
}
0

Jesteś leń, bo

  1. Dostałeś kod błędu
  2. Dostałeś dokładny opis błędu, który jest trywialny.

https://msdn.microsoft.com/en-us/library/6zxfydcs.aspx

1 użytkowników online, w tym zalogowanych: 0, gości: 1