musicmud-2.1.6/data/
musicmud-2.1.6/data/help/
musicmud-2.1.6/data/policy/
musicmud-2.1.6/data/wild/
musicmud-2.1.6/data/world/
musicmud-2.1.6/doc/
musicmud-2.1.6/src/ident/
musicmud-2.1.6/src/lua/
musicmud-2.1.6/src/lua/include/
musicmud-2.1.6/src/lua/src/lib/
musicmud-2.1.6/src/lua/src/lua/
musicmud-2.1.6/src/lua/src/luac/
/* 
 * MusicMUD Daemon, version 1.0
 * Copyright (C) 1998-2003 Abigail Brady
 * 
 * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 * 
 */
#include "musicmud.h"
#include "startup.h"
#include "verbs.h"
#include "Library.h"
#include "Player.h"
#include "State.h"
#include "Interpret.h"
#include "config.h"
#include "pflags.h"
#include "trap.h"
#include "misc.h"
#include "msi.h"

bool reload(const char *what) {
  code_reload = time(NULL);
  Library *w = libs->get(what);
  if (w) {
    libs->remove(*w);
    delete w;
  }
  w = new Library(what);
  if (w->is_valid()) {
    libs->add(*w);
  }
  else {
    if (w) delete w;
	return false;
  }    
  return true;
}

void handle_auto(MudObject *o, int rec) {
  if (o->nuke_me)
    return;
  if (int z=o->array_size("auto")) {
    for (int j=0;j<z;j++) {
      MudObject *t = o->array_get_object("auto", j);
      int c = o->array_get_int("auto", j, "count", 1);
      if (t) {
	while (c) {
	  MudObject *o2=clone_object(t, o, 0);
	  o2->set_bflag(FL_DESTROYONRESET, 1);
	  o2->set("zone", o->get("zone"));
	  if (o->array_get_int("auto", j, "worn", 0)) {
	    o2->set(KEY_WORNBY, o->id);
	  }
	  if (MudObject *seatfor=o->array_get_object("auto", j, "seatfor")) {
	    seatfor->set(KEY_SITON, o2->id);
	    seatfor->unset(KEY_SITONN);
	    seatfor->set_bflag(FL_SITTING, 1);
	  }
	  if (MudObject *bedfor=o->array_get_object("auto", j, "bedfor")) {
	    bedfor->set(KEY_SITON, o2->id);
	    bedfor->unset(KEY_SITONN);
	    bedfor->set_bflag(FL_SLEEPING, 1);
	  }
	  if (o->array_get_int("auto", j, "wield", 0)) {
	    o->set(KEY_WIELD, o2->id);
	  }
	  int makestate=o->array_get_int("auto", j, "state");
	  if (makestate != -1) {
	    o2->set(KEY_STATE, makestate);
	    o2->set("initstate", makestate);
	  }
	  o2->set("start", o->id);
	  o2->set_flag(FL_NOSAVE, 1);
	  if (rec)
	    handle_auto(o2, 0);
	  o2->unset("auto.count");
	  rectify_state(o2);
	  c--;
	}
      }
    }
  }
}

void reset_zone(MudObject *z)
{
  MudObject *o;
  int i;

  foreach(players, o, i)
    if (MudObject *f=o->get_object("_fighting"))
      if (streq(f->id, z->get("zone")))
	o->unset("_fighting");

  World<MudObject> things = *z->children;

  foreach((&things), o, i)
    {
      o->reset();
      rectify_state(o);

      MudObject *p;
      int j;

      if (o->get_flag(FL_QUARTERS))
	continue;

      World<MudObject> ch = *o->children;

      foreach((&ch), p, j) {
	if (!is_player(p) && p->get_object("start")!=o && !streq(p->get("zone"), z->id)
	    && !p->get_flag(FL_SHIP) && !p->get_flag(FL_WANDER) && !p->get_flag(FL_MISSION) 
	    && !p->get_flag(FL_QUEST) 
	    && !p->get_flag(FL_QUARTERS) && !p->mission) {
	  vanish(p);
	}
      }
    }
  foreach((&things), o, i)
    {
      handle_auto(o, 1);
    }
}

