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 - Creation module
 * 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 <string.h>
#include <ctype.h>

#include "musicmud.h"
#include "util.h"
#include "verbs.h"
#include "State.h"
#include "Player.h"
#include "misc.h"
#include "wordwrap.h"
#include "pflags.h"

#define MODULE "make"

#define MAGIC_INT_STATE(funcname, property, nextstate, min) \
static void funcname(Player *who, const char *what) { \
	if (!what) return; if (!*what) { who->pop_state(); return; } \
	int value = atoi(what);	if (value >= min) { \
		who->set(property, value); \
		who->set_state(nextstate); \
	} else { who->printf("A value higher than %i, please.\n", min-1); } }

#define MAGIC_STR_STATE(funcname, property, nextstate) \
static void funcname(Player *who, const char *what) { \
	if (!what) return; if (!*what) { who->pop_state(); return; } \
		who->set(property, what); \
		who->set_state(nextstate); \
     }


static const char *make_id(const char *zone, const char *abbrv) {
  int i = 1;
  static char temp[1024];
  while (1) {
    if (abbrv) sprintf(temp, "%s_%s_%i", zone, abbrv, i); else
    sprintf(temp, "%s_%i", zone, i);
    if (planet->get(temp)==0) return temp;
    i++;
  }
}

static void state_make(Player *, const char *);

static void set_make_state(Player *who) {
  who->push_state("make");
  who->printf("^M Multi-Environment Creation System\n");
  who->printf("^B----------------------------------\n");
  who->printf("^R1  ^m- ^GCreate Object^n\n");
  who->printf("^R2  ^m- ^GCreate Exit^n\n");
  who->printf("^R3  ^m- ^GCreate Room^n\n");
  who->printf("^R4  ^m- ^GCreate Action^n\n");
  who->printf("^R5  ^m- ^GCreate Mobile^n\n");
  who->printf("^R6  ^m- ^GCreate Door^n\n");
  who->printf("^R7  ^m- ^GCreate Zone^n\n");
  who->printf("^R8  ^m- ^GCreate Quest^n\n");
  who->printf("^R99 ^m- ^GRedisplay Options^n\n");
}

static void state_make_quest_name(Player *who, const char *cmd)
{
  if (!*cmd) {
    who->pop_state();
    return;
  }

  const char *c = cmd;
  string lower = "";
  while (*c) {
    if (!isalpha(*c)) {
      who->printf("You can only use letters in a quest name.\n");
      return;
    }
    lower += tolower(*c);
    c++;
  }

  if (find_questob(cmd)) {
    who->printf("There is already a quest called that.\n");
    return;
  }

  string q = cmd;
  q[0] = toupper(q[0]);

  who->get_person_state()->set("questname", q);
  who->get_person_state()->set("questtag", lower);
  who->set_state("make.quest.zone");
}

static void state_make_quest_zone(Player *who, const char *what) {
  if (what && *what)
    who->get_person_state()->set("zone", what);
  else {
    who->pop_state();
    return;
  }
  if (!cantouch_zone(who, what)) {
    who->printf("You aren't authorised to change : %s\n", who->get("!make.object.zone"));
    who->pop_state();
    return;
  }
  who->set_state("make.quest.confirm");
}

static void state_make_quest_confirm(Player *who, const char *what)
{
  if (yes(what)) {
    PersonState *ps = who->get_person_state();
    MudObject *o = new MudObject(ssprintf("quest_%s", ps->get("questtag")).c_str());
    planet->add(o);
    o->set_bflag(FL_QUEST, 1);
    o->set("short", "mission");
    o->set("name", "a ^omission^n");
    o->set("mass", 50);
    o->set("mname", ps->get("questname"));
    o->set("zone", ps->get("zone"));
    o->set("questpoints", 0);
    set_owner(o, "quest_zone");
    if (!o->owner)
      set_owner(o, mud);
    log(PFL_SEEINFO, 0, "make", "new quest : %s", o->id);
    who->pop_state();
  }
  if (no(what)) {
    who->pop_state();
  }
}

static bool verb_make(Player *who, int argc, const char **argv) {
  if (argc > 1) {
    if (streq(argv[1], "room")) { who->push_state("make.room.zone"); }
    else if (streq(argv[1], "object")) { who->push_state("make.object.short"); }
    else if (streq(argv[1], "exit")) { who->push_state("make.exit.direction"); }
    else if (streq(argv[1], "action")) { state_make(who, "4"); }
    else if (streq(argv[1], "mobile")) { who->push_state("make.mobile.zone"); }
    else if (streq(argv[1], "door")) { who->push_state("make.door.zone"); }
    else if (streq(argv[1], "zone")) { who->push_state("make.zone"); }
    else if (streq(argv[1], "quest")) { who->push_state("make.quest.name"); }
  } else {
    set_make_state(who);
  }
  who->oprintf("%#M is making.\n", who);
  return true;
}

