/
ScryMUD/mud/
ScryMUD/mud/grrmud/Boards/
ScryMUD/mud/grrmud/Help/
ScryMUD/mud/grrmud/Pfiles/
ScryMUD/mud/grrmud/PlayerSacks/
ScryMUD/mud/grrmud/PlayerShops/
ScryMUD/mud/grrmud/help_filter/
ScryMUD/mud/hegemon/
ScryMUD/mud/hegemon/data/
ScryMUD/mud/hegemon/data/help/battle/
ScryMUD/mud/hegemon/data/help/client/
ScryMUD/mud/hegemon/data/help/communications/
ScryMUD/mud/hegemon/data/help/skills/
ScryMUD/mud/hegemon/data/help/spells/
ScryMUD/mud/include/
ScryMUD/mud/lib/
ScryMUD/mud/lib/bitfield/
ScryMUD/mud/lib/log/
ScryMUD/mud/lib/string2/
// $Id: zone.cc,v 1.3.2.5 2000/05/03 02:25:14 justin Exp $
// $Revision: 1.3.2.5 $  $Author: justin $ $Date: 2000/05/03 02:25:14 $

//
//ScryMUD Server Code
//Copyright (C) 1998  Ben Greear
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either version 2
//of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//
// To contact the Author, Ben Greear:  greear@cyberhighway.net, (preferred)
//                                     greearb@agcs.com
//
#ifdef USEMYSQL
#include "mysql/mysql.h"
#endif

#include "zone.h"
#include "const.h"
#include "misc.h"
#include "misc2.h"
#include "command4.h"
#include "command5.h"


int ZoneList::_cnt = 0; //instance count
extern String UNKNOWN;

ZoneList& ZoneList::instance() {
   static ZoneList self;
   return self;
}

void ZoneList::readSelf() {
#ifdef USEMYSQL
   if (config.useMySQL)
      dbReadSelf();
   else
#endif
      fileReadSelf();
}

#ifdef USEMYSQL
void ZoneList::dbReadSelf() {
   long i;
   MYSQL_RES* result;
   MYSQL_ROW row;
   String query="select ZONE_NUM from Zones";

   if (mysql_real_query(database, query, strlen(query))==0) {
      if ((result=mysql_store_result(database))==NULL) {
         if (mudlog.ofLevel(WRN)) {
            mudlog << "In ZoneList::dbReadSelf():\n";
            mudlog << "Eror retrieving query results: " << mysql_error(database)
                   << endl;
         }
         return;
      }
      while ((row=mysql_fetch_row(result))) {
         i=atol(row[0]);
         if ((i >= 0) && (i < NUMBER_OF_ZONES)) {
            add(i);
         }
         else {
            if (mudlog.ofLevel(WRN)) {
               mudlog << "In ZoneList::dbReadSelf():\n";
               mudlog << "Bad zone number " << i << " in Zones table. You may\n"
                      << "need to increase NUMBER_OF_ZONES in const.h, then\n"
                      << "recompile.\n";
               return;
            }
         }
      }
      mysql_free_result(result);
   }
   else {
      if (mudlog.ofLevel(WRN)) {
         mudlog << "In ZoneList::dbReadSelf():\n";
         mudlog << "Error executing query: " << mysql_error(database) << endl;
      }
   }
}
#endif

void ZoneList::fileReadSelf() {
   ifstream dafile("./World/ENABLED_ZONES");
   int i;
   if (dafile) {
      dafile >> i;
      while (i != -1) {
         if ((i >= 0) && (i < NUMBER_OF_ZONES)) {
            add(i);
         }//if
         dafile >> i;
      }//while
   }//if
}//read()

void ZoneList::writeSelf() {
   // In theory, writing the Zones collection will take care of this
   // in the MySQL database.
   fileWriteSelf();
}

void ZoneList::fileWriteSelf() {
   ofstream dafile("./World/ENABLED_ZONES");
   Cell<int*> cll(nums);
   int* ptr;

   while ((ptr = cll.next())) {
      dafile << *ptr << endl;
   }
   dafile << "-1";
}//write

void ZoneList::add(int i) {
   if (!contains(i)) {
      nums.append(new int(i));
   }//if
}//add

void ZoneList::remove(int i) {
   Cell<int*> cll(nums);
   int* ptr;

   while ((ptr = cll.next())) {
      if (*ptr == i) {
         nums.lose(cll);
         return;
      }//if
   }//while
}//remove