void doreset(const char *zm, bool a) {
  mud_reset = time(NULL);    
    if (streq(zm, "ALL")) {
      MudObject *o;
      int i;
      log(PFL_NONE, a?LEV_INTERNAL:LEV_COMMANDER, "global", "reset of ALL starting");
      foreach(zones, o, i) {
	reset_zone(o);
      }
    } else if (streq(zm, "all")) {
      MudObject *o;
      int i;
      log(PFL_NONE, a?LEV_INTERNAL:LEV_COMMANDER, "global", "reset of all starting");
      foreach(zones, o, i) {
	if (!streq(o->id, "@auto") && !streq(o->id, "@ship")) {
	  reset_zone(o);
	}
      }
    } else {
      MudObject *z = zones->get(zm);
      if (z) {
	log(PFL_NONE, a?LEV_INTERNAL:LEV_COMMANDER, "global", "reset of %s starting", z->id);
	reset_zone(z);
      }      
    }
    
    //    clock_t af = clock();
    //    printf("Reset took %f\n", ((af-n)*1.0)/CLOCKS_PER_SEC);
    log(PFL_NONE, a?LEV_INTERNAL:LEV_COMMANDER, "global", "reset complete");
}

static bool verb_codeload(MudObject *who, int argc, const char **argv) {
  if (argc<2) {
    who->printf("codeload <verbfile>\n");
	return true;
  }
  if (is_mobile(who)) {
    who->printf("Not like that.\n");
    return true;
  } 
  log(PFL_NONE, 0, "code", "reloading : %s", argv[1]);
  reload(argv[1]);
  return true;
}

static bool verb_codeunload(MudObject *who, int argc, const char **argv) {
  if (argc<2) {
    who->printf("codeunload <verbfile>\n");
	return true;
  }
  if (is_mobile(who)) {
    who->printf("Not like that.\n");
    return true;
  } 
  Library *w = libs->get(argv[1]);
  if (w) {
    log(PFL_NONE, 0, "code", "unloading : %s", argv[1]);
    libs->remove(*w);
    delete w;
  } else {
    who->printf("No such verbfile: %s\n", argv[1]);
  }
  return true;
}

static bool verb_disable(MudObject *who, int argc, const char **argv) 
{
  if (argc < 2) {
    who->printf("Disable which verb?\n");
    return true;
  }
  Verb *v = get_verb(argv[1]);
  if (!v) {
    who->printf("Can't find a matching verb.\n");
    return true;
  }
  if (streq(v->get("module"), "intrinsic")) {
    who->printf("Can't disable builtin verbs.\n");
    return true;
  }
  if (v->disabled) {
    who->printf("%#s is already disabled.\n", v->id);
    return true;
  }
  log(PFL_SEEINFO, 0, "admin", "verb %s disabled", argv[1]);
  v->disabled = 1;
  return true;
}

static bool verb_enable(MudObject *who, int argc, const char **argv) 
{
  if (argc < 2) {
    who->printf("Enable which verb?\n");
    return true;
  }
  if (streq(argv[1], "all")) {
    Verb *v;
    int i;
    int done = 0;
    foreach(verbs, v, i) {
      if (v->disabled) {
	v->disabled = 0;
	done++;
      }
    }
    if (done) {
      log(PFL_SEEINFO, 0, "admin", "all %i disabled verb%s enabled", done, done==1?"":"s");
    } else {
      who->printf("There are no disabled verbs.\n");
    }
    return true;
  }
  Verb *v = get_verb(argv[1]);
  if (!v) {
    who->printf("Can't find a matching verb.\n");
    return true;
  }
  if (!v->disabled) {
    who->printf("%#s is already enabled.\n", argv[1]);
    return true;
  }
  log(PFL_SEEINFO, 0, "admin", "verb %s enabled", v->id);
  v->disabled = 0;
  return true;
}