static void state_make(Player *who, const char *what) {
	int value = atoi(what);
	if (value == 1) {
	  who->set_state("make.object.short");
  } else if (value ==2 ) {
	  who->set_state("make.exit.direction");
  } else if (value == 3) {
	  who->set_state("make.room.zone");
	  who->printf("default zone == %s\n", who->owner->get("zone"));
  } else if (value == 4) {
	  who->interpret("addaction");
  } else if (value == 5) {
	  who->set_state("make.mobile.zone");
  } else if (value == 6) {
	  who->set_state("make.door.zone");
  } else if (value == 7) {
	  who->set_state("make.zone");
  } else if (value == 8) {
	  who->set_state("make.quest.name");
  } else if (value == 99) {
          who->pop_state();
          set_make_state(who);
  } else {
    who->pop_state();
  }
}

static void state_zone(Player *who, const char *what) {
    if (!what) return;
    if (!*what) {
	who->pop_state();
	return;
    }
    
    if (zones->get(what)) {
	who->printf("Zone called that already exists.\n");
	who->pop_state();
	return;
    }

    if (!isalpha(what[0])) {
      who->printf("Zone names must start with letters.\n");
      who->pop_state();
      return;
    }

    char name[256];
    sprintf(name, "%s_zone", what);

    const char *l = what;

    while (*l) {
      if (!isalnum(*l) || isupper(*l)) {
	who->printf("Zones must contain only lowercase letters or digits in their names.\n");
	who->pop_state();
	return;
      }
      l++;
    }

    if (planet->get(name)) {
      who->printf("A zone is already called that.\n");
      who->pop_state();
      return;
    }

    MudObject *zo = new MudObject(name);
    zo->set("owner", "@musicmud");
    planet->add(*zo);
    zo->set("short", name);
    zo->set("name", name);
    zo->set("desc", "Hello. This is a zone.\n");
    zo->set("zone", what);
    log(PFL_SEEINFO, 0, "make", "new zone : %s", what);
    zo->set("author", who->id);
    zo->set_bflag(FL_FIXED, 1);
    who->pop_state();
}

static void state_make_mobile_zone(Player *who, const char *what) {
	if (!what) {
		who->printf("Default zone : %s\n", who->owner->get("zone"));
		return;
	}
	if (!*what) {
		who->set("!make.mobile.zone", who->owner->get("zone"));
	} else
		who->set("!make.mobile.zone", what);
	if (!cantouch_zone(who, who->get("!make.mobile.zone"))) {
		who->printf("You aren't authorised to change : %s\n", who->get("!make.mobile.zone"));
		who->pop_state();
		return;
	}
	who->set_state("make.mobile.short");
}

static void state_make_mobile_short(Player *who, const char *what) {
	if (!what) return;
	
	if (!*what) { who->pop_state(); return; }

	if (strchr(what, ' ')) {
		who->printf("Short names should not have spaces.\n");
		return;
	}
	
	string q = make_lower(what);

	who->set("!make.mobile.short", q);
	who->set_state("make.mobile.name");
}

static void state_make_mobile_name(Player *who, const char *what) {
	if (!what) return;
	
	if (!*what) { who->pop_state(); return; }
	
	who->set("!make.mobile.name", what);
	who->set_state("make.mobile.hardness");

	who->printf("Hardness can be : boss, very, hard, medium, easy, unarmed, child, animal, bug.\n");
}


static void state_make_mobile_hardness(Player *who, const char *what) {
	if (!what) return;
	
	if (!*what) { who->pop_state(); return; }
	
	who->set("!make.mobile.hardness", what);
	who->set_state("make.mobile.wander");
}



static void state_make_mobile_wander(Player *who, const char *what) {
  if (what) {
    if (yes(what)) {
      who->set("!make.mobile.wander", 1);
      who->set_state( "make.mobile.gender");
    } else if (no(what)) {
      who->set("!make.mobile.wander", 0);
      who->set_state( "make.mobile.gender");
    }
  }
}

static void state_make_mobile_gender(Player *who, const char *what) {
  if (what) {
      who->set("!make.mobile.gender", what);
      who->set_state("make.mobile.tellname");
  }
}