int ZoneList::contains(int i) {
   Cell<int*> cll(nums);
   int* ptr;

   while ((ptr = cll.next())) {
      if (*ptr == i) {
         return TRUE;
      }//if
   }//while

   return FALSE;
}

String ZoneList::toString() {
   String retval(150);

   Cell<int*> cll(nums);
   int* ptr;

   retval = "These zones are currently open to mortals:\n";

   while ((ptr = cll.next())) {
      retval.Append(*ptr);
      retval.Append(" ");
   }//while

   return retval;
}//toString

void ZoneList::execute() {
   Cell<int*> cll(nums);
   int* ptr;

   while ((ptr = cll.next())) {
      ZoneCollection::instance().zunlock(*ptr);
   }//while
}//execute



int ZoneCollection::_cnt = 0;

ZoneCollection& ZoneCollection::instance() {
   static ZoneCollection self;
   return self;
}

zone& ZoneCollection::elementAt(int i) {
   zone* foo = zone_list.elementAt(i);
   if (!foo)
      return dummy;
   else
      return *foo;
}//elementAt


zone& ZoneCollection::getZoneFor(room& rm) {

   int rm_num = rm.getIdNum();

   for (int i = 0; i<NUMBER_OF_ZONES; i++) {
      if ((zone_list[i].getBeginRoomNum() <= rm_num) && 
          (zone_list[i].getEndRoomNum() >= rm_num)) {
         return zone_list[i];
      }//if
   }//for

   if (mudlog.ofLevel(WRN)) {
      mudlog << "WARNING: getZone(room: " << rm.getIdNum()
             << ") returning dummy" << endl;
   }//if

   return dummy;
}//getZoneNum

void ZoneCollection::readSelf() {
   int k;
   char buf[82];

   mudlog.log(DB, "In ZoneCollection::readSelf\n");

   ifstream zfile("./World/ZONE_FILE");
   if (!zfile) {
      mudlog.log(DIS, "ERROR:  ZONE_FILE not opened correctly, fatal.\n");
      do_shutdown = TRUE;
      exit(101);
   }//if

   zfile >> k;
   zfile.getline(buf, 80);
   
   while ((k != -1) && zfile) { //then read it in.
      if (!check_l_range(k, 0, NUMBER_OF_ZONES, mob_list[0], FALSE)) {
         mudlog.log(ERROR, "ERROR:  zone number is out of range, fatal\n");
         do_shutdown = TRUE;
         exit(100);
      }//if
      zone_list[k].Read(zfile, k);
      zfile >> k;
      zfile.getline(buf, 80);
   }//while
}//readSelf


void ZoneCollection::doRegeneration() { //for all areas that need it.
   int i;
   for (i = 0; i<NUMBER_OF_ZONES; i++) {
      if (zone_list.elementAtNoCreate(i)) {
         if (zone_list[i].isInUse()) {
            zone_list[i].decrementTicksTillRegen();
            if (zone_list[i].getTicksTillRegen() <= 0) {
               if (!room_list[zone_list[i].getEndRoomNum()].isZlocked()) {
                  update_objects(i, FALSE);
                  //            log("Objects updated.\n");
                  update_critters(i, FALSE);
                  update_zone(i, FALSE);
               }
               zone_list[i].resetTicksTillRegen();
            }//if
         }//if
      }//if
   }//for
}//do_regeneration_zones


void ZoneCollection::zunlock(int znum) {
   int j;
   if ((znum >= 0) && (znum < NUMBER_OF_ZONES)) {
      for (j = zone_list[znum].getBeginRoomNum();
           j <= zone_list[znum].getEndRoomNum();
           j++) {
         room_list[j].unlock();
      }//for
   }
}//zunlock


void ZoneCollection::zlock(int znum) {
   int j;
   if ((znum >= 0) && (znum < NUMBER_OF_ZONES)) {
      for (j = zone_list[znum].getBeginRoomNum();
           j <= zone_list[znum].getEndRoomNum();
           j++) {
         room_list[j].lock();
      }//for
   }
}//zlock

void ZoneCollection::zlist(critter& pc, int start, int end) {
   String buf(100);

   Cell<String*> cll;
   for (int i = start; i<= end; i++) {
      if (zone_list[i].isInUse()) {
         zone_list[i].stat(pc);
      }//if
      else {
         Sprintf(buf, "[%i]\tTHIS ZONE UNDEFINED.\n", i);
         show(buf, pc);
      }//else
   }//for 
}//zlist