bool verb_reload(MudObject *who, int, const char **) {
  if (is_mobile(who)) {
    who->printf("Not like that.\n");
    return true;
  } 

  Library *l;
  int i;
  foreach(libs, l, i) {
    if (l->is_valid());
    if (strstr(l->get("pathname"), "src/extras/")) {
      struct stat foo;
      stat(l->get("pathname"), &foo);
      time_t ltime = l->get_int("loaded");
      if (ltime <= foo.st_mtime) {
	char foo[1000];
	strcpy(foo, l->id);
	log(PFL_NONE, 0, "code", "reloading : %s", foo);
	reload(foo);
      }
    }
  }

  return true;
}

void state_interpret(Player *p, const char *w) {
  MudObject *o;
  int i;
  foreach((&p->snoopers), o, i) {
    o->printf("^R*>^W%s^R<^n\n", w);
  }

  if (streq(w, "!")) {
    p->interpret(p->previous.c_str());
  } else if (strlen(w)) {
    p->previous =  w;
    p->interpret(w);
  }
}

void register_intrinsic() {
  NativeVerb *vreload = new NativeVerb("reload", 6, 0, &verb_reload, PFL_CODER);
  vreload->set("module","intrinsic");
  verbs->add(*vreload);

  NativeVerb *vcodeload = new NativeVerb("codeload", 6, 0, &verb_codeload, PFL_CODER);
  vcodeload->set("module","intrinsic");
  verbs->add(*vcodeload);

  NativeVerb *vcodeunload = new NativeVerb("codeunload", 6, 0, &verb_codeunload, PFL_CODER);
  vcodeunload->set("module","intrinsic");
  verbs->add(*vcodeunload);

  NativeVerb *venable = new NativeVerb("enable", 6, 0, &verb_enable, PFL_CODER);
  venable->set("module","intrinsic");
  verbs->add(*venable);

  NativeVerb *vdisable = new NativeVerb("disable", 6, 0, &verb_disable, PFL_CODER);
  vdisable->set("module","intrinsic");
  verbs->add(*vdisable);

  states->add(* new State("cmd", "%x>",
			  state_interpret));
}

void init_vectors() {
  libs = new World<Library>(); 
  verbs = new World<Verb>(); 
  states = new World<State>(); 
  planet = new Global(); 
  zones = new World<MudObject>(); 
  interpreters = new World<Interpreter>(); 
  players = new World<Player>();
}

void init_world() {
  mud = new MudObject("@musicmud");
  mud->set("short", "musicmud");
  mud->set("name", "the MusicMud");
  mud->set("desc", "Um, what can you say about the root object?\n");
  mud->set("plan.shutdown", "10 announce Shutting down in 10 seconds.;10 shutdown");
  game_mobiles = 1;
  planet->add(*mud);
  
  MudObject *sys = new MudObject("system_zone");
  sys->set("short", "system_zone");
  sys->set("name", "The System Zone");
  sys->set("desc", "This is the zone in which intrinsic objects are kept.");
  sys->set("owner", "@musicmud");
  sys->set_bflag(FL_FIXED, 1);
  planet->add(*sys);
  
  MudObject *empty = new MudObject("empty");
  empty->set("short", "empty");
  empty->set("name", "the Empty Room");
  empty->set("desc", "This is the Void.");
  empty->set("owner", "system_zone");
  empty->set_bflag(FL_FIXED, 1);
  planet->add(*empty);

  MudObject *space = new MudObject("space");
  space->set("short", "space");
  space->set("name", "Space");
  space->set("namestyle", 2);
  space->set("desc", "This is deep Space.");
  space->set("zone", "@space");
  space->set("owner", "system_zone");
  space->set("planet", "Space");
  space->set_bflag(FL_DEEPSPACE, 1);
  space->set_bflag(FL_AIRLESS, 1);
  space->set_bflag(FL_NOGRAVITY, 1);
  space->set_bflag(FL_FIXED, 1);
  planet->add(*space);
  
}