MAGIC_STR_STATE(state_make_mobile_tellname,
			"!make.mobile.tellname",
			"make.mobile.telljob")

MAGIC_STR_STATE(state_make_mobile_telljob,
			"!make.mobile.telljob",
			"make.mobile.tellmission")

MAGIC_STR_STATE(state_make_mobile_tellmission,
			"!make.mobile.tellmission",
			"make.mobile.tellhelp")

MAGIC_STR_STATE(state_make_mobile_tellhelp,
			"!make.mobile.tellhelp",
			"make.mobile.tellfollow")

MAGIC_STR_STATE(state_make_mobile_tellfollow,
			"!make.mobile.tellfollow",
			"make.mobile.confirm")


  enum {
    MT_BOSS,    MT_VERY,    MT_HARD,
    MT_TOUGH,   MT_MEDIUM,  MT_EASY,    MT_UNARMED,
    MT_CHILD,   MT_ANIMAL,  MT_BUG,
  };

struct mstat {
  int hp;
  int dex;
  int str;
  int skill;
  int damage;
};

struct mstat stats[] = 
{
  { 200, 40, 40, 100, 40 }, /* boss (was very) */
  { 200, 30, 30,  80, 30 }, /* very (was hard) */
  { 200, 20, 20,  70, 30 }, /* hard */
  { 200, 20, 20,  60, 25 }, /* tough */
  { 200, 20, 20,  50, 20 }, /* medium */
  { 200, 15, 15,  25, 10 }, /* easy */
  { 200, 10, 10,   0, 10 }, /* unarmed */
  { 100, 10, 10,   0,  5 }, /* child */
  {  50, 10, 10,   0,  5 }, /* animal */
  {  10, 10, 10,   0,  2 }}; /* bug */

static int matchmob(const char *name) {
  //  if (streq(name, "fucking")) return MT_BOSS;
  if (streq(name, "copper"))  return MT_BOSS;
  if (streq(name, "boss"))    return MT_BOSS;
  if (streq(name, "very"))    return MT_VERY;
  if (streq(name, "hard"))    return MT_HARD;
  if (streq(name, "tough"))  return MT_TOUGH;
  if (streq(name, "medium"))  return MT_MEDIUM;
  if (streq(name, "officer"))  return MT_MEDIUM;
  if (streq(name, "easy"))    return MT_EASY;
  if (streq(name, "unarmed")) return MT_UNARMED;
  if (streq(name, "child"))   return MT_CHILD;
  if (streq(name, "animal"))  return MT_ANIMAL;
  if (streq(name, "bug"))     return MT_BUG;
  return MT_UNARMED;
}

static void state_make_mobile_confirm(Player *who, const char *what) {
  if (what) {
    if (yes(what)) {
	
	MudObject *obj = 
	    new MudObject(
			  make_id
			  (who->get("!make.mobile.zone"),
			   who->get("!make.mobile.short")));
	
	obj->set("short", who->get("!make.mobile.short"));

	const char *name = who->get("!make.mobile.name");
	const char *noart = remove_articles(name);
	
	if (noart==name) {
	  obj->setf("name", "^P%s^n", name);
	} else {
	  obj->setf("name", "%s ^P%s^n", string(name, noart-1), noart);
	}

	obj->set("start", who->owner->id);
	set_owner(obj, who->owner->id);
	obj->set("zone", who->get("!make.mobile.zone"));
	obj->set("gender", who->get("!make.mobile.gender"));
	obj->set_flag(FL_WANDER, who->get_int("!make.mobile.wander"));

	int which = matchmob(who->get("!make.mobile.hardness"));
	
	obj->set(KEY_STRENGTH, stats[which].hp);
	obj->set("maxstrength", stats[which].hp);

	obj->set("att.dex", stats[which].dex);
	obj->set("att.str", stats[which].str);
	obj->set("skill.combat", stats[which].skill);
	obj->set("damage", stats[which].damage);

	obj->set("hardness", who->get("!make.mobile.hardness"));

	obj->set("tell.name", who->get("!make.mobile.tellname"));
	obj->set("tell.job", who->get("!make.mobile.telljob"));
	obj->set("tell.mission", who->get("!make.mobile.tellmission"));
	obj->set("tell.help", who->get("!make.mobile.tellhelp"));
	obj->set("tell.follow", who->get("!make.mobile.tellfollow"));

	obj->set_flag(FL_FIXED, 1);
	obj->set_flag(FL_MOBILE, 1);
	obj->unreset();
	
	planet->add(*obj);

	log(PFL_SEEINFO, 0, "make", "new mobile : %s", obj->id);

	who->printf("Mobile created with id %s...\n", obj->id);
    }
  }
  who->pop_state();
}