void ZoneCollection::writeWorld(critter& pc) {
   String buf(100);

   for (int i = 0; i<NUMBER_OF_ZONES; i++) {
      if (zone_list[i].isInUse()) {
         if (zone_list[i].canWriteRooms()) {
            do_write_zone(i);
         }
         else {
            Sprintf(buf,
                    "Can't write rooms in zone:  %i, it's being edited.\n",
                    i);
               show(buf, pc);
         }
         
         if (zone_list[i].canWriteMobs()) {
            do_amsave(i);
         }
         else {
            Sprintf(buf,
                    "Can't write mobs in zone: %i, mobs are being edited.\n",
                    i);
            show(buf, pc);
         }
         
         if (zone_list[i].canWriteObjects()) {
            do_aosave(i);
         }
         else {
            Sprintf(buf,
                    "Can't write objs in zone: %i, they're being edited.\n",
                    i);
            show(buf, pc);
         }
         
         if (zone_list[i].canWriteDoors()) {
            do_adsave(i);
         }
         else {
            Sprintf(buf,
                    "Can't write doors in zone: %i, they're being edited.\n",
                    i);
            show(buf, pc);
         }
         
         Sprintf(buf, "Zone %i has been written.\n", i);
         show(buf, pc);
      }//else
      else {
         Sprintf(buf, "Zone %i has not been defined yet.\n", i);
         show(buf, pc);
      }//else
   }//for
}//writeWorld


/* helper function, not directly called by player */
void ZoneCollection::writeSelf() {
#ifdef USEMYSQL
   if (config.useMySQL)
      dbWriteSelf();
   else
#endif
      fileWriteSelf();
}

void ZoneCollection::fileWriteSelf() {

   ofstream dafile("./World/ZONE_FILE");

   for (int i = 0; i<NUMBER_OF_ZONES; i++) {
      if (zone_list[i].isInUse()) {
         dafile << i << "\tBegin of zone\n";
         zone_list[i].fileWrite(dafile);
      }//if
   }//for

   dafile << "-1                END OF ZONE FILE\n" << flush;
}//write_zone_list

#ifdef USEMYSQL
void ZoneCollection::dbWriteSelf() {
   for (int i = 0; i<NUMBER_OF_ZONES; i++) {
      if (zone_list[i].isInUse()) {
         zone_list[i].dbWrite();
      }
   }
}
#endif

void ZoneCollection::createNeatoFiles() {
   String buf(100);

   for (int i = 0; i<NUMBER_OF_ZONES; i++) {
      if (zone_list[i].isInUse()) {
         Sprintf(buf, "./World/zone_%i.nto", i);
         ofstream ofile(buf);
         ofile << zone_list[i].createNeatoMapFile();
      }//if
   }//for
}//createNeatoFiles


void ZoneCollection::createNewZone(critter& pc, int num_ticks, int num_rooms,
                                   const String& name) {
   String buf(100);

           /* find the starting room */
   int start = 0, i = 0;
   for (; i<NUMBER_OF_ZONES; i++) {
      if (zone_list[i].getEndRoomNum() > start) {
         start = zone_list[i].getEndRoomNum();
      }//if
   }//for

   if ((1 + start + num_rooms) > NUMBER_OF_ROOMS) {
      show("ERROR:  there isn't room in the database.\n", pc);
      show("NUMBER_OF_ROOMS needs to be increased in externs.h.\n", pc);
      return;
   }//if

   start += 1;

   int free_zone = -1;
   for (i = 0; i< NUMBER_OF_ZONES; i++) {
      if (!zone_list[i].isInUse()) {
         free_zone = i;
         break;
      }//if
   }//for

   if (free_zone == -1) {
      show("Not enough zones in database.\n", pc);
      show("Increase NUMBER_OF_ZONES in extersn.h.\n", pc);
      return;
   }//if


   if (num_ticks < 10)
      num_ticks = 10;

                /* good to go */
   zone_list[free_zone].setName(name);
   zone_list[free_zone].setTicksInRegenCycle(num_ticks);
   zone_list[free_zone].setTicksTillRegen(num_ticks);
   zone_list[free_zone].setBeginRoomNum(start);
   zone_list[free_zone].setEndRoomNum(start + num_rooms - 1);

   Sprintf(buf, "cp ./World/DEFAULT_DOORS ./World/doors_%i", free_zone);
   system(buf);
   Sprintf(buf, "cp ./World/DEFAULT_DOORS ./World/objects_%i", free_zone);
   system(buf);
   Sprintf(buf, "cp ./World/DEFAULT_DOORS ./World/zone_%i", free_zone);
   system(buf);
   Sprintf(buf, "cp ./World/DEFAULT_DOORS ./World/critters_%i", free_zone);
   system(buf);


   show("New zone created.\n", pc);
   show("Now you should use 'zenable' to specify zone builders.\n", pc);

   writeSelf();
}//createNewZone


///*****************************************************************///
///**********************  zone class  *****************************///

int zone::_cnt = 0;

zone::zone() {
   _cnt++;
   ticks_in_regen_cycle = ticks_till_regen = 0;
   begin_room_num = end_room_num = 0;
   zone_num = 0;
}//default constructor

zone::zone(int id_num) {
   _cnt++;
   ticks_in_regen_cycle = ticks_till_regen = 0;
   begin_room_num = end_room_num = 0;
   zone_num = id_num;
}//default constructor

zone::zone(const zone& src) { //copy constructor
   _cnt++;
   ticks_in_regen_cycle = src.ticks_in_regen_cycle;
   ticks_till_regen = src.ticks_till_regen;
   begin_room_num = src.begin_room_num;
   end_room_num = src.end_room_num;
   zone_num = src.zone_num;
}//copy constructor


zone::~zone() {
   _cnt--;
   clear_ptr_list(owners);
}//~zone


/** create some output that the graph-viz program neato can use to
 * create a horribly complex looking graph of the zone!
 */
String zone::createNeatoMapFile() {
   String retval(10000);
   String buf(100);

   // This will create lots of duplicate entries, but the
   // neato program should deal with it easier than I can!
   Cell<door*> cll;
   door* ptr;

   String cur_room_name(50);
   String dest_room_name(50);

   Sprintf(retval, "graph zone_%i {\n\tpage=\"40,80\";\n\tsize=\"40,80\";\n",
           zone_num);

   for (int i = begin_room_num; i <= end_room_num; i++) {
      if (room_list.elementAtNoCreate(i)) {
         Sprintf(cur_room_name, "[%i] %S", i, &(room_list[i].short_desc));
         //spaceToNewlines(cur_room_name);

         room_list[i].doors.head(cll);
         
         while ((ptr = cll.next())) {

            if (ptr->getDestRoom()) {
               Sprintf(dest_room_name, "[%i] %S",
                       ptr->getDestRoom()->getIdNum(),
                       &(ptr->getDestRoom()->short_desc));
               //spaceToNewlines(dest_room_name);
               
               if (ptr->getDestRoom()->getZoneNum() != zone_num) {
                  Sprintf(buf, "\t\"%S\" -- \"%S\" [color=blue];\n",
                          &cur_room_name, &dest_room_name);
               }
               else {
                  Sprintf(buf, "\t\"%S\" -- \"%S\";\n", &cur_room_name,
                          &dest_room_name);
               }
               
               retval.Append(buf);
            }//if
         }//while
      }//if
   }//for

   retval.Append("}\n");
   return retval;
}//createNeatoFile


void zone::spaceToNewlines(String& str) {
   for (int i = 0; i<str.Strlen(); i++) {
      if (isspace(str[i])) {
         str.setCharAt(i, '\n');
      }//if
   }//for
}//spaceToNewlines

 
void zone::setEndRoomNum(int i) {
   if ((i >= 0) && (i < NUMBER_OF_ROOMS))
      end_room_num = i;
}
 
void zone::setBeginRoomNum(int i) {
   if ((i >= 0) && (i < NUMBER_OF_ROOMS))
      begin_room_num = i;
}


void zone::addOwner(const String& str) {
   owners.append(new String(str));
}//addOwner


int zone::removeOwner(const String& char_name) {
   Cell<String*> cll(owners);
   String* ptr;

   while ((ptr = cll.next())) {
      if (strcasecmp(*ptr, char_name) == 0) {
         String* ptr2 = ptr;
         ptr = owners.lose(cll);
         delete ptr2;
         ptr2 = NULL;
         return TRUE;
      }//if
   }//while

   return FALSE;
}//removeOwner