static string tstring(const char *a, const char *b, const char *c) {
  string t = a;
  t+=b;
  t+=c;
  return t;
}

static void state_make_object_short(Player *who, const char *what) {
  if (!what || !*what) {
    who->pop_state();
    return;
  }

  if (strchr(what, ' ')) {
    who->printf("Short names should not have spaces.\n");
    return;
  }
  
  string q = make_lower(what);

  who->set("!make.object.short", q);
  who->set_state("make.object.name");

  string temp;
  if (isvowel(what[0]))
    temp = tstring("an ^o", what, "^n");
  else
    temp = tstring("a ^o" , what ,"^n");

  who->set("!make.object.name", temp.c_str());

  who->printf("default name = %s\n", temp.c_str());
}


static bool valid_name(const char *what) {
	int percents=0;
	while (true) {
		switch (*what) {
		 case 0: return true;
		 case '%': 
				{
					what++;
					if (percents) return false;
					percents++;
					if (*what!='s') return false;
					break;
				}
		}
		what++;
	}
}

static void state_make_object_name(Player *who, const char *what) {
  if (what && *what) {
	  if (valid_name(what)) {
		  char shortish[256];
		  sprintf(shortish, "^o%s^n", who->get("!make.object.short"));
		  char buffer[256];
		  sprintf(buffer, what, shortish);
		  who->set("!make.object.name", buffer);
	  } else {
		  who->printf("name not valid for some reason..\n");
		  return;
	  }
  }
  who->set_state( "make.object.start");
  who->set("!make.object.start", who->owner->id);
  who->printf("default start = %s\n", who->owner->id);
}

static void state_make_object_start(Player *who, const char *what) {
  if (what && *what)
    who->set("!make.object.start", what);
  who->set_state( "make.object.zone");
  who->set("!make.object.zone", who->owner->get("zone"));
  who->printf("default zone = %s\n", who->get("!make.object.zone"));
}

static void state_make_object_zone(Player *who, const char *what) {
  if (what && *what)
		who->set("!make.object.zone", what);
  if (!cantouch_zone(who, who->get("!make.object.zone"))) {
	  who->printf("You aren't authorised to change : %s\n", who->get("!make.object.zone"));
	  who->pop_state();
	  return;
  }
  who->set_state( "make.object.container");
}

static void state_make_object_container(Player *who, const char *what) {
  if (what) {
    if (yes(what)) {
      who->set("!make.object.container", 1);
      who->set_state( "make.object.fixed");
    } else if (no(what)) {
      who->set("!make.object.container", 0);
      who->set_state( "make.object.fixed");
    }
  }
}

static void state_make_object_fixed(Player *who, const char *what) {
  if (what) {
    if (yes(what)) {
      who->set("!make.object.fixed", 1);
      who->set_state( "make.object.confirm");
    } else if (no(what)) {
      who->set("!make.object.fixed", 0);
      who->set_state( "make.object.confirm");
    }
  }
}

static void state_make_object_confirm(Player *who, const char *what) {
  if (what) {
    if (yes(what)) {
      
      MudObject *obj = new MudObject(make_id(who->get("!make.object.zone"), who->get("!make.object.short")));
      
      obj->set("short", who->get("!make.object.short"));
      obj->set("name", who->get("!make.object.name"));
      obj->set("start", who->get("!make.object.start"));
      set_owner(obj, who->get("!make.object.start"));
      obj->set("zone", who->get("!make.object.zone"));
      obj->set_flag(FL_CONTAINER, who->get_int("!make.object.container"));
      obj->set_flag(FL_FIXED, who->get_int("!make.object.fixed"));
		
      obj->unreset();
      planet->add(*obj);

      log(PFL_SEEINFO, 0, "make", "new object : %s", obj->id);
      
      who->printf("Object created with id %s...\n", obj->id);
      who->printf("Editing examination description...\n");

      who->pop_state();
      who->interpretf("description %s", obj->id);
      return;
    }
  }
  who->pop_state();
}


static const char *expand_dir(const char *dir) {
  if (streq(dir, "n")) return "north";
  if (streq(dir, "s")) return "south";
  if (streq(dir, "e")) return "east";
  if (streq(dir, "w")) return "west";
  if (streq(dir, "u")) return "up";
  if (streq(dir, "d")) return "down";
  if (streq(dir, "a")) return "anticlockwise";
  if (streq(dir, "r")) return "rimwards";
  if (streq(dir, "h")) return "hubwards";
  if (streq(dir, "c")) return "clockwise";
  if (streq(dir, "i")) return "in";
  if (streq(dir, "o")) return "out";
  return dir;
}

static void state_make_exit_direction(Player *who, const char *what) {
  if (what && *what) {
    who->set("!make.exit.direction", expand_dir(what));
    who->set_state( "make.exit.start");
    who->set("!make.exit.start", who->owner->id);
    who->printf("default start = %s\n", who->owner->id);
  } else {
    who->pop_state();
  }
}

static void state_make_exit_start(Player *who, const char *what) {
  if (what && *what) {
    who->set("!make.exit.start", what);
  }
  Object *owner = planet->get(who->get("!make.exit.start"));
  if (owner) {
    who->set("!make.exit.zone", owner->get("zone"));
    who->set_state( "make.exit.zone");
    who->printf("default zone = %s\n", owner->get("zone"));
  } else {
    who->printf("Cant find that room!\n");
  }
}

static void state_make_exit_zone(Player *who, const char *what) {
  if (what && *what) {
    who->set("!make.exit.zone", what);
  }
  if (!cantouch_zone(who, who->get("!make.exit.zone"))) {
    who->printf("You aren't authorised to change : %s\n", who->get("!make.exit.zone"));
    who->pop_state();
    return;
  }
  if (who->get_object("lastmaderoom")) {
    who->printf("Default destination is %s.\n", who->get("lastmaderoom"));
  }
  who->set_state( "make.exit.destination");
}


static void state_make_exit_destination(Player *who, const char *what) {
  if (what && *what) {
    if (!planet->get(what)) {
      who->printf("Cannot find location : %s\n", what);
      who->pop_state();
      return;
    }
    who->set("!make.exit.destination", what);
  } else {
    MudObject *lmr = who->get_object("lastmaderoom");
    if (!lmr) {
      who->pop_state();
      return;
    } else 
      who->set("!make.exit.destination", lmr->id);
  }
  
  if (what[0]==':' || what[0]=='@') {
    MudObject *dest = planet->get(what);
    MudObject *from = who->get_object("!make.exit.start");
    who->set("!make.exit.reverse", 0);
    who->printf("One-way link from %M to %M?\n", from, dest);
    who->set_state( "make.exit.confirm");
  }
  else
    who->set_state( "make.exit.reverse");
}

static void state_make_exit_reverse(Player *who, const char *what) {
  MudObject *dest = who->get_object("!make.exit.destination");
  MudObject *from = who->get_object("!make.exit.start");

  if (yes(what)) {
    who->printf("Join %M and %M?\n", from, dest);
    who->set("!make.exit.reverse", 1);
    who->set_state( "make.exit.confirm");
  } else if (no(what)) {
    who->printf("One-way from %M to %M?\n", from, dest);
    who->set("!make.exit.reverse", 0);
    who->set_state( "make.exit.confirm");
  }
}

static void state_make_exit_confirm(Player *who, const char *what) {
  if (yes(what)) {
    char identity[4096];
    sprintf(identity, "%s_%s", who->get("!make.exit.start"), who->get("!make.exit.direction"));
    
    if (planet->get(identity)) {
      who->printf(
		  "Can't create unique id : exit called %s already exists.\n"
		  , identity);
      return;
    }
    
    MudObject *x = new MudObject(identity);
    set_owner(x, who->get("!make.exit.start"));
    x->set("short", who->get("!make.exit.direction"));
    x->set("link", who->get("!make.exit.destination"));
    if (x->owner)
      x->set("start", x->owner->id);
    x->set("zone", planet->get(who->get("!make.exit.start"))->get("zone"));
    x->set_flag(FL_EXIT, 1);
    x->set_rflag(FL_EXIT, 1);
    
     x->unreset();
    planet->add(*x);
    log(PFL_SEEINFO, 0, "make", "new exit : %s", x->id);
    
    if (who->get_int("!make.exit.reverse")==1) {
      
      const char *other = other_dir(x->get("short"));
      
      if (other) {
	
	sprintf(identity, "%s_%s", who->get("!make.exit.destination"), other);
	
	if (!planet->get(identity)) {
	  
	  MudObject *y = new MudObject(identity);
	  
	  set_owner(y, who->get("!make.exit.destination"));
	  y->set("link", x->owner->id);
	  if (y->owner)
	    y->set("start", y->owner->id);
	  y->set("short", other);
	  y->set("zone", planet->get(who->get("!make.exit.destination"))->get("zone"));
	  y->set_flag(FL_EXIT, 1);
	  
          y->unreset();
	  planet->add(*y);
	  log(PFL_SEEINFO, 0, "make", "new reverse exit : %s", y->id);
	  
	  who->printf("Creating exit going the other way.\n");
	  
	}
      }
    }
    
    
    who->pop_state();
  }
  
  else if (no(what)) {
    who->pop_state();
  }
}