void zone::stat(critter& pc) {
   String buf(100);
   Cell<String*> cll;
   String* ptr;

   Sprintf(buf, "[%i]  %S  %P35 Begin#  %i, End#  %i, Ticks in Regen:  %i\n",
           zone_num, &(zone_name), begin_room_num, end_room_num,
           ticks_in_regen_cycle);
   show(buf, pc);

   show("    Owners:  ", pc);
   
   owners.head(cll);
   buf = "";
   while ((ptr = cll.next())) {
      buf.Append(*ptr);
      buf.Append(" ");
   }//while
   
   buf.Append("\n");
   pc.show(buf);
}//stat


String& zone::getFirstOwner() { //returns NONE if has none.
   if (owners.isEmpty()) {
      return UNKNOWN;
   }//if
   else {
      return *(owners.peekFront());
   }//else
}//getFirstOwner


int zone::isOwnedBy(critter& pc) {
   if (pc.isImmort()) {
      Cell<String*> cll(owners);
      String* ptr;
      
      while ((ptr = cll.next())) {
         if (strcasecmp(*ptr, *(Top(pc.names))) == 0)
            return TRUE;
      }//wile
   }//if

   return FALSE;
}//isOwnedBy


/** znum will be the number for this zone. */
int zone::Read(ifstream& dafile, int znum) {
   mudlog.log(DBG, "In zone::read.\n");
   char buf[81];

   Clear();

   if ((znum < 0) || (znum > NUMBER_OF_ZONES)) {
      mudlog << "ERROR:  znum is out of range: " << znum << endl;
      zone_num = 0;
   }//if
   else {
      zone_num = znum;
   }

   if (!dafile) {
      if (mudlog.ofLevel(ERROR)) {
         mudlog << "ERROR:  da_file FALSE in obj read." << endl;
      }
      return FALSE;
   }

                /* zone_name */
   dafile.getline(buf, 80);
   zone_name = buf;
        
                /* numeric data */
   dafile >> ticks_in_regen_cycle >> ticks_till_regen >>
                    begin_room_num >> end_room_num;
   if ((ticks_till_regen < 0) || (ticks_till_regen > ticks_in_regen_cycle)) {
      ticks_till_regen = ticks_in_regen_cycle;
   }
   dafile.getline(buf, 80);  //clear junk

   //mudlog.log(DBG, "About to read zone_flags.\n");
   zone_flags.Read(dafile);
   //mudlog.log(DBG, "read em.\n");

   short test = TRUE;
   while (test) {

      if (!dafile) {
         if (mudlog.ofLevel(ERROR)) {
            mudlog << "ERROR:  da_file FALSE in zone read." << endl;
         }
         return FALSE;
      }

      dafile >> buf;
      mudlog.log(DBG, buf);
      if (strcmp(buf, "~") == 0) {
         test = FALSE;
      }//if
      else {
         owners.append(new String(buf));
      }//else
   }//while            

   dafile.getline(buf, 80); //junk stuff at end of names

   dafile.getline(buf, 80); //junk extra line
   return TRUE;
}//Read


int zone::fileWrite(ofstream& dafile) {
   Cell<String*> st_cell(owners);
   String* st_ptr;

   dafile << zone_name << endl;
   dafile << ticks_in_regen_cycle << " " << ticks_till_regen << " "
          << begin_room_num << " " << end_room_num << endl;

   int len = 0;

   zone_flags.Write(dafile);

   while ((st_ptr = st_cell.next())) {
      len += st_ptr->Strlen() + 1;
      if (len > 79) {
         dafile << endl;
         len = 0;
      }//if
      dafile << *st_ptr << " ";
   }//while
   dafile << "~" << "\towners\n\n";
   return true;
}//fileWrite