static void state_make_room_zone(Player *who, const char *what) {
  if (what && *what) {
    who->set("!make.room.zone", what);
  } else {
    who->set("!make.room.zone", who->owner->get("zone"));
  }
  if (!cantouch_zone(who, who->get("!make.room.zone"))) {
	  who->printf("You aren't authorised to change : %s\n", who->get("!make.room.zone"));
	  who->pop_state();
	  return;
  }
  who->set_state( "make.room.name");
}


static void state_make_room_name(Player *who, const char *what) {
  if (what && *what) {
    who->set("!make.room.name", what);
    who->set_state( "make.room.confirm");
    
    who->printf("Room id will probably be : %s\n", (const char *)(make_id(who->get("!make.room.zone"), 0)));
					     
  } else {
    who->pop_state();
  }
}


static void state_make_room_confirm(Player *who, const char *what) {
  if (what) {
    if (yes(what)) {
      
      MudObject *obj = new MudObject(make_id(who->get("!make.room.zone"), 0));

      char start[2048];
      sprintf(start, "%s_zone", who->get("!make.room.zone"));
      
      obj->set("name", who->get("!make.room.name"));
      obj->set("zone", who->get("!make.room.zone"));
      obj->set("start", start);
      obj->set("desc", "Description not here yet.");
      obj->set_bflag(FL_ROOM, 1);
      obj->set_bflag(FL_FIXED, 1);
      set_owner(obj, start);
      
      who->pop_state();

      obj->unreset();
      planet->add(*obj);

      log(PFL_SEEINFO, 0, "make", "new room : %s", obj->id);

      who->printf("Room created with %s...\n", obj->id);

      who->set("lastmaderoom", obj->id);

      who->printf("Editing description...\n");
      who->interpretf("description %s", obj->id);
      return;
    }
  }
  who->pop_state();
}


static void state_make_door_zone(Player *who, const char *what) {
    if (what && *what)
	who->set("!make.door.zone", what);
    else
	who->set("!make.door.zone", who->owner->get("zone"));
    if (!cantouch_zone(who, who->get("!make.door.zone"))) {
	who->printf("Sorry, you can't modify %s zone.\n", who->owner->get("zone"));
	who->pop_state();
	return;
    }
    who->printf("Default : %s.\n", who->owner->id);
    who->set_state("make.door.start1");
}

static void state_make_door_start1(Player *who, const char *what) {
  if (what && *what) 
    who->set("!make.door.start1", what);
  else 
    who->set("!make.door.start1", who->owner->id);
  who->set_state("make.door.dir1");
}

static void state_make_door_dir1(Player *who, const char *what) {
  if (!what || !*what) {
    who->pop_state();
    return;
  }
  string a = who->get("!make.door.start1");
  a += "_";
  a += expand_dir(what);
  if (planet->get(a.c_str()))
    who->set("!make.door.dir1", a.c_str());
  who->set_state("make.door.start2");
}

static void state_make_door_start2(Player *who, const char *what) {
  if (what && *what) 
    who->set("!make.door.start2", what);
  else
    who->set("!make.door.start2", who->owner->id);
  who->set_state("make.door.dir2");
}

static void state_make_door_dir2(Player *who, const char *what) {
  if (!what || !*what) {
    who->pop_state();
    return;
  }
  string a = who->get("!make.door.start2");
  a += "_";
  a += expand_dir(what);
  if (planet->get(a.c_str()))
    who->set("!make.door.dir2", a.c_str());
  who->set_state("make.door.confirm");
}