#ifdef USEMYSQL
int zone::dbWrite() {
   Cell<String*> st_cell(owners);
   String query;
   String* st_ptr;

   query = "DELETE FROM Zones WHERE ZONE_NUM = ";
   query += zone_num;

   if (mysql_real_query(database, query, strlen(query)) !=0) {
      if (mudlog.ofLevel(WRN)) {
         mudlog << "In zone::dbWrite():\n";
         mudlog << "Eror executing query: " << mysql_error(database)
                << endl;
      }
      return FALSE;
   }

   query = "DELETE FROM ZoneOwners WHERE ZONE_NUM = ";
   query += zone_num;

   if (mysql_real_query(database, query, strlen(query)) !=0) {
      if (mudlog.ofLevel(WRN)) {
         mudlog << "In zone::dbWrite():\n";
         mudlog << "Eror executing query: " << mysql_error(database)
                << endl;
      }
      return FALSE;
   }

   query = "INSERT INTO Zones (ZONE_NUM, TICKS_IN_REGEN_CYCLE, ";
   query += "TICKS_TILL_REGEN, ZONE_NAME, BEG_ROOM_NUM, END_ROOM_NUM) VALUES ";

   query += "("; query += zone_num;             query += ", ";
                 query += ticks_in_regen_cycle; query += ", ";
                 query += ticks_till_regen;     query += ", ";
                 query += zone_name;            query += ", ";
                 query += begin_room_num;       query += ", ";
                 query += end_room_num;
   query += ")";

   if (mysql_real_query(database, query, strlen(query)) !=0) {
      if (mudlog.ofLevel(WRN)) {
         mudlog << "In zone::dbWrite():\n";
         mudlog << "Eror executing query: " << mysql_error(database)
                << endl;
      }
      return false;
   }

   query = "INSERT INTO ZoneOwners (ZONE_NUM, OWNER) VALUES ";
   while ((st_ptr = st_cell.next())) {
      query += "(";
      query += zone_num; query += ", ";
      query += *st_ptr;  query += "), ";
   }//while
   query.dropFromEnd(2);
   if (mysql_real_query(database, query, strlen(query)) !=0) {
      if (mudlog.ofLevel(WRN)) {
         mudlog << "In zone::dbWrite():\n";
         mudlog << "Eror executing query: " << mysql_error(database)
                << endl;
      }
      return false;
   }

   return true;
}
#endif

void zone::Clear() {
   zone_name.Clear();
   zone_flags.Clear();
   clear_ptr_list(owners);
   ticks_in_regen_cycle = ticks_till_regen = begin_room_num = end_room_num = 0;
   zone_num = 0;
}//clear


int zone::isTotallyLoaded() {
   int i;

   for (i = begin_room_num; i <= end_room_num; i++) {
      if (room_list.elementAtNoCreate(i) && room_list[i].isInUse()) {
         if (room_list[i].isTotalLoaded()) { //if total loaded
            return TRUE;
         }//if
            else {
            return FALSE;
         }//else
      }//if
   }//for

   if (room_list[begin_room_num].isTotalLoaded())
      return TRUE;
   else
      return FALSE;
}//isTotallyLoaded


/**  From mortal intervention, mob procs, vehicle movement.. */
int zone::isLocked() {
   int i;

   for (i = begin_room_num; i <= end_room_num; i++) {
      if (room_list.elementAtNoCreate(i) && room_list[i].isInUse()) {
         if (room_list[i].isZlocked()) { //if total loaded
            return TRUE;
         }//if
            else {
            return FALSE;
         }//else
      }//if
   }//for

   if (room_list[begin_room_num].isZlocked())
      return TRUE;
   else
      return FALSE;
}//isLocked


int zone::canWriteRooms() {
   int i;

   for (i = begin_room_num; i <= end_room_num; i++) {
      if (room_list.elementAtNoCreate(i) && room_list[i].isInUse()
          && (room_list[i].isNotComplete())) {
         return FALSE;
      }//if
   }//for

   return TRUE;

}//canWriteRooms



/**  Check to make sure there are no mobs that are only half-way 
 * constructed in OLC.
 */
int zone::canWriteMobs() {
   int i;

   for (i = 0; i < NUMBER_OF_MOBS; i++) {
      if (mob_list[i].isInUse() && mob_list[i].isNotComplete()
          && (mob_list[i].getNativeZoneNum() == zone_num)) {
         return FALSE;
      }//if
   }//for
   return TRUE;
}//canWriteMobs


/**  Check to make sure there are no doors that are only half-way 
 * constructed in OLC.
 */
int zone::canWriteDoors() {
   int i;

   for (i = 0; i < NUMBER_OF_DOORS; i++) {
      if (door_list[i].isInUse() && door_list[i].isNotComplete()
          && (door_list[i].getZoneNum() == zone_num)) {
         return FALSE;
      }//if
   }//for
   return TRUE;
}//canWriteDoors


/**  Check to make sure there are no objects that are only half-way 
 * constructed in OLC.
 */
int zone::canWriteObjects() {
   int i;

   for (i = 0; i < NUMBER_OF_ITEMS; i++) {
      if (obj_list[i].isInUse() && obj_list[i].isNotComplete()
          && (obj_list[i].getZoneNum() == zone_num)) {
         return FALSE;
      }//if
   }//for
   return TRUE;
}//canWriteObjects