static void state_make_door_confirm(Player *who, const char *what) {
  if (yes(what)) {

    if (!planet->get(who->get("!make.door.start1"))) {
      who->printf("Cannot find : %s\n", who->get("!make.door.start1"));
      who->pop_state();
      return;
    }
    if (!planet->get(who->get("!make.door.start2"))) {
      who->printf("Cannot find : %s\n", who->get("!make.door.start2"));
      who->pop_state();
      return;
    }

    string id1 = make_id(who->get("!make.door.zone"), "door");
    MudObject *ob1 = new MudObject(id1.c_str());
    planet->add(*ob1);
    log(PFL_SEEINFO, 0, "make", "new door : %s", ob1->id);

    string id2 = make_id(who->get("!make.door.zone"), "door");
    MudObject *ob2 = new MudObject(id2.c_str());
    planet->add(*ob2);
    log(PFL_SEEINFO, 0, "make", "new door : %s", ob2->id);

    ob1->set("short", "door");
    ob1->set("name", "a ^odoor^n");
    ob1->set("desc", "It is a door.");
    ob1->set("zone", who->get("!make.door.zone"));
    ob1->set("other", id2.c_str());
    ob1->set(KEY_STATE, 0);
    ob1->set("initstate", 0);
    ob1->set("owner", who->get("!make.door.start1"));
    ob1->set("start", who->get("!make.door.start1"));
    ob1->set_flag(FL_CANOPEN, 1);
    ob1->set_flag(FL_FIXED, 1);

    ob2->set("short", "door");
    ob2->set("name", "a ^odoor^n");
    ob2->set("desc", "It is a door.");
    ob2->set("zone", who->get("!make.door.zone"));
    ob2->set("other", id1.c_str());
    ob2->set(KEY_STATE, 0);
    ob2->set("initstate", 0);
    ob2->set("owner", who->get("!make.door.start2"));
    ob2->set("start", who->get("!make.door.start2"));
    ob2->set_flag(FL_CANOPEN, 1);
    ob2->set_flag(FL_FIXED, 1);

      ob1->unreset();
      ob2->unreset();
    
    
    if (Object *x1 = planet->get(who->get("!make.door.dir1"))) {
      x1->set("door", id1.c_str());
    }

    if (Object *x2 = planet->get(who->get("!make.door.dir2"))) {
      x2->set("door", id2.c_str());
    }

    who->pop_state();

  } else if (no(what)) {
    who->pop_state();
  }
}
#if 0
bool verb_wordwrap(MudObject *who, int argc, const char **argv) {
    if (argc != 2) {
	who->printf("syntax: wordwrap <what>\n");
	return true;
    }
    Object *what = planet->get(argv[1]);
    if (streq(argv[1], "me")) what = who;
    if (streq(argv[1], "here")) what = who->owner;
    if (!what) {
	who->printf("cannot find object called : %s\n", argv[1]);
	return true;
    }
    if (cantouch_zone(who, what->get("zone")) || what == who) {
        char desc[4096];
	wordwrap(desc, what->get("desc"), 80, 0, 4096);
	what->set("desc", desc);
    } else {
	who->printf("You don't have rights to modify that zone.\n");
    }
    return true;
}

bool verb_unwordwrap(MudObject *who, int argc, const char **argv) {
    if (argc != 2) {
	who->printf("syntax: unwordwrap <what>\n");
	return true;
    }
    Object *what = planet->get(argv[1]);
    if (streq(argv[1], "me")) what = who;
    if (streq(argv[1], "here")) what = who->owner;
    if (!what) {
	who->printf("cannot find object called : %s\n", argv[1]);
	return true;
    }
    if (cantouch_zone(who, what->get("zone")) || what == who) {
	char desc[4096];
	unwordwrap(desc, what->get("desc"), 4096);
	what->set("desc", desc);
    } else {
	who->printf("You don't have rights to modify that zone.\n");
    }
    return true;
}
#endif
#if 0
bool verb_wrapzone(MudObject *who, int argc, const char **argv) {
    if (argc < 2) {
	who->printf("syntax : wrapzone <zone>\n");
	return true;
    }
    int i;
    Object *o;
    foreach(planet, o, i) {
	if (streq(o->get("zone"), argv[1])) {
	    if (o->get("desc")) {
	       char desc[4096];
	       wordwrap(desc, o->get("desc"), 80, 0, 4096);
	       o->set("desc", desc);
	    }
	}
    }
    return true;
}
#endif
#if 0
bool verb_hard(MudObject *who, int argc, const char **argv)
{
  if (argc < 3) {
    who->printf("Hard <id> <how>\n");
    return true;
  }
  MudObject *what = planet->get(argv[1]);
  if (!what) {
    who->printf("Can't find %s.\n", argv[1]);
    return true;
  }
  what->set("hardness", argv[2]);
  //  int which = matchmob(argv[2]);
  return true;
}

bool verb_cbalance(MudObject *who, int argc, const char **argv)
{
  MudObject *obj;
  int i;
  foreach(planet, obj, i) if (is_mobile(obj)) {
    const char *h = obj->get("hardness");
    if (h) {
      int which = matchmob(h);
      obj->set(KEY_STRENGTH, stats[which].hp);
      obj->set("maxstrength", stats[which].hp);
      obj->set("att.dex", stats[which].dex);
      obj->set("att.str", stats[which].str);
      obj->set("skill.combat", stats[which].skill);
      obj->set("damage", stats[which].damage);
      obj->unset("armour");
      //      who->printf("%s is %s.\n", obj->id, h);
      if (streq(h, "copper"))
	obj->set_priv(PFL_IMMORTAL, 1);
    } else {
      who->printf("%s has no hardness set.\n", obj->id);
    }
  }
  return true;
}
#endif

#include "verbmodule.h"

/* 
 *
 *  object types are
 *
 *     normal          container/empty  clothing  weapon  food/drink  key
 *     scenery  chute  fixedcontainer  
 *
 *     scenery includes floor
 *
 */

//        AUTO_VERB(hard, 4, 0, PFL_GOD);
//        AUTO_VERB(cbalance, 4, 0, PFL_GOD);

void startup() {

        AUTO_VERB(make, 4, 0, PFL_MAKE);
        ADD_ALIAS(create, 4, make);
    
   //     AUTO_VERB(wordwrap, 4, 0, PFL_MAKE);
   //     AUTO_VERB(wrapzone, 8, 0, PFL_MAKE);

        ADD_STATE("make", "^RMECS^G>^n", state_make, false);

#define MOB_ADD(what) ADD_STATE("make.mobile."#what, \
                                "Mobile " #what " : ", \
                                 state_make_mobile_##what, 0) 

    MOB_ADD(zone);
    MOB_ADD(short);
    MOB_ADD(name);
    MOB_ADD(hardness);
    MOB_ADD(wander);
    MOB_ADD(confirm);
    MOB_ADD(gender);
    MOB_ADD(tellname);
    MOB_ADD(telljob);
    MOB_ADD(tellmission);
    MOB_ADD(tellhelp);
    MOB_ADD(tellfollow);

    ADD_STATE("make.object.short", "Object short : ",  state_make_object_short, false);
    ADD_STATE("make.object.name", "Object name : ",    state_make_object_name, false);
    ADD_STATE("make.object.start", "Object start : ",  state_make_object_start, false);
    ADD_STATE("make.object.zone", "Object zone : ",    state_make_object_zone, false);
    ADD_STATE("make.object.container", "Is the Object A Container? : ", 
			  state_make_object_container, false);
    ADD_STATE("make.object.fixed", "Is the Object Fixed? : ", 
			  state_make_object_fixed, false);
	ADD_STATE("make.object.confirm", "Confirm Object? : ", 
			  state_make_object_confirm, false);

	ADD_STATE("make.quest.name", "Quest name? : ", state_make_quest_name, 0);
	ADD_STATE("make.quest.zone", "Quest zone? : ", state_make_quest_zone, 0);
	ADD_STATE("make.quest.confirm", "Confirm quest? : ", state_make_quest_confirm, 0);


	ADD_STATE("make.exit.direction", "Exit Direction : ", state_make_exit_direction, false);
	ADD_STATE("make.exit.start", "Exit Start : ", state_make_exit_start, false);
	ADD_STATE("make.exit.zone", "Exit Zone : ", state_make_exit_zone, false);
	ADD_STATE("make.exit.destination", "Exit Destination : ", state_make_exit_destination, false);
	ADD_STATE("make.exit.reverse", "Do you want an exit going the other way? : ", state_make_exit_reverse, false);
	ADD_STATE("make.exit.confirm", "Confirm Exit? : ", state_make_exit_confirm, false);

	ADD_STATE("make.room.name", "Room Name : ", state_make_room_name, false);
	ADD_STATE("make.room.zone", "Room Zone : ", state_make_room_zone, false);
	ADD_STATE("make.room.confirm", "Confirm Room : ", state_make_room_confirm, false);
	ADD_STATE("make.zone", "Zone Name : ", state_zone, false);

ADD_STATE("make.door.zone", "Door Zone : ", state_make_door_zone, false);
ADD_STATE("make.door.start1", "Door Location (1) : ", state_make_door_start1, false);
ADD_STATE("make.door.start2", "Door Location (2) : ", state_make_door_start2, false);
ADD_STATE("make.door.dir1", "Door Direction (1) : ", state_make_door_dir1, false);
ADD_STATE("make.door.dir2", "Door Direction (2) : ", state_make_door_dir2, false);
ADD_STATE("make.door.confirm", "Confirm Door : ", state_make_door_confirm, false);


}