Added public files

Roughly added all public files. Probably missed some, though.
diff --git a/d/seher/haeuser/moebel/access_rights.c b/d/seher/haeuser/moebel/access_rights.c
new file mode 100644
index 0000000..255cd58
--- /dev/null
+++ b/d/seher/haeuser/moebel/access_rights.c
@@ -0,0 +1,5 @@
+int access_rights(string user, string file) {
+  if(user == "swift" && file!="autoloadertruhe.c")
+    return 1;  // Swift hat auf die Moebel Zugriff.
+  return 0;
+}
diff --git a/d/seher/haeuser/moebel/autoloadertruhe.c b/d/seher/haeuser/moebel/autoloadertruhe.c
new file mode 100644
index 0000000..e22ce17
--- /dev/null
+++ b/d/seher/haeuser/moebel/autoloadertruhe.c
@@ -0,0 +1,1015 @@
+//--------------------------------------------------------------------------------
+// Name des Objects:    Aufbewahrungtruhe fuer Autoload-Objekte
+//
+// Magier:              Zesstra
+//--------------------------------------------------------------------------------
+#pragma strong_types,rtt_checks
+
+#include "schrankladen.h"
+inherit LADEN("swift_std_container");
+
+//#include <ansi.h>
+#include <class.h>
+#include <wizlevels.h>
+#include "/d/seher/haeuser/haus.h"
+
+#define IDS     0
+#define NAME   1
+#define ALDATA  2
+
+#define LOG(x,y) log_file(x,sprintf("%s [%s, %O, %O]: %s\n",dtime(time()),\
+      (uuid?uuid:" "),PL,object_name(ME),y))
+#define STORELOG(x) LOG("zesstra/ALTRUHE_STORE.log",x)
+#define PICKLOG(x) LOG("zesstra/ALTRUHE_PICK.log",x)
+
+#define ITEMLOG(x) log_file("zesstra/ALTRUHE_ITEMS.log",\
+    sprintf("%s [%O]: %s\n",dtime(time()),\
+      this_interactive()||PL,x))
+
+#define ERRLOG(x) LOG("zesstra/ALTRUHE.ERR",x)
+
+#undef BS
+#define BS(x) break_string(x,78)
+
+#define VERSION_OBJ "5"
+
+#ifdef MAINTAINER
+#undef MAINTAINER
+#endif
+#define MAINTAINER ({"zesstra"})
+
+// Savefile der Blueprint
+#ifdef SAVEFILE
+#undef SAVEFILE
+#endif
+#define SAVEFILE __FILE__[..<3]
+
+#define DEBUG(x)    if (funcall(symbol_function('find_player),MAINTAINER[0]))\
+          tell_object(funcall(symbol_function('find_player),MAINTAINER[0]),\
+                      "ALTruhe: "+x+"\n")
+
+#define ACCESS (my_secure_level() >= ARCH_LVL)
+
+// Diese 4 sind fuer die Blueprint (Master aller Truhen)
+mapping whitelist=([]); // erlaubte Autoloader, alle anderen nicht erlaubt.
+mapping blacklist=([]); // bereits explizit durch EM+ abgelehnte Autoloader
+mapping vorschlaege=m_allocate(1,2); // vorschlaege der Spieler
+mapping data=([]);  // hier speichert die BP alle Daten der Truhen
+                    // WICHTIG: dieses Mapping wird in /secure/memory
+                    // abgelegt und muss auch beim Neuladen ggf. von dort
+                    // wieder abgeholt werden. Ausserdem teilen sich alle
+                    // Truhen eines Spielers und diese Blueprint die Mappings
+                    // darin, damit Aenderungen sofort in allen Truhen und dem
+                    // Master bekannt sind.
+
+/* die einzelnen Truhen speichern in autoloader. Format: 
+   3 Werte pro Key, Keys sind die Namen der Blueprints der Objekte:
+   ([<blueprint>: <P_IDS>; <ob->name()>; <P_AUTOLOADOBJ> ])
+   */
+nosave mapping autoloader=m_allocate(1,3);
+nosave string uuid; // UUID des Eigentuemers
+nosave object ob_in_bewegung; // uebler Hack eigentlich. :-(
+
+void NotifyInsert(object ob, object oldenv);
+static mapping QueryData();
+static mapping SetData(mixed data);
+protected void save_me();
+protected void check_content();
+
+nomask private int my_secure_level(); //Args.
+
+protected void create() {
+
+  // Ja, es is Absicht, dass das create der BP erst spaeter abgebrochen wird!
+  swift_std_container::create();
+
+  seteuid(getuid(ME));
+
+  // falls dies die BP ist:
+  // 1. das Savefile zu laden.
+  // 2. versuchen, die truhendaten von /secure/memory zu holen, damit nach dem
+  //    Neuladen der Master und die Client immer nach _dieselben_ Mappings
+  //    haben.
+  if (!clonep(ME))
+  {
+    // Savefile restaurieren (auch wenn data im Memory ist, muss das sein,
+    // damit die anderen Variablen wieder eingelesen sind).
+    restore_object(SAVEFILE);
+    // jetzt Daten aus Memory holen, sofern verfuegbar
+    mapping tmp = "/secure/memory"->Load("truhendaten");
+    if (mappingp(tmp))
+    {
+      // Daten aus Savefile durch die vom Memory ersetzen
+      data = tmp;
+    }
+    else
+    {
+      // Keine Daten in Memory. Jetzt in jedem Fall den Pointer auf das Mapping data in
+      // /secure/memory ablegen
+      if ("/secure/memory"->Save("truhendaten",data) != 1)
+      {
+        raise_error("Could not save memory to /secure/memory.");
+      }
+    }
+  }
+  else
+  {
+    // brauchen Clones nicht.
+    set_next_reset(-1);
+    data=0; // brauchen Clones nicht.
+  }
+
+  SetProp(P_SHORT, "Eine kleine, magische Holztruhe");
+  SetProp("cnt_version_obj", VERSION_OBJ);
+  SetProp(P_NAME, "Holztruhe");
+  SetProp(P_GENDER, FEMALE);
+  SetProp(P_NAME_ADJ,({"klein", "magisch"}));
+  SetProp(P_LONG, BS(
+     "Die kleine Holztruhe ist aus stabilem Eichenholz gefertigt. Eigentlich "
+     "saehe sie recht unscheinbar aus, waeren da nicht die vielen kunstvollen "
+     "Runen an den Seiten und auf dem Deckel.")
+    +"@@cnt_status@@");
+
+  AddId(({"autoloadertruhe", "holztruhe", "truhe"}));
+
+  // den Rest vom Create braucht die BP nicht.
+  if (!clonep(ME)) return;
+
+  SetProp(P_LOG_FILE,"zesstra/ALTRUHE.rep");
+
+  SetProp(P_WEIGHT, 3000);         // Gewicht 5 Kg
+  // die drei hier sind in diesme Fall eigentlich voellig ohne Bedeutung
+  SetProp(P_MAX_WEIGHT, 1000000);  // Es passen fuer 1000 kg Sachen rein.
+  SetProp(P_WEIGHT_PERCENT, 100);
+  SetProp(P_MAX_OBJECTS, 100);     // sind eh immer 0 echte Objekte drin.
+
+  SetProp(P_VALUE, 0);             // Kein materieller Wert. Ist eh nicht verkaufbar.
+  SetProp(P_NOBUY, 1);             // Wird im Laden zerstoert, falls er verkauft wird.
+  SetProp(P_NOGET, "Das geht nicht. "+Name(WER,1)+" haftet wie magisch am Boden.\n");
+  SetProp(P_MATERIAL, ([MAT_OAK:49, MAT_MISC_MAGIC:50, MAT_JOFIUM: 1]) );
+  SetProp(P_INFO, BS("In diese stabile Truhe kannst Du bestimmte "
+        "Autoload-Objekte hineinlegen und sie lagern, wenn Du sie gerade "
+        "nicht brauchst. (Mit 'deponiere <was>' kannst Du etwas in der "
+        "Truhe zur Aufbewahrung deponieren, mit 'entnehme <was> oder "
+        "'nimm <was> aus truhe' kannst Du einen Gegenstand wieder "
+        "herausnehmen.)"));
+
+  // Prop fuer rebootfeste Moebel
+  // Der endgueltige Wert (UUID des Spielers) wird per SetBesitzer() gesetzt,
+  // sobald die Truhe das erste Mal in ein Seherhaus bewegt wurde.
+  SetProp(H_FURNITURE, 1);
+
+  AD(({"platz","groesse"}), 
+      BS("Die Truhe ist recht klein, aber merkwuerdigerweise "
+        "scheint sie viel mehr an Gegenstaenden aufnehmen zu koennen, als "
+        "es von ihrer Groesse her scheint."));
+  AD(({"gegenstand","gegenstaende"}),
+      BS("Die Truhe scheint zwar vielen Gegenstaenden Platz zu bieten, aber "
+        "dafuer nimmt sie nicht jeden Gegenstand auf."));
+  AD(({"holz","eichenholz"}),
+      BS("Das Eichenholz ist sehr stabil. Es ist ganz glatt geschliffen und "
+        "traegt viele kunstvolle Runen in sich."));
+  AD(({"seiten","seite"}),
+      BS("Die Truhe hat 4 Seiten, die allesamt mit Runen verziert sind."));
+  AD(({"boden"}),
+      BS("Der Boden der Truhe traegt keinerlei Runen."));
+  AD(({"deckel"}),
+      BS("Auch der Deckel der Truhe ist mit Runen verziert."));
+  AD(({"runen","rune"}),
+      BS("Die Runen bedecken alle 4 Seiten und den Deckel der Truhe. Man "
+        "hat sie zweifellos in muehsamer Arbeit aus dem harten Holz "
+        "geschnitzt. Anschliessend wurden sie offenbar mit einem "
+        "Metall gefuellt. Du verstehst zwar ueberhaupt nicht, was "
+        "die Runen bedeuten, aber sie sind bestimmt magisch, denn wann immer "
+        "Du den Deckel oeffnest oder schliesst oder Gegenstaende hineinlegst "
+        "oder herausnimmst, leuchten die Runen hell auf."));
+  AD(({"metall"}),
+      BS("Was das wohl fuer ein Metall sein mag? Zweifellos hat es auch was "
+        "mit Magie zu tun."));
+  AD(({"magie"}),
+      BS("In dieser Truhe scheint viel Magie zu stecken, wenn selbst ein "
+        "Weltuntergang ihr nichts anhaben kann."));
+  AD(({"arbeit","fertigung"}),
+      BS("Die Fertigung dieser Truhe muss sehr aufwendig gewesen sein. "
+        "Kein Wunder, dass die Truhe so teuer ist."));
+  AD(({"wunder"}),
+      BS("Ein Wunder scheint es zu sein."));
+  AD(({"weltuntergang","armageddon"}),
+      BS("Dir schaudert beim Gedanken an den Weltuntergang."));
+  AD(({"gedanken"}),
+      BS("Denk doch lieber an was anderes..."));
+
+  AddCmd("deponier|deponiere&@PRESENT","cmd_deponiere",
+      "Was moechtest Du in der Eichenholztruhe deponieren?");
+  AddCmd("entnimm|entnehme|entnehm","cmd_entnehmen");
+
+  // bei dieser Truhe waere das Erlauben voellig sinnlos. ;-)
+  RemoveCmd(({"serlaube"}));
+
+}
+
+// keine Truhen zerstoeren, die irgendeinen INhalt haben.
+int zertruemmern(string str) {
+  // aus swift_std_container
+  string nf_str;
+  nf_str="Syntax: zertruemmer [Objekt-Id]\n"
+        +"Bsp.:   zertruemmer "+QueryProp(P_IDS)[1]+"\n";
+  notify_fail("Fehler: Ohne Parameter klappt das nicht.\n"+nf_str);
+  if(!str) return 0;
+  notify_fail("Fehler: Du musst eine gueltige Objekt-Id angeben!\n"+nf_str);
+  if(present(str)!=TO)   // Ueberpruefe, ob auch dieses Objekt gemeint ist!
+    return 0;
+  if( QueryHausbesitzer() != QueryTP() && !QueryProp("test") )
+  {
+    write( BS("Nur "+QueryHausbesitzer()+" darf "+name(WEN,1)+" zertruemmern!"));
+    return 1;
+  }
+  // Objekte enthalten? Wenn ja, abbruch.
+  if (sizeof(autoloader)) {
+    tell_object(PL,BS("Du willst gerade zum Schlag ausholen, um "
+          +name(WEN,1)+ " zu zertruemmern, als Dir einfaellt, dass "
+          +QueryPronoun(WER)+ " ja gar nicht leer ist! Nene, wer weiss, ob "
+          "Du das nicht noch brauchen koenntest."));
+    return 1;
+  }
+  // sonst geerbten Kram ausfuehren.
+  return ::zertruemmern(str);
+}
+
+// Zesstra, 1.7.07, fuers Hoerrohr
+string GetOwner() {return "zesstra";}
+
+// Prueft das Objekt auf Eignung fuer die Truhe, speichert seine Daten und
+// zerstoert es anschliessend. NODROP-Objekte koennen nur so in die Truhe
+// gelegt werden, alle anderen koennen auch mit "stecke ... in truhe"
+// deponiert werden, woraufhin ebenfalls PreventInsert() und NotifyInsert()
+// durchlaufen werden.
+protected int cmd_deponiere(string cmd, mixed args) {
+  if (!objectp(PL)) return 0;
+
+  notify_fail(Name(WER,1)+" ist doch geschlossen!\n");
+  if(QueryProp(P_CNT_STATUS)!=CNT_STATUS_OPEN) return 0;
+  
+  notify_fail("Was moechtest Du in der Eichenholztruhe deponieren?\n");
+  if (!stringp(cmd) || !sizeof(cmd) 
+      || !pointerp(args) || !sizeof(args)) return 0;
+  object ob=args[0];
+  if (!objectp(ob)) return 0;
+  // wuerde die Truhe das Objekt ueberhaupt aufnehmen? Fehlerausgabe durch
+  // PrevenInsert()
+  if (PreventInsert(ob)) return 1;
+  // Ausziehen... Schade, dass DoUnwear nix vernuenftiges an Rueckgabewert
+  // hat. :-(
+  if (objectp(ob->QueryProp(P_WORN))) {
+    ob->DoUnwear();
+    if (objectp(ob->QueryProp(P_WORN))) {
+      tell_object(PL, BS("Du musst "+ ob->name(WEN,1)+ "zunaechst einmal "
+            "ausziehen!"));
+      return 1;
+    }
+  }
+  // wegstecken
+  if (objectp(ob->QueryProp(P_WIELDED))) {
+    ob->DoUnwield();
+    if (objectp(ob->QueryProp(P_WIELDED))) {
+      tell_object(PL, BS("Du musst "+ ob->name(WEN,1)+ "zunaechst einmal "
+            "wegstecken!"));
+      return 1;
+    }
+  }
+  // NO_CHECK und Silent-Bewegung, Meldungen an den Spieler selber machen.
+  tell_object(PL, BS("Du steckst "+ ob->name(WEN,1) + " in " + name(WEN,1) +
+      "."));
+    
+  tell_room(environment(),BS(PL->Name(WER) + " legt " + ob->name(WEN,0) +
+      " in " + name(WEN,1) + " hinein."),({PL}));
+  ob->move(ME, M_NOCHECK|M_SILENT);
+  return 1;
+}
+
+// alternative zum "nimm bla aus truhe". Spieler wollten was kurzes dafuer
+// haben.
+protected int cmd_entnehmen(string cmd) {
+  int res;
+  mixed noget;
+
+  if (!objectp(PL)) return 0;
+
+  notify_fail(Name(WER,1)+" ist doch geschlossen!\n");
+  if(QueryProp(P_CNT_STATUS)!=CNT_STATUS_OPEN) return 0;
+
+  notify_fail(BS("Was moechtest Du aus "+name(WEM,1)+ " entnehmen?\n"));
+  if (!stringp(cmd) || !sizeof(cmd)) return 0;
+
+  object *obs=present_objects(cmd);
+
+  if (!sizeof(obs) || !objectp(obs[0]))
+    return 0;
+
+  // NOGET ist hier bloed. So ist es zwar auch nicht richtig doll... *seufz*
+  // Die hier ist/waere aber nen uebler Hack, erstmal auskommentiert lassen.
+  // also, P_NOGET sichern.
+  /*if (!closurep(noget=ob->Query(P_NOGET,F_QUERY_METHOD))) {
+    noget=ob->Query(P_NOGET,F_VALUE);
+    ob->Set(P_NOGET,0,F_VALUE);
+  }
+  else {
+    ob->Set(P_NOGET,0,F_QUERY_METHOD);
+  }*/
+  // nehmen.
+  res=PL->pick_obj(obs[0]);
+  // P_NOGET zurueckschreiben. (Ja, wenn eine Closure als F_VALUE drinsteht,
+  // landet die jetzt als F_QUERY_METHOD im Objekt.
+  /*if (closurep(noget)) {
+    ob->Set(P_NOGET,noget,F_QUERY_METHOD);
+  }
+  else
+    ob->Set(P_NOGET,noget,F_VALUE);
+*/
+  return(res);
+}
+
+// Hier wird auch das PreventInsert() von der Blueprint gerufen. Das
+// erleichtert es, die Liste an erlaubten Objekten zu aendern, ohne dass man
+// alle Clones ersetzen muss.
+varargs int PreventInsert(object ob) {
+  string oname;
+  // Das Objekt, was die Truhe gerade selber bewegt, wird ignoriert.
+  if (!objectp(ob) || ob_in_bewegung==ob) return 0;
+  
+  oname=BLUE_NAME(ob);
+  
+  // Pruefung in Clonen:
+  if (clonep(ME))
+  {
+    // nur Eigentuemer
+    if (!stringp(uuid) || !sizeof(uuid)) {
+      if (objectp(PL))
+        tell_object(PL,BS(sprintf("%s gehoert Dir nicht, daher kannst Du "
+            "auch keine Gegenstaende in %s legen.",
+            Name(WER,1),QueryPronoun(WEN))));
+      return 1;
+    }
+    if (!objectp(PL) || getuuid(PL)!=uuid) {
+      if (objectp(PL))
+        tell_object(PL,BS(sprintf("Nur %s darf Gegenstaende in %s "
+          "hineinlegen.",capitalize(explode(uuid,"_")[0]),name(WEN,1))));
+      return 1;
+    }
+    // jedes Objekt nur einmal.
+    if (member(autoloader,oname)) {
+      if (objectp(PL))
+        tell_object(PL,BS(Name(WER,1)+ " kann von einem Gegenstand jeweils "
+          "nur ein Exemplar aufnehmen, es ist aber bereits "
+          +ob->name(WER,0) + " in " + QueryPronoun(WEM) + "."));
+      return 1;
+    }
+    // jetzt Erlaubnisliste der BP fragen.
+    if (objectp(blueprint(ME)))
+      return blueprint(ME)->PreventInsert(ob);
+    else
+      return load_object(load_name(ME))->PreventInsert(ob);
+  }
+  // Ende fuer Pruefung fuer Clone.
+
+  // ab hier jetzt die Pruefung durch die BP.
+  // Keine (freigegebener) Autoloader? Hat in diesem Container nix verloren!
+  if( !ob->QueryProp(P_AUTOLOADOBJ) ) {
+    if (objectp(PL))
+      tell_object(PL,BS("In "+name(WEN,1)
+            +" kannst Du nur Autoload-Objekte hineinlegen. "));
+    return 1;
+  }
+  else if (member(blacklist,oname)) {
+    if (objectp(PL))
+      tell_object(PL,BS("In "+name(WEN,1)
+            +" kannst Du nur dafuer erlaubte Autoload-Objekte hineinlegen. "
+            +ob->Name(WER,1) + " wurde explizit als nicht erwuenscht "
+            "befunden."));
+    return 1;
+  }
+  else if (!member(whitelist,oname)) {
+    if (!member(vorschlaege,oname)) {
+      vorschlaege[oname,0]=ob->name(WER,0) || "";
+      vorschlaege[oname,1]=ob->short() || "";
+    }
+    if (objectp(PL))
+      tell_object(PL,BS("In "+name(WEN,1)
+            +" kannst Du nur dafuer erlaubte Autoload-Objekte hineinlegen. "
+            +ob->Name(WER,1) + " ist momentan nicht auf der Liste. Der "
+            "Gegenstand wurde jetzt als Vorschlag gespeichert. Bitte hab "
+            "etwas Geduld, bis sich jemand den Gegenstand angeschaut hat."));
+    // ggf. reset reaktivieren und Maintainer informieren.
+    if (!query_next_reset())
+      set_next_reset(1);
+    return 1;
+  }
+  // getragenes?
+  if (ob->QueryProp(P_WORN)) {
+      ob->DoUnwear(0);
+      if (ob->QueryProp(P_WORN)) { //ARGL. GRUMMEL.
+        if (objectp(PL))
+          tell_object(PL,BS("Willst Du "+ob->name(WEN,1) + " nicht erstmal "
+                "ausziehen?"));
+        return 1;
+      }
+  }
+  // enthaelt es irgendwelche anderen Objekte?
+  if (sizeof(all_inventory(ob))) {
+      if (objectp(PL))
+        tell_object(PL,BS(ob->Name(WER,1) + " ist nicht leer."));
+      return 1;
+  }
+
+  // andere Einschraenkungen, als hier geprueft werden, gibt es nicht.
+  return 0;
+}
+
+// hier ist das Objekt jetzt in der Truhe, d.h. Daten speichern und Objekt
+// destructen. ;)
+void NotifyInsert(object ob, object oldenv) {
+
+  // Das Objekt, was die Truhe gerade selber bewegt, wird ignoriert.
+  if (!objectp(ob) || ob==ob_in_bewegung)
+    return;
+  STORELOG(sprintf("%s deponiert %s [%O], Daten: %O",getuid(PL),ob->name(WEN,0),
+        ob,ob->QueryProp(P_AUTOLOADOBJ)));
+  // noetig sind die IDs, den Namen und die AUTOLOADOBJ-Daten des Objekts.
+  // ;-)
+  autoloader[BLUE_NAME(ob),ALDATA]=ob->QueryProp(P_AUTOLOADOBJ);
+  autoloader[BLUE_NAME(ob),IDS]=ob->QueryProp(P_IDS);
+  // Objekte, die 0 als short liefern, kriegen eine Standard-Short und werden
+  // sichtbar gemacht, da sie sonst nicht wiederzufinden sind. Objekte, die
+  // unsichtbar sein sollen, duerfen nicht erlaubt werden.
+  // TODO eine ID als Short nehmen?
+  autoloader[BLUE_NAME(ob),NAME]=capitalize((ob->short()||"<Unbekannt>.\n")[..<3]);
+  // nach dem Move die realen Objekte destructen.
+  call_out(#'check_content, 0);
+  save_me();
+}
+
+// Objekt wurde entnommen, also aus der Liste der enthaltenen Autoloader
+// loeschen. Ausserdem Objekt konfigurieren. Dies wird erst hier gemacht und
+// nicht in create_object(), damit es so aehnlich wie moeglich zum clonen der
+// Autoloader beim erstellen des Spielerobjektes wird (dort wird erst bewegt,
+// dann konfiguriert).
+void NotifyLeave(object ob, object dest) {
+  string error, oname;
+ 
+  if (!objectp(ob))
+    return;
+  
+  oname=BLUE_NAME(ob);
+  if (!member(autoloader,oname)) {
+    // Das sollte definitiv nicht passieren.
+    ERRLOG(sprintf("Gegenstand (%O) wurde entnommen, der nicht "
+      "gespeichert war!",ob));
+    return;
+  }
+
+  // wenn kein Fehler: Objekt aus Liste loeschen. Sonst wird das Objekt
+  // zerstoert. Damit bleiben die Autoloader-Daten hier erhalten und der
+  // Spieler hat kein disfunktionales Objekt im Inventar.
+  if (error) {
+    ERRLOG(sprintf("Fehler beim Konfigurieren von %O. Fehlermeldung: %O."
+        "Daten: %O",ob,error,autoloader[oname,ALDATA]));
+    ob->remove(1);
+    if (objectp(ob))
+      destruct(ob);
+  }
+  else {
+    PICKLOG(sprintf("Objekt (%O) wurde entnommen.",ob));
+    m_delete(autoloader,oname);
+    // speichern
+    save_me();
+  }
+}
+
+protected void check_content() {
+  // wenn Objekte noch in der Truhe sind, also nicht erfolgreich in
+  // einen Spieler bewegt wurden, werden zerstoert. Datenverlust gibt es
+  // hierbei nicht, weil die Daten der Autoloader nur durch NotifyLeave()
+  // geloescht werden.
+  foreach(object ob: all_inventory()) {
+    ob->remove(1);
+    if (objectp(ob)) destruct(ob);
+  }
+}
+
+// hier nochmal schauen, ob das Objekt auch in den richtigen Spieler bewegt
+// wird... Falls das move dann hier abgebrochen wird, wird das Objekt im
+// naechsten HB von der Truhe zerstoert. (chk_contents())
+varargs int PreventLeave(object ob, mixed dest) {
+  object ob2;
+  
+  //DEBUG(sprintf("PreventLeave(): Ob: %O, Dest: %O (%O)",
+  //        ob,dest,(objectp(dest)?"Objekt":"Non-Object")));
+
+  if (!objectp(ob)) return 0; 
+  // falls string uebergeben, erstmal zug. Spieler finden.
+  if (stringp(dest) && sizeof(dest))
+    dest=find_player(dest);
+
+  // richtiges INteractive? Dann darf das Objekt raus. Sonst nicht. ;-)
+  if (!objectp(dest) || !interactive(dest) || getuuid(dest)!=uuid)
+      return 1;
+
+  // pruefen, ob der Spieler schon ein Objekt dieser Blueprint dabei hat. Wenn
+  // ja, Abbruch, das koennte sonst zuviele Probleme geben.
+  if (objectp(ob2=present_clone(ob,dest))) {
+    tell_object(dest,BS("Du hast bereits "+ob2->name(WEN,0) +
+        " dabei. Zwei Gegenstaende dieser Art kannst du nicht gleichzeitig "
+        "mit Dir herumtragen."));
+    return 1; //nicht rausnehmen.
+  }
+  return 0;
+}
+
+// Objekte ausgeben, die hier angeblich drin sind. ;-) Gibt aber nur die
+// Autoloader aus, keine echten Objekt, die Container sind. Allerdings sollte
+// sowas eh nicht vorkommen. ;-)
+// flags: 1 - return array, 2 - don't collect equal objects '
+// flags: 4 - don't append infos for wizards
+varargs mixed make_invlist(object viewer, mixed inv, int flags) {
+  int iswiz;
+  mixed objs;
+
+  iswiz = IS_LEARNER( viewer ) && viewer->QueryProp(P_WANTS_TO_LEARN);
+  // Mapping benutzen, um multiplen Overhead fuer allokation im foreach() zu
+  // vermeiden.
+  objs=m_allocate(sizeof(autoloader),1);
+  foreach(string oname, string *ids, string sh: autoloader) {
+    if (iswiz && !(flags & 4))
+      objs[oname]=sh + ". ["+oname+"]";
+    else
+      objs[oname]=sh + ".";
+  }
+  if(flags & 1) return(m_values(objs)-({""}));
+  if(!sizeof(autoloader)) return "";
+  return sprintf("%"+(sizeof(objs) > 6 ? "#" : "=")+"-78s",
+                 implode(m_values(objs)-({""}), "\n")) + "\n";
+}
+
+// erzeugt das benannte Objekt und liefert es zurueck. Liefert 0 im Fehlerfall.
+// ausserdem bewegt es das Objekt in die Truhe, damit es ein Env hat und die
+// Truhe via NotifyLeave() mitkriegt, dass es tatsaechlich entnommen wurde.
+private object create_object(string oname) {
+  string error;
+  object ob;
+  mixed noget;
+  if (!member(autoloader,oname)) return 0;
+
+  //Blueprint finden (ja, das ist nicht unbedingt noetig, man koennte auch
+  //direkt clonen)
+  if (error=catch(ob=load_object(oname);publish) ||
+      !objectp(ob)) {
+    ERRLOG(sprintf("Konnte %s nicht laden/finden. Fehler: %O",
+          oname,error));
+    return 0;
+  }
+  // clonen
+  if (error=catch(ob=clone_object(oname);publish) ||
+      !objectp(ob)) {
+    ERRLOG(sprintf("Konnte %s nicht clonen. Fehler: %O",
+        oname,error));
+    return 0;
+  }
+  // konfigurieren
+  error=catch(ob->SetProp(P_AUTOLOADOBJ,autoloader[oname,ALDATA]);publish);
+
+  //Objekt bewegen, dabei Objekt in glob. Var. merken, damit PreventInsert()
+  //und NotifyInsert() es ignorieren. *seufz*
+  ob_in_bewegung=ob;
+  ob->move(ME,M_NOCHECK);
+  ob_in_bewegung=0;
+
+  // jetzt noch nen Callout starten, damit das Objekt zerstoert wird, wenn es
+  // nicht wirklich in einen Spieler bewegt wird.
+  call_out(#'check_content,1);
+
+  return(ob);
+}
+
+// Schauen, ob die truhe ein Objekt mit passender ID enthaelt. Wenn
+// ja, das Objekt erzeugen und zurueckliefern. 
+// Diese Funktion hat eine Reihe von Nachteilen bzw. Defiziten ggue. der
+// normalerweise in Containern definierten Funktion:
+// - Nur das erste Objekt, auf das id passt. Ich hab erstmal keine Lust,
+//   hier mehrere Objekte zu erzeugen. Mal schauen, ob es so geht. Auch waere
+//   es ein Problem, wenn viele Objekt die Evalgrenze bzw. nicht alle in den
+//   Spieler bewegt werden, nachdem sie erzeugt wurden.
+// - keine komplexen Ausdruecke, nur reine IDs.
+// Ich halte den Aufwand fuer nicht gerechtfertigt.
+object *present_objects( string complex_desc ) {
+  object ob;
+  if (!stringp(complex_desc) || !sizeof(complex_desc))
+      return ({});
+  // diese Funktion liefert nur Objete zurueck, wenn der richtige Interactive
+  // versucht, sie zu entnehmen. ;-)
+  if (!objectp(this_interactive()) ||
+      getuuid(this_interactive())!=uuid)
+      return ({});
+
+  // "alles" liefert das erstbeste Objekt.
+  if (complex_desc=="alles" && sizeof(autoloader))
+  {
+    string oname=m_indices(autoloader)[0];
+    ob=create_object(oname);
+    if (objectp(ob)) return ({ob});
+  }
+
+  // ueber alle Eintraege gehen, bis eine ID stimmt, erstes passendes Objekt
+  // erzeugen und in einem Array zurueckliefern.
+  foreach(string oname, string *ids: autoloader) {
+    if (member(ids,complex_desc)==-1) continue;
+    ob=create_object(oname);
+    break; //objekt gefunden, fertig hier
+  }
+  if (objectp(ob)) return ({ob});
+  return ({}); // nix gefunden
+}
+
+
+
+// ******************* Verwaltung *********************************
+
+// registriert die Truhe auf den jeweiligen Eigentuemer.
+protected void SetBesitzer(string unused, string newuuid) {
+  if (!stringp(newuuid) || !sizeof(newuuid)) return;
+  // wenn schon registriert, abbrechen
+  if (stringp(uuid) && sizeof(uuid)) return;
+
+  uuid=newuuid;
+  Set(H_FURNITURE,uuid,F_VALUE); //Setmethode umgehen, sonst Rekursion 
+  // ab jetzt nur noch von der Truhe selber.
+  Set(H_FURNITURE,SECURED,F_MODE_AS);
+  
+  // Daten fuer den Benutzer aus der Blueprint holen (BP liefert KEINE Kopie
+  // und es darf KEINE gemacht werden!):
+  autoloader=(mapping)load_name()->GetData(uuid);
+  
+  // keine Daten gekriegt? -> Fehler loggen
+  if (!mappingp(autoloader))
+  {
+    ERRLOG(sprintf("Keine gueltigen Daten vom Truhenmaster (BP) erhalten. "
+        "initialisiere mit leerem Mapping. :-("));
+    raise_error(sprintf(
+          "Keine gueltigen Daten vom Truhenmaster (BP) fuer UUID %s "
+          "erhalten.\n",uuid));
+  }
+}
+
+// Set-Funktion
+string _set_h_furniture(mixed arg) {
+  if (stringp(arg))
+  {
+    SetBesitzer(0,arg); // bricht ab, wenn bereits registriert.
+  }
+  return(uuid);
+}
+
+// Falls das Speichern in der BP nicht klappte, rufen die Clones diese
+// Funktion. Schreiben der Daten in in Logfile zur Restaurieren per Hand.
+private void EmergencyStore(int res) {
+    ERRLOG(sprintf("EmergencyStore() called. Rueckgabewert des "
+        "Truhenmaster (BP) war: %O. Speichere Daten in Logfile. ",res));
+    write_file(__DIR__+"ALTRUHE.NOTFALLDATEN",
+        sprintf("Daten fuer %O:\n%O\n",uuid,autoloader));
+}
+
+protected void save_me() {
+  int res;
+  // nur BP speichern
+  if (!clonep(ME))
+    save_object(SAVEFILE);
+  else
+  {
+    if (objectp(blueprint(ME)))
+      res=(int)blueprint(ME)->StoreData(uuid,autoloader);
+    else
+      res=(int)load_object(load_name(ME))->StoreData(uuid,autoloader);
+
+    if (res!=1)
+      EmergencyStore(res); // Daten in einem Notfall-Logfile ablegen.
+  }
+}
+
+
+// diese Funktion wird vom Seherhausraum gerufen, sobald ein rebootfestes
+// Moebelstueck erzeugt und konfiguriert wurde.
+void post_create() {
+    if (!clonep()) return;
+
+    // wenn jetzt kein Env: destructen
+    if (!objectp(environment())) {
+        remove(1);
+        return;
+    }
+    //beim Schrankmaster registrieren
+    SCHRANKMASTER->RegisterCnt(ME, QueryProp("cnt_version_std")
+      +":"+QueryProp("cnt_version_obj"), environment()->QueryOwner(),
+       environment());
+}
+
+// diese Funktion wird vom Schrankmaster gerufen, wenn dieser meint, dass
+// dieses Objekt neu erstellt werden sollte.
+int UpdateMe()
+{
+  if (!clonep())
+    return 0;
+  if (!objectp(environment()))
+    return 1;
+  object ob=clone_object(load_name(ME));
+  if (objectp(ob)) {
+    object oldenv=environment();
+    // UUID uebertragen
+    ob->SetProp(H_FURNITURE, uuid);
+    // hierhier bewegen, dabei werden UUID und Daten von der neuen Truhe meist
+    // automatisch geholt.
+    ob->move(oldenv,M_NOCHECK);
+    // jetzt erst post_create() rufen!
+    ob->post_create();
+    // dieses Objekt rausbewegen (damit das Seherhaus es austraegt).
+    move("/room/void",M_NOCHECK);
+    // Seherhausraum speichern (koennte teuer sein!)
+    oldenv->Save(1);
+    // selbstzerstoeren
+    // __INT_MAX__ bedeutet: nicht speichern, die neue Truhe hat die daten
+    // schon aus der BP abgefragt.
+    remove(__INT_MAX__);
+  }
+  return(1);
+}
+
+// bei Selbstzerstoerung speichern bzw. Daten an die Blueprint uebermitteln
+// und beim Schrankmaster abmelden.
+varargs int remove(int silent) {
+  string uid="";
+
+  // Blueprint speichern im Savefile, Clones uebertragen die Daten hier an die
+  // Blueprint. Clones nur, wenn nicht __INT_MAX__ uebergeben wurde.
+  if (silent!=__INT_MAX__ || !clonep())
+    save_me();
+
+  if (clonep()) {
+    // Clone melden sich beim Schrankmaster ab.
+    if (objectp(environment())) {
+        uid=environment()->QueryOwner();
+    }
+    //beim Schrankmaster deregistrieren
+    SCHRANKMASTER->RemoveCnt(ME,uid);
+  }
+  return(::remove(silent));
+}
+
+// ***************** NUR BLUEPRINTS *********************************
+
+// neuen Autoloader zulassen (nur EM+!)
+varargs int AddAutoloader(string path,string nam) {
+  object ob;
+  if (clonep(ME)) return 0;
+  if (!stringp(path) || !sizeof(path)) return -1;
+  if (!ACCESS) return -2;
+  //if (!ARCH_SECURITY) return -2;
+  if (member(whitelist,path)) return -3;
+  if (catch(ob=load_object(path);publish)
+      || !objectp(ob))
+      return -4;
+  // wenn Name nicht angegeben und auch nicht aus BP ermittelbar: Abbruch.
+  if (!stringp(nam) || !sizeof(nam)) {
+      nam=ob->name(WER,0);
+      if (!stringp(nam) || !sizeof(nam)) return -5;
+  }
+  ITEMLOG(sprintf("%s erlaubt: %s (%s)\n",getuid(this_interactive()),
+          path,nam));
+  whitelist+=([path:capitalize(nam)]);
+  if (member(vorschlaege,path))
+    m_delete(vorschlaege,path);
+  save_me();
+  return(1);
+}
+
+// Autoloader aus Erlaubnisliste entfernen (nur EM+!)
+int RemoveAutoloader(string path) {
+  if (clonep(ME)) return 0;
+  if (!stringp(path) || !sizeof(path)) return -1;
+  if (!ACCESS) return -2;
+  //if (!ARCH_SECURITY) return -2;
+  if (!member(whitelist,path)) return -3;
+  ITEMLOG(sprintf("%s widerruft Erlaubnis: %s (%s)\n",getuid(this_interactive()),
+          path,whitelist[path]));
+  whitelist-=([path]);
+  save_me();
+  return(1);
+}
+
+// erlaubte Autoloader abfragen
+mapping QueryAutoloader() {
+  return(copy(whitelist));
+}
+
+// neuen Autoloader in Blacklist eintragen (nur EM+!)
+varargs int AddBlacklist(string path, string nam) {
+  object ob;
+  if (clonep(ME)) return 0;
+  if (!stringp(path) || !sizeof(path)) return -1;
+  if (!ACCESS) return -2;
+  //if (!ARCH_SECURITY) return -2;
+  
+  if (member(blacklist,path)) return -3;
+
+  if (catch(ob=load_object(path);publish)
+      || !objectp(ob))
+      return -4;
+  // wenn Name nicht angegeben und auch nicht aus BP ermittelbar: Abbruch.
+  if (!stringp(nam) || !sizeof(nam)) {
+      nam=ob->name(WER,0);
+      if (!stringp(nam) || !sizeof(nam)) return -5;
+  }
+  // ggf. erlaubten entfernen.
+  if (member(whitelist,path))
+    RemoveAutoloader(path);
+  ITEMLOG(sprintf("%s verbietet: %s (%s)\n",getuid(this_interactive()),
+          path,nam));
+
+  blacklist+=([path:capitalize(nam)]);
+
+  if (member(vorschlaege,path))
+    m_delete(vorschlaege,path);
+
+  save_me();
+  return(1);
+}
+
+// Autoloader aus Blacklist entfernen (nur EM+!)
+int RemoveBlacklist(string path) {
+  if (clonep(ME)) return 0;
+  if (!stringp(path) || !sizeof(path)) return -1;
+  if (!ACCESS) return -2;
+  //if (!ARCH_SECURITY) return -2;
+  if (member(blacklist,path)==-1) return -3;
+  ITEMLOG(sprintf("%s loescht: %s (%s) von Blacklist\n",getuid(this_interactive()),
+          path,blacklist[path]));
+  blacklist-=([path]);
+  save_me();
+  return(1);
+}
+
+// gesperrte Autoloader abfragen
+mapping QueryBlacklist() {
+  return(copy(blacklist));
+}
+
+// vorschlaege abfragen
+varargs mixed QueryVorschlaege(int format) {
+  string res="\n";
+  if (!format) return(copy(vorschlaege));
+
+  foreach(string oname, string nam, string sh: vorschlaege) {
+    res+=sprintf("%.78s:\n   %.37s,%.37s\n",oname,nam,sh); 
+  }
+
+  if (format==2 && objectp(PL))
+    tell_object(PL,res);
+  else
+    return res;
+  return 0;
+}
+
+// Wird diese funktion in der Blueprint gerufen, liefert sie die Daten fuer
+// eine Truhe mit dieser UUID zurueck. Aber nur dann, wenn die auch von einer
+// truhe abgerufen wird und keinem beliebigen anderen Objekt oder wenn ein EM
+// abfragt.
+mapping GetData(string uid) {
+  if (clonep(ME)) return 0;
+  if (extern_call())
+  {
+    if (!objectp(previous_object())) return 0;
+    if (blueprint(previous_object()) != ME
+        && load_name(previous_object()) != __FILE__[..<3]
+        && !ACCESS)
+        return(0);
+  }
+  if (!stringp(uid)) return ([]);
+
+  if (!member(data, uid))
+    data[uid] = m_allocate(1,3);
+
+  // Absichtlich keine Kopie, damit die Truhen (falls jemand mehrere kauft)
+  // sich alle eine Kopie des Mappings teilen.
+  return data[uid];
+}
+
+// Loest die Speicherung der Daten im Savefile aus, denn irgendwelche Daten
+// haben sich in einem Clone geaendert, welche noch auf die Platte muessen.
+// Diese Funktion speicherte frueher Daten aus den Clones wieder im Mapping
+// des Masters (der Blueprint). Dies ist heute nicht mehr so, weil alle Truhen
+// (eines Benutzers) sich data[uid] teilen. Daher wird hier ein Fehler
+// ausgeloest, wenn es von einer Truhe ein Mapping kriegt, welches nicht
+// identisch (!) mit dem data[uid] ist.
+// liefert 0 im Fehlerfall!
+int StoreData(string uid, mapping tmp) {
+
+  if (clonep(ME)) return 0;
+
+  // Aber nur dann, wenn die auch von einer truhe abgerufen wird und keinem
+  // beliebigen anderen Objekt oder wenn ein EM setzt.
+  if (extern_call())
+  {
+    if (!objectp(previous_object()))
+      return 0;
+    if (blueprint(previous_object()) != ME 
+        && load_name(previous_object()) != __FILE__[..<3]
+        && !ACCESS)
+      return 0;
+  }
+  if (!stringp(uid) || !mappingp(tmp))
+    return(0);
+
+  // tmp muss auf _dasselbe_ Mapping zeigen wie data[uid]. Wenn das nicht der
+  // Fall ist, ist was schiefgelaufen. Jedenfalls wird dann hier nen Fehler
+  // ausgeloest.
+  if (tmp != data[uid])
+  {
+//    if(program_time(previous_object()) < 1400525694)
+//      data[uid]=tmp;
+//    else
+      raise_error("StoreData() gerufen und Daten sind nicht identisch "
+          "mit den bereits bekannten.\n");
+  }
+
+  // Absichtlich keine Kopie, damit sich alle Truhen das Mapping teilen.
+  //data[uid]=tmp;
+
+  // Savefile muss natuerlich geschrieben werden, fuer den naechsten Reboot.
+  if (find_call_out(#'save_me)==-1)
+      call_out(#'save_me,10); // Speichervorgaenge ggf. sammeln (upd -ar ...)
+  return(1);
+}
+
+// Maintainer ueber Truhenvorschlaege informieren
+void reset() {
+
+  if (clonep() || !sizeof(vorschlaege)) {
+    // ohne Vorschlaege ist auch kein reset noetig.
+    set_next_reset(-1);
+    return;
+  }
+  set_next_reset(12000); // alle 3-4h reicht.
+  foreach(string uid: MAINTAINER) {
+    object pl=find_player(uid);
+    if (objectp(pl) && query_idle(pl) < 1800)
+      tell_object(pl,BS("Es gibt neue Objektvorschlaege fuer die "
+        "Autoloadertruhe. Bitt schau da doch bei Gelegenheit mal drueber."));
+  }
+}
+
+
+// *************************************************************************
+
+// **************** SONSTIGES **********************************************
+
+// *seufz*
+// secure_level() aus der simul_efun ist hier momentan nicht brauchbar, weil
+// dort auch p/seher/moebel/autoloadertruhe in der Callerkette steht und das
+// ein levle von 0 hat. *seufz*
+nomask private int my_secure_level() {
+  int *level;
+  //kette der Caller durchlaufen, den niedrigsten Level in der Kette
+  //zurueckgeben. Zerstoerte Objekte (Selbstzerstoerer) fuehren zur Rueckgabe
+  //von 0.
+  //caller_stack(1) fuegt dem Rueckgabearray this_interactive() hinzu bzw. 0,
+  //wenn es keinen Interactive gibt. Die 0 fuehrt dann wie bei zerstoerten
+  //Objekten zur Rueckgabe von 0, was gewuenscht ist, da es hier einen
+  //INteractive geben muss.
+  level=map(caller_stack(1),function int (object caller)
+      {if (objectp(caller))
+        return(query_wiz_level(geteuid(caller)));
+       return(0); // kein Objekt da, 0.
+      } );
+  return(min(level)); //den kleinsten Wert im Array zurueckgeben (ggf. 0)
+}
+
+
+// debugkram
+mixed _query_content() {
+  //deep_copy, damit nicht jemand einfach so an den Daten rumbasteln kann.
+  return(deep_copy(autoloader));
+}
+
+mixed _query_owner() {
+  return(uuid);
+}
+
+int DeleteData(string uid) {
+  if (clonep(ME)) return 0;
+  if (!stringp(uid) || !sizeof(uid)) return -1;
+  if (!ACCESS) return -2;
+  //if (!ARCH_SECURITY) return -2;
+  m_delete(data,uid);
+  save_me();
+  return(1);
+}
+
+mixed testfun() {return "bin da\n";}
+
diff --git a/d/seher/haeuser/moebel/kleiderschrank.c b/d/seher/haeuser/moebel/kleiderschrank.c
new file mode 100644
index 0000000..79209b4
--- /dev/null
+++ b/d/seher/haeuser/moebel/kleiderschrank.c
@@ -0,0 +1,208 @@
+//--------------------------------------------------------------------------------
+// Name des Objects:    Kleiderschrank
+// Letzte Aenderung:    17.03.2001
+// Magier:              Swift
+//--------------------------------------------------------------------------------
+#pragma strong_types,rtt_checks
+
+#include "schrankladen.h"
+#include <ansi.h>
+inherit LADEN("swift_std_container");
+
+#define VERSION_OBJ "3"
+
+string strall;
+
+protected void create()
+{
+  if (!clonep(TO)) return;
+  swift_std_container::create();
+  SetProp(P_SHORT, "Ein Kleiderschrank");
+  SetProp(P_LONG, BS(
+     "In diesem massiven Holzschrank kannst Du die Ausruestung fuer eine "
+    +"halbe Armee unterbringen. Mehrere Regale sorgen dafuer, dass alles "
+    +"seinen geordneten Platz findet, damit Du es auch schnell "
+    +"wiederfindest.")+"@@cnt_status@@");
+  AddId(({"kleiderschrank", "holzschrank", "schrank"}));
+  SetProp("cnt_version_obj", VERSION_OBJ);
+  SetProp(P_NAME, "Kleiderschrank");
+  SetProp(P_GENDER, MALE);
+  SetProp(P_WEIGHT, 5000);         // Gewicht 5 Kg
+  SetProp(P_MAX_WEIGHT, 1000000);  // Es passen fuer 1000 kg Sachen rein.
+  SetProp(P_WEIGHT_PERCENT, 100);  // Dafuer macht er auch nix leichter :)
+  SetProp(P_MAX_OBJECTS, 100);     // Mehr sollte nicht sein, lt. Tiamak.
+  SetProp(P_VALUE, 0);             // Kein materieller Wert. Ist eh nicht verkaufbar.
+  SetProp(P_NOBUY, 1);             // Wird im Laden zerstoert, falls er verkauft wird.
+  SetProp(P_NOGET, "Das geht nicht. "+Name(WER,1)+" haftet wie magisch am Boden.\n");
+  SetProp(P_MATERIAL, ({MAT_MISC_WOOD, MAT_MISC_MAGIC}) );
+  SetProp(P_INFO, "Versuchs mal mit: \"skommandos "+QueryProp(P_IDS)[1]+"\" !\n");
+  SetProp("obj_cmd", "sliste [Objekt-Id] [Kleidungs-/Ruestungstyp|\"alles\"]\n"
+                    +"  Kleidungs-/Ruestungstypen: Helme, Umhaenge, Ruestungen, Hosen, Schuhe,\n"
+                    +"                             Handschuhe, Guertel, Amulette, Ringe, Koecher,\n"
+                    +"                             Schilde, Sonstiges\n");
+  AD(({"regal", "regale"}), BS("Durch die Regale kommt etwas Ordnung in die "
+    +"vielen Sachen, die man in den Schrank stecken kann. Du kannst Dir z.B. "
+    +"eine Liste bestimmter Kleidungs-/Ruestungstypen des Schrankinhaltes "
+    +"mit dem Befehl \"sliste\" anschauen. (Das geht natuerlich nur bei "
+    +"offenem Schrank!"));
+
+  AddCmd(({"sliste"}), "auflistung");
+}
+
+varargs int PreventInsert(object ob)
+{
+  // Nur Ruestung/Kleidung hat in diesem Container was verloren!
+  if ((ob->IsClothing() || ob->QueryProp(P_ARMOUR_TYPE))
+      && !ob->QueryProp(P_WEAPON_TYPE) )
+  {
+    return ::PreventInsert(ob);
+  }
+
+  write( BS("In "+name(WEN,1)+" kannst Du nur Ruestungs-/Kleidungsstuecke legen!"));
+  return 1;
+}
+
+int auflistung2(string was, string nf_str1, string nf_str2, int alles)
+{
+  string obshort, suche, *strs;
+  object *obs;
+  int i;
+  mapping suchobs;
+  switch(was)
+  {
+    case "helme"      : suche=AT_HELMET; break;
+    case "umhaenge"   : suche=AT_CLOAK; break;
+    case "ruestungen" : suche=AT_ARMOUR; break;
+    case "hosen"      : suche=AT_TROUSERS; break;
+    case "schuhe"     : suche=AT_BOOT; break;
+    case "handschuhe" : suche=AT_GLOVE; break;
+    case "guertel"    : suche=AT_BELT; break;
+    case "amulette"   : suche=AT_AMULET; break;
+    case "ringe"      : suche=AT_RING; break;
+    case "koecher"    : suche=AT_QUIVER; break;
+    case "schilde"    : suche=AT_SHIELD; break;
+    case "sonstiges"  : suche=AT_MISC; break;
+    default           : write("Fehler: Ungueltiger Kleidungs-/Ruestungstyp. "
+                             +"Folgende Typen gibt es:\n"+nf_str1+nf_str2);
+                        return 1; break;
+  }
+  obs=all_inventory();
+  suchobs=([]);
+  for(i=0;i<sizeof(obs);i++)
+  {
+    obshort=obs[i]->QueryProp(P_SHORT);
+    if(obshort=="Nichts besonderes") // keine P_SHORT ?
+      obshort=obs[i]->Name(WER);     //   Hoffen wir mal dass das Obj. nen Namen hat.
+    if(obs[i]->QueryProp(P_ARMOUR_TYPE)==suche)    // Gesuchter ArmourType gefunden...
+    {
+      if(suchobs[obshort])                         // P_SHORT des Obj. schon im mapping?
+      {
+        if( obs[i]->QueryProp(P_AMOUNT) )
+          suchobs[obshort]+=obs[i]->QueryProp(P_AMOUNT); //   Dann den Zaehler um Amount hoch!
+        else
+          suchobs[obshort]+=1;                     //   Dann den Zaehler um 1 hoch!
+      }
+      else
+      {
+        if( obs[i]->QueryProp(P_AMOUNT) )
+          suchobs+=([obshort: obs[i]->QueryProp(P_AMOUNT)]);
+        else
+          suchobs+=([obshort: 1]);
+      }
+    }
+  }
+  strs=m_indices(suchobs);
+  if(sizeof(strs))
+  {
+    if(!alles)
+    {
+      strall+=Name(WER,1)+" enthaelt folgende "+CAP(was)+":\n";
+      strall+="------------------------------------------------------------\n";
+    }
+    else
+      strall+=ANSI_BOLD+"=== "+CAP(was)+":\n"+ANSI_NORMAL;
+    for(i=0;i<sizeof(strs);i++)
+    {
+      if(suchobs[strs[i]] > 1)
+        strall+=strs[i]+". ("+suchobs[strs[i]]+")\n";
+      else
+        strall+=strs[i]+".\n";
+    }
+  }
+  else
+    if(!alles)
+      strall+=Name(WER,1)+" enthaelt keine "+CAP(was)+"!\n";
+  return 1;
+}
+
+int auflistung(string str)
+{
+  string *strs, ob_id, was, nf_str1,nf_str2;
+  strall="";
+  nf_str1="   (Helme, Umhaenge, Ruestungen, Hosen, Schuhe, Handschuhe,\n"
+         +"    Guertel, Amulette, Ringe, Koecher, Schilde, Sonstiges)\n";
+  nf_str2="Syntax: sliste [Objekt-Id] [Kleidungs-/Ruestungstyp|\"alles\"]\n"
+         +"Bsp.:   sliste "+QueryProp(P_IDS)[1]+" "+"helme\n"
+         +"        sliste "+QueryProp(P_IDS)[1]+" alles\n";
+  notify_fail("Fehler: Ohne Parameter klappt das nicht.\n"+nf_str2);
+  if(!str) return 0;
+  if(present(str)==TO)   // Ueberpruefe, ob dieses Objekt gemeint ist!
+  {
+    write("Fehler: Es fehlt ein Kleidungs-/Ruestungstyp. Folgende Typen gibt es:\n"
+         +nf_str1+nf_str2);
+    return 1;
+  }
+  strs=old_explode(str, " ");
+  notify_fail("Fehler: Du musst eine gueltige Objekt-Id angeben!\n"
+             +nf_str2);
+  if( sizeof(strs) < 2 ) return 0;   // Nur 1 Par. und der ist nicht die Objekt-Id
+  if( sizeof(strs) == 2 )   // Anzahl Par. = 2
+  {
+    ob_id=strs[0];
+    was=strs[1];
+    if( IST_ZAHL(was) )     // Objekt-Id z.B. mit "schrank 2" angesprochen?
+      if(present(ob_id+" "+was)==TO)   // Falls dieses Objekt gemeint ist und kein 3. Par!
+      {
+        write("Fehler: Es fehlt ein Kleidungs-/Ruestungstyp. Folgende Typen gibt es:\n"
+              +nf_str1+nf_str2);
+        return 1;
+      }
+      else
+        return 0;
+  }
+  else if( sizeof(strs) == 3 )
+  {
+    ob_id=strs[0]+" "+strs[1];
+    was=strs[2];
+  }
+  else        // Anzahl erforderlicher Parameter ueberschritten!
+    return 0;
+  if(present(ob_id)!=TO)   // Ueberpruefe, ob auch dieses Objekt gemeint ist!
+    return 0;
+  if(QueryProp(P_CNT_STATUS)!=CNT_STATUS_OPEN)
+  {
+    write("Dazu muesste "+name(WER,1)+" geoeffnet sein.\n");
+    return 1;
+  }
+//--- Hier ist Parameterpruefung zu Ende.
+  was=LOWER(was);
+  if(was!="alles")
+    auflistung2(was, nf_str1, nf_str2, 0);
+  else
+  {
+    auflistung2("helme", nf_str1, nf_str2, 1);
+    auflistung2("umhaenge", nf_str1, nf_str2, 1);
+    auflistung2("ruestungen", nf_str1, nf_str2, 1);
+    auflistung2("hosen", nf_str1, nf_str2, 1);
+    auflistung2("schuhe", nf_str1, nf_str2, 1);
+    auflistung2("handschuhe", nf_str1, nf_str2, 1);
+    auflistung2("guertel", nf_str1, nf_str2, 1);
+    auflistung2("amulette", nf_str1, nf_str2, 1);
+    auflistung2("ringe", nf_str1, nf_str2, 1);
+    auflistung2("koecher", nf_str1, nf_str2, 1);
+    auflistung2("schilde", nf_str1, nf_str2, 1);
+    auflistung2("sonstiges", nf_str1, nf_str2, 1);
+  }
+  TP->More(strall);
+  return 1;
+}
diff --git a/d/seher/haeuser/moebel/kommode.c b/d/seher/haeuser/moebel/kommode.c
new file mode 100644
index 0000000..dea2b50
--- /dev/null
+++ b/d/seher/haeuser/moebel/kommode.c
@@ -0,0 +1,40 @@
+//--------------------------------------------------------------------------------
+// Name des Objects:    Kommode
+// Letzte Aenderung:    17.03.2001
+// Magier:              Swift
+//--------------------------------------------------------------------------------
+#pragma strong_types,rtt_checks
+
+#include "schrankladen.h"
+inherit LADEN("swift_std_container");
+
+#define VERSION_OBJ "3"
+
+protected void create()
+{
+  if (!clonep(TO)) return;
+  swift_std_container::create();
+  SetProp(P_SHORT, "Eine Kommode");
+  SetProp(P_LONG, BS(
+     "Diese robuste Kommode aus Eichenholz passt einfach in jeden Raum. "
+    +"Man kann jede Menge Zeug darin verstauen, und die vielen Schubladen "
+    +"lassen es einfach verschwinden. So ein Moebelstueck gehoert einfach "
+    +"in jedes Haus!")+"@@cnt_status@@");
+  AddId(({"kommode"}));
+  SetProp("cnt_version_obj", VERSION_OBJ);
+  SetProp(P_NAME, "Kommode");
+  SetProp(P_GENDER, FEMALE);
+  SetProp(P_WEIGHT, 5000);         // Gewicht 5 Kg
+  SetProp(P_MAX_WEIGHT, 1000000);  // Es passen fuer 1000 kg Sachen rein.
+  SetProp(P_WEIGHT_PERCENT, 100);  // Dafuer macht er auch nix leichter :)
+  SetProp(P_MAX_OBJECTS, 100);     // Mehr sollte nicht sein, lt. Tiamak.
+  SetProp(P_VALUE, 0);             // Kein materieller Wert. Ist eh nicht verkaufbar.
+  SetProp(P_NOBUY, 1);             // Wird im Laden zerstoert, falls er verkauft wird.
+  SetProp(P_NOGET, "Das geht nicht. "+Name(WER,1)+" haftet wie magisch am Boden.\n");
+  SetProp(P_MATERIAL, ({MAT_OAK, MAT_MISC_MAGIC}) );
+  SetProp(P_INFO, "Versuchs mal mit: \"skommandos "+QueryProp(P_IDS)[1]+"\" !\n");
+
+  AD(({"schubladen"}), BS("Es sind viele, aber zum Glueck musst Du sie nicht "
+    +"einzeln ansprechen. Du kannst einfach alles in "+name(WEN,1)+" stecken."));
+  AD(({"moebelstueck"}), BS(Name(WER,1)+" ist gemeint."));
+}
diff --git a/d/seher/haeuser/moebel/kuehlschrank.c b/d/seher/haeuser/moebel/kuehlschrank.c
new file mode 100644
index 0000000..7bf1df4
--- /dev/null
+++ b/d/seher/haeuser/moebel/kuehlschrank.c
@@ -0,0 +1,45 @@
+//--------------------------------------------------------------------------------
+// Name des Objects:    Kuehlschrank
+// Letzte Aenderung:    17.03.2001
+// Magier:              Swift
+//--------------------------------------------------------------------------------
+#pragma strong_types,rtt_checks
+
+#include "schrankladen.h"
+inherit LADEN("swift_std_container");
+
+#define VERSION_OBJ "3"
+
+protected void create()
+{
+  if (!clonep(TO)) return;
+  swift_std_container::create();
+  SetProp(P_SHORT, "Ein Kuehlschrank");
+  SetProp(P_LONG, BS(
+     "Dieser strahlendweisse Kuehlschrank der Firma Brosch ueberzeugt durch "
+    +"ein leises Summen von seiner Funktion, auch wenn Du nicht weisst, woher "
+    +"er den Strom dafuer nimmt. Vermutlich auf magische Weise. Aber Du kennst "
+    +"das ja, mit Magie laesst sich fast alles erklaeren. Gut dass der "
+    +"Kuehlschrank so gross ist, man koennte einen ausgewachsenen Eisbaeren "
+    +"darin unterbringen - aber der duerfte wohl was dagegen haben.")
+    +"@@cnt_status@@");
+  AddId(({"kuehlschrank", "schrank"}));
+  SetProp("cnt_version_obj", VERSION_OBJ);
+  SetProp(P_NAME, "Kuehlschrank");
+  SetProp(P_GENDER, MALE);
+  SetProp(P_WEIGHT, 5000);         // Gewicht 5 Kg
+  SetProp(P_MAX_WEIGHT, 1000000);  // Es passen fuer 1000 kg Sachen rein.
+  SetProp(P_WEIGHT_PERCENT, 100);  // Dafuer macht er auch nix leichter :)
+  SetProp(P_MAX_OBJECTS, 100);     // Mehr sollte nicht sein, lt. Tiamak.
+  SetProp(P_VALUE, 0);             // Kein materieller Wert. Ist eh nicht verkaufbar.
+  SetProp(P_NOBUY, 1);             // Wird im Laden zerstoert, falls er verkauft wird.
+  SetProp(P_NOGET, "Das geht nicht. "+Name(WER,1)+" haftet wie magisch am Boden.\n");
+  SetProp(P_MATERIAL, ({MAT_MISC_METAL, MAT_MISC_MAGIC}) );
+  SetProp(P_INFO, "Versuchs mal mit: \"skommandos "+QueryProp(P_IDS)[1]+"\" !\n");
+
+  AD(({"strom"}), BS("Keine Ahnung, wo "+name(WER,1)+" den hernimmt, aber "
+    +"wie gesagt, bestimmt ist Magie im Spiel."));
+
+  AddSounds(({"summen"}), BS("Das Summen des Kuehlschranks ueberzeugt Dich davon, "
+    +"dass er an ist."));
+}
diff --git a/d/seher/haeuser/moebel/lesepult.c b/d/seher/haeuser/moebel/lesepult.c
new file mode 100644
index 0000000..4eb8300
--- /dev/null
+++ b/d/seher/haeuser/moebel/lesepult.c
@@ -0,0 +1,559 @@
+// Einiger Code wurde aus dem Questtagebuch des Tempels uebernommen.
+// Da man das Buch, sobald es im aufgestellten Lesepult des Spielers
+// abgelegt wurde, auch lesen koennen muss, sind die Funktionen und
+// Details auch weiterhin sinnvoll. Kaufen kann es jeder Seher, aber
+// nutzen kann man es nur mit dem von Hels Avatar ueberreichten Buch.
+
+#include <properties.h>
+#include <moving.h>
+#include <language.h>
+#include <wizlevels.h>
+#include "/d/seher/haeuser/moebel/moebel.h"
+#include "/d/seher/haeuser/haus.h"
+#include "/d/anfaenger/ark/knochentempel/files.h"
+#pragma strong_types,rtt_checks
+
+inherit LADEN("swift_std_container");
+
+static string owner;
+string le(string key);
+string in(string key);
+int cmd_eintragen(string str);
+int cmd_lesen(string str);
+int take_page(string str);
+int drop_book(string str);
+int cmd_blaettern(string str);
+int cmd_oeffnen(string str);
+int cmd_schliessen(string str);
+void AddTheOldDetails();
+
+protected void create()
+{
+ if(!clonep(this_object()))
+ {
+  set_next_reset(-1);
+  return;
+ }
+
+ ::create();
+
+owner="Anonymus";
+
+AddDetail("finger",BS(
+"Deine Finger sollten schon vorsichtig sein, wenn sie das Zeder"+
+"nholz beruehren. Einerseits, damit Du Dich nicht verletzt, and"+
+"ererseits, damit Du nichts beschmutzt.",78));
+AddDetail(({"holz","zedernholz","zeder"}),BS(
+"Aus einem einzigen starken Stamm einer Zeder bearbeitet, ist d"+
+"ieses edle Lesepult schon etwas sehr Feines und Dekoratives.",78));
+AddDetail(({"stamm","zedernstamm","holzstamm"}),BS(
+"Der Zedernstamm ist wahrlich kunstvoll veredelt worden, sein k"+
+"raeftiges Braun wurde hervorragend zur Geltung gebracht.",78));
+AddDetail(({"braun","dunkelbraun"}),BS(
+"Der dunkelbraune Stamm glaenzt wunderschoen, wenn Licht auf ih"+
+"n faellt. Ein sehr angenehmes Holz, das fuer das Lesepult verw"+
+"endet wurde.",78));
+AddDetail("geltung",BS(
+"Ja, dieses Holz gefaellt Dir sehr, das ganze Pult ist ein beme"+
+"rkenswertes Kunstwerk.",78));
+AddDetail(({"kunst","werk","kunstwerk"}),BS(
+"Immer wieder faellt Dein bewundernder Blick auf das Lesepult.",78));
+AddDetail("blick",BS(
+"Wachsam und flink wie immer, hat er jedoch ein wenig pausiert,"+
+" indem er muessig auf dem Lesepult ruht.",78));
+AddDetail(({"feines","dekoratives"}),BS(
+"Das teilweise eckige und dann wieder sanft geschwungene, runde"+
+" Lesepult sieht schon ziemlich repraesentativ aus.",78));
+AddDetail("zeder",BS(
+"Von ihr ist nurmehr das Pult geblieben, allerdings findest Du,"+
+" dass es nicht der schlechteste Teil ist.",78));
+AddDetail("teil",BS(
+"Du siehst nur den bearbeiteten Teil der Zeder vor Dir.",78));
+AddDetail("exemplar",BS(
+"Es ist ganz klar zu sehen, dass es sich nur um eine Zeder hand"+
+"elt, aus der dieses Pult entstand.",78));
+AddDetail(({"handwerk","kunst"}),BS(
+"Tatsaechlich ist dieses Lesepult ein sehr schoenes Beispiel ho"+
+"echster handwerklicher Kunst.",78));
+AddDetail("beispiel",BS(
+"Ein weiteres steht hier dummerweise nicht herum.",78));
+
+ SetProp("cnt_version_obj","1");
+ SetProp(P_NAME,"Lesepult");
+ SetProp(P_GENDER,NEUTER);
+ SetProp(P_NEVERDROP,1);
+ SetProp(P_VALUE,10);
+ SetProp(P_WEIGHT,500000);
+ SetProp(P_NOGET,"Das Lesepult ist Dir viel zu schwer.\n");
+ SetProp(P_NOSELL,"Du behaeltst das Lesepult lieber.\n");
+ SetProp(P_MATERIAL,([MAT_CEDAR:100]));
+ SetProp(H_FURNITURE,1);
+ SetProp(P_INFO,BS(
+ "Auf dieses Lesepult kann man ein ganz bestimmtes schwarzes Bu"+
+ "ch legen. Dort liegt es perfekt, um darin zu blaettern und zu"+
+ " lesen. Ausserdem birgt es sicher noch Geheimnisse.",78));
+
+ AddId(({"pult","lesepult","\nlesepult_ark"}));
+
+ AddCmd("eintragen&quest|aufgabe|loesung|erlebnis|abenteuer",
+ #'cmd_eintragen,"Was willst Du hier denn eintragen ?\n");
+ AddCmd(({"lies","lese","les"}),#'cmd_lesen);
+ AddCmd("nimm",#'take_page);
+ AddCmd(({"lege","leg"}),#'drop_book);
+ AddCmd("blaetter|blaettre|blaettere&in&buch|tagebuch|"
+ "tempeltagebuch",#'cmd_blaettern,"Worin willst Du blaettern ?|"
+ "Willst Du im Tagebuch blaettern ?");
+ AddCmd("oeffne&@ID|buch|tagebuch|tempeltagebuch",#'cmd_oeffnen,
+ "Was willst Du oeffnen?\n");
+ AddCmd("schliesse|schliess&@ID|buch|tagebuch|tempeltagebuch",
+ #'cmd_schliessen,"Was willst Du schliessen?\n");
+
+ if (MQTBMASTER->QueryTagebuchAufPult(this_player()))
+ AddTheOldDetails();
+}
+
+void SetOwner(string str)
+{
+ owner=str;
+}
+
+string QueryOwner()
+{
+ return owner;
+}
+
+string _query_short()
+{
+ if ((owner=="Anonymus")||
+      !this_player()||
+      !(MQTBMASTER->QueryTagebuchAufPult(this_player())))
+ return "Ein wunderschoenes Lesepult aus dunkelbraunem Zedernholz";
+ if (getuid(this_player())==owner)
+ return
+ "Ein wunderschoenes Lesepult, auf dem Dein Tagebuch des Tempels ruht";
+ else return
+ "Ein wunderschoenes Lesepult, das ein gueldenes Buch traegt";
+}
+
+string _query_long()
+{
+ if ((owner=="Anonymus")||
+      !this_player()||
+      !(MQTBMASTER->QueryTagebuchAufPult(this_player())))
+ return BS(
+ "Vorsichtig faehrst Du mit den Fingern ueber das dunkelbraune Holz."+
+ " Was Du spuerst, fuehlt sich kuehl und angenehm an, die Zeder, die"+
+ " fuer dieses bestaunenswerte Lesepult herhalten musste, wurde vors"+
+ "ichtig und aeusserst kunstfertig bearbeitet. Ein wirklich schoenes"+
+ " Exemplar holzhandwerklicher Kunst.",78);
+ if (getuid(this_player())==owner)
+ {
+  if (MQTBMASTER->QueryTagebuchAufPult(this_player()))
+  return BS(
+  "Vorsichtig faehrst Du mit den Fingern ueber das dunkelbraune Holz"+
+  ". Was Du spuerst, fuehlt sich kuehl und angenehm an, die Zeder, d"+
+  "ie fuer dieses bestaunenswerte Lesepult herhalten musste, wurde v"+
+  "orsichtig und aeusserst kunstfertig bearbeitet. Ein wirklich scho"+
+  "enes Exemplar holzhandwerklicher Kunst, Du bist froh, dieses Lese"+
+  "pult erstanden zu haben. Auf dem Lesepult siehst Du Dein schwarze"+
+  "s Tagebuch des Knochentempels, in dem Du nun nur noch lesen kanns"+
+  "t, denn Deine Abenteuer dort sind vollstaendig zu Papier gebracht"+
+  ". Allerdings kannst Du auch noch ein wenig weiter drin herumblaet"+
+  "tern, wenn Du magst.",78);
+  return BS(
+  "Vorsichtig faehrst Du mit den Fingern ueber das dunkelbraune Holz"+
+  ". Was Du spuerst, fuehlt sich kuehl und angenehm an, die Zeder, d"+
+  "ie fuer dieses bestaunenswerte Lesepult herhalten musste, wurde v"+
+  "orsichtig und aeusserst kunstfertig bearbeitet. Ein wirklich scho"+
+  "enes Exemplar holzhandwerklicher Kunst, Du bist froh, dieses Lese"+
+  "pult erstanden zu haben. Ein wenig gruebeln laesst Dich die Tatsa"+
+  "che, dass das Lesepult leer ist. Was man dort wohl platzieren kan"+
+  "n ?",78);
+ }
+ return BS(
+ "Vorsichtig faehrst Du mit den Fingern ueber das dunkelbraune Holz."+
+ ". Was Du spuerst, fuehlt sich kuehl und angenehm an, die Zeder, di"+
+ "e fuer dieses bestaunenswerte Lesepult herhalten musste, wurde vor"+
+ "sichtig und aeusserst kunstfertig bearbeitet. Ein wirklich schoene"+
+ "s Exemplar holzhandwerklicher Kunst, Du bist ein wenig neidisch."+
+ ""+(MQTBMASTER->QueryTagebuchAufPult(this_player())?" Auf dem Lesep"+
+ "ult wurde ein schwarzes Buch abgelegt, das sehr wertvoll aussieht.":
+ " Das Lesepult sieht ohne dazugehoeriges Buch ein wenig einsam aus.")+".",78);
+}
+
+void AddTheOldDetails()
+{
+ AddDetail(({"buch","buechlein","tagebuch"}),BS(
+ "Dies ist ein kleines Buechlein aus Gold, auf dem ein Name in "+
+ "schwarzen Lettern steht. Ansonsten ist der Einband schlicht, "+
+ "das Papier schon ausfuehrlich beschrieben und vom vielen Blae"+
+ "ttern hier und da auch schon ein wenig geknickt.",78));
+ AddDetail("blaettern",BS(
+ "Ja, das schoene Buechlein ist von haeufigem Blaettern nicht s"+
+ "choener geworden, aber irgendetwas Magisches hat es schon an "+
+ "sich. Ab und an magst Du immer wieder einmal herumblaettern.",78));
+ AddDetail("magisches",BS(
+ "Es ist nicht so einfach zu ergruenden, indem man einmal genau"+
+ "er hinsieht.",78));
+ AddDetail("leder",BS(
+ "Das Leder ist glatt und vollkommen guelden. Nur die schwarzen"+
+ " Lettern geben einen angenehmen Kontrast ab. Irgendwie seltsa"+
+ "m, denn Du findest, dass Schwarz und Gold eigentlich umgekehr"+
+ "t mehr Sinn machen.",78));
+ AddDetail("sinn",BS(
+ "Vielleicht ist aber auch alles bestens, und nur Dein Verstand"+
+ " will das nicht nachvollziehen.",78));
+ AddDetail("verstand",BS(
+ "Ja, auch Du kannst ihm nicht immer folgen, also wundere Dich "+
+ "nicht, warum dieses Leder hier golden verfaerbt ist und die B"+
+ "uchstaben darauf schwarz.",78));
+ AddDetail(({"lettern","buchstaben"}),BS(
+ "Du kannst sie lesen.",78));
+ AddDetail(({"name","namen"}),BS(
+ "Man kann ihn genauso lesen wie die Buchstaben.",78));
+ AddDetail("kontrast",BS(
+ "Die Buchstaben heben sich wirklich deutlich vom gueldenen Led"+
+ "er des Einbands ab.",78));
+ AddDetail("einband",BS(
+ "Es ist kein aufwaendiger Einband, fuerwahr. Dennoch faszinier"+
+ "t die Pracht, die mit den schwarzen Lettern kontrastiert.",78));
+ AddDetail("pracht",BS(
+ "So muss man den goldenen Einband wohl nennen.",78));
+ AddDetail(({"papier","seiten","buchseiten","seite","buchseite"}),BS(
+ "Das Papier ist von guter Qualitaet, die Buchseiten lassen sic"+
+ "h sicher einfach beschreiben.",78));
+ AddDetail(({"schwarze buchseiten","schwarze buchseite",
+ "schwarze buchseite"}),BS(
+ "Tatsaechlich, beim Blaettern siehst Du einige schwarze Buchse"+
+ "iten, die unbeschrieben sind. Was hat dies zu bedeuten ?",78));
+ AddDetail("qualitaet",BS(
+ "Du siehst, dass das Papier fest und bluetenweiss ist.",78));
+ AddReadDetail(({"buch","buechlein","tagebuch"}),BS(
+ "Das Buch hat ein Inhaltsverzeichnis. Wenn dort etwas steht, k"+
+ "annst Du das oder die Kapitel sicher lesen.",78));
+ AddDetail("kapitel",BS(
+ "Lies nur im Inhaltsverzeichnis nach, vielleicht hat das Buch "+
+ "bereits ein oder mehrere Kapitel.",78));
+ AddReadDetail("kapitel",BS(
+ "Welches Kapitel willst Du denn lesen ? Sie sind sicher durchn"+
+ "ummeriert, wenn man schon etwas im Buch niedergeschrieben hat.",78));
+ AddReadDetail(({"name","namen","buchstaben","lettern"}),#'le);
+ AddReadDetail(({"inhalt","inhaltsverzeichnis"}),#'in);
+ SetProp(P_MATERIAL,([MAT_LEATHER:10,MAT_PAPER:15,MAT_CEDAR:75]));
+}
+
+int drop_book(string str)
+{
+ if (!stringp(str))
+ return 0;
+ if (strstr(lower_case(str),"pult",0)==-1)
+ return 0;
+ notify_fail(BS(
+ "Willst Du etwas auf das Pult legen ? Ein Buch waere passend, "+
+ "aber es sollte schon etwas Besonderes sein.",78));
+ if (strstr(lower_case(str),"buch",0)==-1&&
+     strstr(lower_case(str),"buechlein",0)==-1)
+ return 0;
+ notify_fail(BS(
+ "Das ist nicht Dein Lesepult, Du laesst es besser in Ruhe.",78));
+ if (getuid(this_player())!=owner)
+ return 0;
+ notify_fail(BS(
+ "Auf dem Pult liegt schon ein goldenes Buch.",78));
+ if (MQTBMASTER->QueryTagebuchAufPult(this_player()))
+ return 0;
+ notify_fail(BS(
+ "Entweder hast Du Dich noch nicht als wuerdig erwiesen, indem "+
+ "Du alle Aufgaben im Knochentempel erfuellt hast oder Du hast "+
+ "dem Avatar des Waechters der Nacht, Mhun'dae Hel, noch nicht "+
+ "Deine Aufwartung gemacht und ihm gezeigt, dass Du wuerdig bis"+
+ "t, ein geeignetes Buch zu empfangen. Auf alle Faelle kannst D"+
+ "u hier noch nichts auf das Pult legen.",78));
+ if (!present_clone(OBJ("buechlein_invers"),this_player()))
+ return 0;
+ MQTBMASTER->AddBuchAufPult(this_player());
+ this_player()->ReceiveMsg(BS(
+ "Vorsichtig schlaegst Du Dein gueldenes Tagebuch auf, das Dir "+
+ "Mhun'dae Hel, das Avatar des Waechters der Nacht, ueberreicht"+
+ " hat. Du legst es sachte auf das Pult und merkst, dass es sof"+
+ "ort eine magische Verbindung mit dem Lesepult eingeht. Es ist"+
+ " nun untrennbar mit diesem verbunden.",78),MT_MAGIC,MA_USE);
+ tell_room(environment(),BS(
+ this_player()->Name(WER)+" legt vorsichtig ein gueldenes Buch "+
+ "mit schwarzen Lettern aufgeschlagen auf dem Lesepult ab und b"+
+ "etrachtet dieses dann ehrfuerchtig und zutiefst zufrieden.",78),
+ ({this_player()}));
+ return 1;
+}
+
+int cmd_blaettern(string str)
+{
+ notify_fail(BS(
+ "Auf dem Lesepult liegt doch gar kein Tagebuch.",78));
+ if (!(MQTBMASTER->QueryTagebuchAufPult(find_player(owner))))
+ return 0;
+ notify_fail(BS(
+ "Das ist nicht Dein Tagebuch, Du laesst es lieber in Frieden.",78));
+ if (getuid(this_player())!=owner)
+ return 0;
+ this_player()->ReceiveMsg(BS(
+ "Du blaetterst ein wenig durch Dein Tagebuch und stoesst auf e"+
+ "inige raetselhafte schwarze Seiten. Was mag es damit auf sich"+
+ " haben ? Ob Du sie herausnehmen kannst ?",78),MT_LOOK,MA_LOOK);
+ return 1;
+}
+
+int take_page(string str)
+{
+ if (!stringp(str))
+ return 0;
+ if (present(str,environment()))
+ return 0;
+ notify_fail(BS(
+ "Wo siehst Du denn hier ein Buch ?",78));
+ if (!(MQTBMASTER->QueryTagebuchAufPult(this_player()))&&
+     strstr(lower_case(str),"buch")!=-1)
+ return 0;
+ if ((owner!=getuid(this_player()))&&
+     strstr(lower_case(str),"buch")!=-1)
+ notify_fail(BS(
+ "Dies ist nicht Dein Lesepult oder Dein Buch darauf, deshalb l"+
+ "aesst Du es vorsichtshalber liegen.",78));
+ return 0;
+ if ((owner!=getuid(this_player()))&&
+     strstr(lower_case(str),"seite")!=-1)
+ notify_fail(BS(
+ "Die Eigentuemerin oder der Eigentuemer des Lesepults haette s"+
+ "icher etwas dagegen, wenn Du das Buch zerstoerst, also laesst"+
+ " Du es lieber.",78));
+ return 0;
+ // Heilung 1x alle 6 Stunden.
+ if (this_player()->check_and_update_timed_key(21600,"Ark_Hels_Schwarzes_Buch")==-1)
+ {
+  object o;
+  this_player()->ReceiveMsg(BS(
+  "Du reisst erst vorsichtig eine schwarze Seite und dann eine"+
+  " weitere aus dem goldenen Buch. Dann ueberfaellt Dich eine "+
+  "kleine Schwaeche, die Dich vor weiterem Zerstoeren innehalt"+
+  "en laesst. Du solltest Hels Grosszuegigkeit nicht ueberscha"+
+  "etzen.",78),MT_FEEL,MA_TAKE);
+  tell_room(environment(),BS(
+  this_player()->Name(WER)+" reisst zwei Seiten aus dem Buch, "+
+  "das auf dem Pult liegt. Dann haelt "+this_player()->QueryPronoun(WER)+""+
+  " inne, wahrscheinlich folgt "+this_player()->QueryPronoun(WER)+""+
+  " einer klugen Eingebung.",78));
+  o=clone_object(OBJ("reg_seite"));
+  if (o->move(this_player())!=MOVE_OK)
+  {
+   o->remove(1);
+   this_player()->ReceiveMsg(BS(
+   "Du kannst die erste Seite nicht mehr tragen, sie loest sic"+
+   "h einfach auf.",78),MT_MAGIC,MA_REMOVE);
+  }
+  // Die erste Seite behandelt, hier, falls man auch die zweite
+  // Seite nicht tragen kann oder mit der ersten am Limit ist.
+  o=clone_object(OBJ("reg_seite"));
+  if (o->move(this_player())!=MOVE_OK)
+  {
+   o->remove(1);
+   this_player()->ReceiveMsg(BS(
+   "Du kannst die zweite Seite nicht mehr tragen, sie loest si"+
+   "ch einfach auf.",78),MT_MAGIC,MA_REMOVE);
+  }
+  return 1;
+ }
+ this_player()->ReceiveMsg(BS(
+ "Vergeblich reisst Du mehr oder weniger vorsichtig an einigen"+
+ " schwarzen Seiten im Buch herum, doch sie bleiben stoerrisch"+
+ ". Es wird wohl ein wenig dauern, bis Du das wieder versuchen"+
+ " kannst.",78),MT_MAGIC,MA_USE);
+ tell_room(environment(),BS(
+ this_player()->Name(WER)+" reisst im Buch auf dem Lesepult he"+
+ "rum.",78),({this_player()}));
+ return 1;
+}
+
+int cmd_lesen(string str)
+{
+int k;
+ if(!str) return 0;
+ if (owner=="Anonymus")
+ {
+  write (BS(
+  "Dieses Lesepult scheint niemandem zu gehoeren ... es loest s"+
+  "ich daher einfach auf, als Du darauf etwas lesen willst.",78));
+  remove(1);
+  return 1;
+ }
+ if (getuid(this_player())!=owner)
+ {
+  notify_fail(BS(
+  "Dieses Tagebuch gehoert "+capitalize(owner)+", nicht Dir, Du"+
+  " bist eigentlich nicht so recht an dem interessiert, was man"+
+  " in dem Buch niedergeschrieben hat. Sicher ist es uebertrieb"+
+  "en langatmig formuliert und stimmt nicht genau mit dem ueber"+
+  "ein, was wirklich geschah. Man kennt das ja.",78));
+  return 0;
+ }
+ if (strstr(lower_case(str),"kapitel",0)!=-1&&
+     sscanf(lower_case(str),"kapitel %d",k)!=1)
+ {
+  write (BS(
+  "Willst Du ein Kapitel aus dem Buch lesen ? Dann gib bitte ei"+
+  "ne Ziffer an.",78));
+  return 1;
+ }
+ if (k>0)
+ {
+  MQTBMASTER->LiesQuest(k,this_player());
+  return 1;
+ }
+ return 0;
+}
+
+int cmd_eintragen(string str)
+{
+int i;
+ if (!(MQTBMASTER->QueryTagebuchAufPult(this_player())))
+ {
+  notify_fail(BS(
+  "Du findest hier nichts, worin Du etwas eintragen koenntest.",78));
+  return 0;
+ }
+ if (getuid(this_player())!=owner)
+ {
+  notify_fail(BS(
+  "Dieses Tagebuch gehoert "+capitalize(owner)+", nicht Dir, Du"+
+  " kannst darin nichts eintragen.",78));
+  return 0;
+ }
+ notify_fail(BS(
+ "Deine Missionen im Knochentempel ... besser gesagt, dem Wyrmt"+
+ "empel, sie sind allesamt tapfer von Dir erfuellt worden. Du k"+
+ "annst hier nichts weiter mehr eintragen, sicher aber von der "+
+ "arkanen Macht des Buches profitieren, wenn Du es einmal durch"+
+ "blaetterst.",78));
+ return 0;
+}
+
+string calc_name()
+{
+string *nam;
+string res;
+int i,j;
+ res="";
+ if (owner=="")
+ return "";
+ nam=explode(upperstring(owner),"");
+ if (j=sizeof(nam))
+ {
+  switch(j)
+  {
+   case 3..4:
+    res="          ";
+    break;
+   case 5:
+    res="        ";
+    break;
+   case 7:
+    res="      ";
+    break;
+   case 9:
+    res="    ";
+    break;
+   default:
+    res="   ";
+  }
+  for (i=0;i<j;i++)
+  {
+   res+=nam[i]+" ";
+  }
+ }
+ return res;
+}
+
+string le(string key)
+{
+ return "\n"+
+ "    De Templum Os Hel\n\n"+
+ calc_name()+"\n\n";
+}
+
+string in(string key)
+{
+ if (owner!=getuid(this_player()))
+ return "Dort steht allerdings nichts. Seltsam.\n";
+ return MQTBMASTER->LiesInhalt(find_player(owner));
+}
+
+// Das hier bezeichnet den Urheber des Moebelstuecks.
+// Nicht meine Idee!
+string GetOwner() { return "Ark"; }
+
+int cmd_oeffnen(string str)
+{
+ if (strstr(lower_case(str),"pult")!=-1)
+ {
+  this_player()->ReceiveMsg(
+  "Du kannst das Pult nicht oeffnen, nur etwas zum Lesen darauflegen.",
+  MT_LOOK,MA_FEEL);
+  return 1;
+ }
+ if (strstr(lower_case(str),"buch")!=-1)
+ {
+  if (!(MQTBMASTER->QueryTagebuchAufPult(this_player())))
+  return 0;
+  this_player()->ReceiveMsg(
+  "Das schwarze Buch ist doch schon geoeffnet.",MT_LOOK,MA_FEEL);
+  return 1;
+ }
+ // Alles andere per Default.
+ return 0;
+}
+
+int cmd_schliessen(string str)
+{
+ if (strstr(lower_case(str),"pult")!=-1)
+ {
+  this_player()->ReceiveMsg(
+  "Du kannst das Pult nicht schliessen.",MT_LOOK,MA_FEEL);
+  return 1;
+ }
+ if (strstr(lower_case(str),"buch")!=-1)
+ {
+  if (!(MQTBMASTER->QueryTagebuchAufPult(this_player())))
+  return 0;
+  this_player()->ReceiveMsg(
+  "Das Buch bleibt trotz Deiner Bemuehungen einfach offen.",MT_LOOK,MA_FEEL);
+  return 1;
+ }
+ else return 0;
+}
+
+mixed _query_noget()
+{
+ if (getuid(this_player())!=owner)
+ return BS(
+ "Dies ist offensichtlich nicht Dein Pult, deshalb laesst "+
+ "Du es auch besser liegen.",78);
+ return 0;
+}
+
+string _query_autoloadobj()
+{
+ return QueryOwner();
+}
+
+string _set_autoloadobj(string s)
+{
+ return QueryOwner();
+}
+
+// Beim Kauf setzen wir erstmal nur den Eigentuemer.
+// Ist aus Swifts Container, der diese Funktion im
+// NotifyMove() aufruft.
+protected void SetBesitzer(string uid, string uuid)
+{
+ SetOwner(uid);
+ MQTBMASTER->AddLesepult(find_player(uid)||find_netdead(uid));
+}
diff --git a/d/seher/haeuser/moebel/moebel.h b/d/seher/haeuser/moebel/moebel.h
new file mode 100644
index 0000000..debc474
--- /dev/null
+++ b/d/seher/haeuser/moebel/moebel.h
@@ -0,0 +1,13 @@
+#ifndef _SEHERMOEBEL_H_
+#define _SEHERMOEBEL_H_
+
+#define LADEN(x) "/d/seher/haeuser/moebel/"+x
+#define RAUM_VOR_LADEN "/d/unterwelt/wurzel/dorf/nstr2"
+#define IDEEN_LOG "ideen.log"
+#define SHVERWALTER "/d/seher/haeuser/hausverwalter"
+#define VERANTWORTLICHER_MAGIER "Seleven" 
+// Der Erhaelt Bug-Mails der Spieler!
+#define SCHRANKMASTER load_object(LADEN("schrankmaster"))
+
+#endif // _SEHERMOEBEL_H_
+
diff --git a/d/seher/haeuser/moebel/muellcontainer.c b/d/seher/haeuser/moebel/muellcontainer.c
new file mode 100644
index 0000000..1e95d18
--- /dev/null
+++ b/d/seher/haeuser/moebel/muellcontainer.c
@@ -0,0 +1,92 @@
+//--------------------------------------------------------------------------------
+// Name des Objects:    Muellcontainer
+// Letzte Aenderung:    17.03.2001
+// Magier:              Swift
+//--------------------------------------------------------------------------------
+
+#include "schrankladen.h"
+inherit LADEN("swift_std_container");
+
+#define VERSION_OBJ ".003"
+
+create()
+{
+  if (!clonep(TO)) return;
+  swift_std_container::create();
+  SetProp(P_SHORT, "Ein Muellcontainer");
+  SetProp(P_LONG, BS(
+     "Ein grosser Container aus Stahl, aus dem es nicht gerade angenehm duftet. "
+    +"Offensichtlich werden dort alle Sachen entsorgt, die Seher nicht gerne in "
+    +"ihrem Haus oder auf der Strasse herumliegen sehen.")
+    +"@@cnt_status@@");
+  AddId(({"muellcontainer", "container"}));
+  SetProp("cnt_version_obj", VERSION_OBJ);
+  SetProp(P_NAME, "Muellcontainer");
+  SetProp(P_GENDER, MALE);
+  SetProp(P_WEIGHT, 5000);         // Gewicht 5 Kg
+  SetProp(P_MAX_WEIGHT, 1000000);  // Es passen fuer 1000 kg Sachen rein.
+  SetProp(P_WEIGHT_PERCENT, 100);  // Dafuer macht er auch nix leichter :)
+  SetProp(P_MAX_OBJECTS, 100);     // Mehr sollte nicht sein, lt. Tiamak.
+  SetProp(P_VALUE, 0);             // Kein materieller Wert. Ist eh nicht verkaufbar.
+  SetProp(P_NOBUY, 1);             // Wird im Laden zerstoert, falls er verkauft wird.
+  SetProp(P_NOGET, "Das geht nicht. "+Name(WER,1)+" haftet wie magisch am Boden.\n");
+  SetProp(P_MATERIAL, ({MAT_STEEL, MAT_MISC_MAGIC}) );
+  SetProp(P_INFO, "Versuchs mal mit: \"skommandos "+QueryProp(P_IDS)[1]+"\" !\n");
+
+  AddSmells(({"container", "duft", "gestank"}), BS("Aus "+name(WEM,1)+" stinkt es "
+    +"schon ganz schoen, aber Deine Nase ist ja allerhand gewoehnt."));
+
+  AddCmd(({"wirf", "werf", "werfe"}), "wegwerfen");
+}
+
+int wegwerfen(string str)
+{
+  string was,inwas;
+  notify_fail("Was willst Du wo hinein werfen?\n");
+  if(!str) return 0;
+  if( sscanf(str, "%s in %s", was, inwas) != 2)
+    return 0;
+  if( present(inwas)==TO )   // Dies Objekt ist gemeint!
+  {
+    TP->command_me("stecke "+str);
+    return 1;
+  }
+  return 0;  
+}
+
+varargs int PreventInsert(object ob)
+{
+  if( living(ob) )
+  {
+    write( BS("Lebewesen kannst Du nicht in "+name(WEN,1)+" werfen!"));
+    return 1;
+  }
+  else if( ob->QueryProp(P_VALUE) )
+  {
+    write( BS("Nur Dinge ohne materiellen Wert lassen sich in "
+      +name(WEN,1)+" werfen."));
+    return 1;
+  }
+  else if( ob->QueryProp(P_CURSED) )
+  {
+    write( BS("Verfluchte Dinge kannst Du nicht in "+name(WEN,1)+" werfen!"));
+    return 1;
+  }
+  else
+    return ::PreventInsert(ob);
+}
+
+void reset()
+{
+  int i;
+  object *inv;
+  ::reset();
+  inv=all_inventory(TO);
+  if(inv && sizeof(inv))
+  {
+    for(i=sizeof(inv)-1;i>=0;i--)
+      destruct(inv[i]);
+    tell_room(ETO, BS("Aus "+name(WEM,1)+" ertoent kurz ein Knistern und Knacken, "
+           +"dann ist wieder Ruhe."));
+  }
+}
diff --git a/d/seher/haeuser/moebel/preisliste.txt b/d/seher/haeuser/moebel/preisliste.txt
new file mode 100644
index 0000000..05e7839
--- /dev/null
+++ b/d/seher/haeuser/moebel/preisliste.txt
@@ -0,0 +1,102 @@
+
+=====================================================
+D E R   S C H R A E N K E R   -   P R E I S L I S T E
+=====================================================
+
+Herzlich willkommen im SCHRAENKER. Bei uns finden Sie
+das ideale Mobiliar fuer Ihr Seherhaus. Weg mit der
+Unordnung zuhaus, bringen Sie ihre Ausruestung ueber-
+sichtlich und wohlsortiert in unseren edlen Moebel-
+stuecken unter. Wir hoffen, unsere Auswahl findet
+Ihren Gefallen.
+
+ANMERKUNG: Die Waren, die hier aufgelistet sind, sind NICHT REBOOTFEST !
+           Evtl. werden wir dies zu einem spaeteren Zeitpunkt ins Auge
+           fassen, im Moment ist es nicht so, wir versuchen lieber, die
+           Moebelstuecke zu verbessern, um sie auch an die ungewoehnlichsten
+           Objekte im MorgenGrauen anzupassen.
+
+Art.-Nr.   Name             Beschreibung                                Preis
+-----------------------------------------------------------------------------
+ 1         Kommode          Eine robuste Kommode aus Eichenholz. Sie    3.799
+                            passt in jeden Raum und bietet jede Menge
+                            Platz zum Verstauen von Dingen aller Art.
+
+ 2         Kleiderschrank   Ein massiver Holzschrank, in dem Sie        5.899
+                            Kleider und Ruestungen aller Art unter-
+                            bringen koennen. Der Schrank verfuegt
+                            ueber ein Kommando zur Auflistung von
+                            Ruestungstypen.
+
+ 3         Spind            Ein grosser, einfacher Stahlschrank. Darin  5.299
+                            lassen sich Kleider und Ruestungen aller
+                            Art unterbringen. Der Spind verfuegt ueber
+                            ein Kommando zur Auflistung von Ruestungs-
+                            typen.
+
+ 4         Kuehlschrank     Ein strahlendweisser Kuehlschrank aus dem   3.499
+                            Hause Brosch. Passt in jede Kueche. Darin
+                            bleiben Ihre Speisen und Getraenke frisch!
+
+ 5         Waffenschrank    Ein massiver Holzschrank mit Faechern fuer  5.899
+                            Waffen aller Art. Jede Waffengattung hat
+                            ihren einenen Platz, es gibt ein Kommando
+                            zur Auflistung von Waffentypen.
+
+ 6         Waffentruhe      Eine Stahltruhe mit verschiedenen Faechern  5.399
+                            zur Aufnahme von Waffen aller Art. Die
+                            Truhe verfuegt ueber ein Kommando zur
+                            Auflistung von Waffentypen.
+
+ 7         Tresor           Sichern Sie Ihr Vermoegen gegen Einbruch    4.499
+                            und Diebstahl. Wie? Ganz einfach: Mit
+                            diesem stabilen, feuersicheren Tresor
+                            sind Ihre Wertsachen sicher.
+
+ 8         Zauberkiste      Sind Sie Zauberer? Oder einfach nur Sammler 7.999
+                            hier von Zauberer-Komponenten? Dann haben
+                            wir ein Moebelstueck fuer Sie, das Sie haben
+                            muessen! Aus magischem Birnbaumholz gefertigt.
+
+ 9         Muellcontainer   Der Ersatz fuer den Muellschlucker.           999
+                            Nie mehr brauchen Sie einen Laden aufsuchen,
+                            nur um wertlosen Plunder loszuwerden.
+                            
+10         Schluesselbrett  Sie haben durch Ihre Abenteuer einen Sack     499
+                            voll Schluessel? Dieses Brett schafft
+                            Ordnung.
+
+11         Duschkabine      Endlich auch fuer Ihr Zuhause:              3.499
+                            Eine ultramoderne Waschgelegenheit. Sie 
+                            koennen sogar selbst einstellen, womit Sie 
+                            Sich waschen wollen!
+
+12         mag. Holztruhe   Haben auch Sie Probleme mit einem ueber-   74.999
+                            vollen Inventar? Wir haben jetzt die
+                            Loesung fuer Sie: diese kleine Holztruhe
+                            nimmt ihre ewigen Objekte auf und 
+                            bewahrt sie sicher ueber den naechsten
+                            Weltuntergang hinaus auf!
+ 
+13         Vitrine          Gehoeren Sie auch zu den tapferen Helden,  49.999
+                            die sich bereits Pokale verdient haben? 
+                            Dann sollten Sie sich diese Vitrine 
+                            zulegen, damit Ihre Pokale eine passende
+                            Umgebung erhalten und auch beim Welt-
+                            untergang geschuetzt sind.
+
+14         Lesepult         Das hat man sich redlich verdient! Eine    60.000
+                            schoene Belohnung, wenn man schliesslich
+                            den knoechernen Tempel mal so richtig
+                            aufgeraeumt hat. Und zwar vollstaendig,
+                            so dass selbst der Totengott staunt.
+                            Endlich koennen Sie, wenn er es denn dann
+                            auch zufrieden ist, das Tagebuch hierauf
+                            ablegen und in aller Ruhe blaettern.
+-----------------------------------------------------------------------------
+Anm. der Geschaeftsleitung:
+Wir bemuehen uns, Ihrem Geschmack und Ihren Beduerfnissen gerecht zu werden.
+Falls Sie Verbesserungsvorschlaege haben, oder falls Sie Moebelstuecke fuer Ihr
+Haus in unserem Angebot vermissen, so setzen Sie doch bitte eine entsprechende
+Idee im Laden ab.
+-----------------------------------------------------------------------------
diff --git a/d/seher/haeuser/moebel/schluesselbrett.c b/d/seher/haeuser/moebel/schluesselbrett.c
new file mode 100644
index 0000000..93bace6
--- /dev/null
+++ b/d/seher/haeuser/moebel/schluesselbrett.c
@@ -0,0 +1,679 @@
+//---------------------------------------------------------------------------
+// Name des Objects:    Schluesselbrett
+// Letzte Aenderung:    02.06.2001
+// Original:            Swift
+// Neue Version:        Seleven
+// Übernommen:          23.01.2006
+//---------------------------------------------------------------------------
+/* Changelog
+   * 21.06.2007, Zesstra
+     im inherit abs. Pfad durch LADEN(x) ersetzt.
+   * 01.07.2007, Zesstra
+     GetOwner() definiert.
+   * 11.05.2015, Arathorn
+     weitraeumig ueberarbeitet zur Behebung von Fehlfunktionen
+*/
+#pragma strong_types, rtt_checks
+
+#include "/d/seher/haeuser/moebel/schrankladen.h"
+#include <ansi.h>
+inherit  LADEN("swift_std_container");
+
+#define VERSION_OBJ "3"
+// Zur Indizierung des Mappings <haken>
+#define HOOK_OB    0
+#define HOOK_LABEL 1
+
+private varargs string KeyDescription(int keynum);
+private int IsValidKey(object ob);
+private int GetNextFreeSlot();
+private object GetKeyForLabel(string label);
+private int GetHookNumberForKey(object ob);
+private void ConsolidateInventory();
+
+// Struktur: ([ haken_nr : objekt; beschriftung ])
+private mapping haken=([:2]);
+private int hooklist_long = 0;
+
+protected void create() {
+  if (!clonep(TO)) {
+    set_next_reset(-1);
+    return;
+  }
+  ::create();
+  
+  foreach(int i: 1..16) {
+    m_add(haken, i);
+  }
+
+  // DEBUG! Sonst funktioniert's ausserhalb von Seherhaeusern nicht.
+  SetProp("test",1);
+  SetProp(P_SHORT, "Ein Schluesselbrett");
+  Set(P_LONG, function string () {
+    string text = BS(
+      "Ein kleines Brett aus Holz, an dem in 2 Reihen je 8 Haken befestigt "
+      "sind, an die man insgesamt 16 Schluessel haengen kann. Um die "
+      "Uebersicht nicht zu verlieren, befindet sich ueber jedem der Haken "
+      "ein kleines Schildchen aus Schiefer, das sich beschriften laesst. "
+      "Auf diese Weise geht der Sinn und Zweck des Schluessels, der an "
+      "diesem Haken ruht, nicht verloren. Praktischerweise haengt an einer "
+      "Schnur ein Stueck Kreide von dem Brett herab, mit dem Du die "
+      "Schildchen beschriften kannst.");
+    text += KeyDescription(0);
+    return text; 
+  }, F_QUERY_METHOD);
+
+  AddId(({"schluesselbrett","brett"}));
+  SetProp("cnt_version_obj", VERSION_OBJ);
+  SetProp(P_CNT_STATUS, 0);
+  SetProp(P_NAME, "Schluesselbrett");
+  SetProp(P_GENDER, NEUTER);
+  SetProp(P_WEIGHT, 1000);         // Gewicht 1 Kg
+  SetProp(P_MAX_WEIGHT, 1000000);  // Es passen fuer 1000 kg Sachen rein.
+  SetProp(P_WEIGHT_PERCENT, 100);  // Dafuer macht er auch nix leichter :)
+  SetProp(P_MAX_OBJECTS, 16);
+  // Man soll nichts ueber den normalen Mechanismus reinstecken oder 
+  // rausnehmen koennen. Wird von put_and_get.c geprueft.
+  SetProp(P_CONTAINER, 0);
+  SetProp(P_NOINSERT_MSG, BS("An das Schluesselbrett kannst Du nur "
+    "Schluessel haengen.\nSyntax: 'haenge <schluessel> an brett'."));
+  SetProp(P_NOGET, "Das geht nicht. "+Name(WER,1)+
+    " laesst sich nicht bewegen.\n");
+  SetProp(P_MATERIAL, ({MAT_OAK, MAT_MISC_MAGIC}) );
+  SetProp(P_INFO, "Versuch's mal mit: \"skommandos schluesselbrett\".\n");
+
+  AD(({"holz"}), BS("Echte, robuste Eiche."));
+
+  RemoveCmd(({"schliesse","schliess","oeffne"}));
+
+  AddCmd(({"unt", "untersuche", "betrachte", "betracht", "betr",
+           "schaue", "schau"}), "unt_haken");
+  AddCmd(({"haeng", "haenge"}), "schluessel_an_haken_haengen");
+  AddCmd(({"nimm"}), "schluessel_von_haken_nehmen");
+  AddCmd("sbeschrifte", "cmd_beschriften");
+  AddCmd("sliste", "cmd_sliste");
+}
+
+/***** KOMMANDOFUNKTIONEN *****/
+
+// Konfiguration der Schluesselliste, entweder "alle" anzeigen oder nur die
+// belegten Haken.
+static int cmd_sliste(string str) {
+  notify_fail("Syntax: 'sliste alle|belegte'.\n");
+  if ( !stringp(str) || !sizeof(str) )
+    return 0;
+
+  if ( str == "alle" ) {
+    if ( !hooklist_long ) {
+      tell_object(TP, BS("Ok, es werden jetzt immer alle Haken "
+        "aufgelistet."));
+      hooklist_long = 1;
+    }
+    else 
+      tell_object(TP, BS("Die Einstellung war schon 'alle'."));
+  }
+  else if ( str == "belegte" ) {
+    if ( hooklist_long ) {
+      tell_object(TP, BS("Ok, es werden jetzt nur die belegten Haken "
+        "aufgelistet."));
+      hooklist_long =0;
+    }
+    else 
+      tell_object(TP, BS("Die Einstellung war schon 'belegte'."));
+  }
+  else 
+    return 0;
+  return 1;
+}
+
+// Haken untersuchen. Ohne Angabe der Nummer werden alle ausgegeben,
+// ansonsten der gewuenschte, sofern es diesen gibt.
+static int unt_haken(string str) {
+  if ( !stringp(str) || !sizeof(str) || strstr(str, "haken") == -1 )
+    return 0;
+  
+  int hakennr;
+  if ( sscanf(str, "haken %d", hakennr) != 1 ) {
+    string det = KeyDescription(hakennr);
+    tell_object(TP, sizeof(det) ? det : "Die Haken sind alle leer.\n");
+    return 1;
+  }
+
+  notify_fail("Welchen Haken moechtest Du untersuchen? Es gibt nur die "
+    "Haken 1 bis 16.\n");
+  if( hakennr<1 || hakennr > 16 )
+    return 0;
+
+//  ausgabe_haken(hakennr);
+  tell_object(TP, KeyDescription(hakennr));
+  return 1;
+}
+
+// Schluessel aufhaengen.
+static int schluessel_an_haken_haengen(string str) {
+  notify_fail("Was willst Du woran haengen?\n");
+  if(!stringp(str) || !sizeof(str))
+    return 0;
+  
+  notify_fail("Das darfst Du nicht.\n");
+  if(!erlaubt())
+    return 0;
+
+  string was, woran;
+  notify_fail("Folgende Syntax versteht Dein Schluesselbrett:\n"
+    "  \"haenge <schluesselname> an haken [nr]\" oder\n"
+    "  \"haenge <schluesselname> an [schluessel]brett\".\n");
+  if ( sscanf(str, "%s an %s", was, woran) != 2 )
+    return 0;
+
+  notify_fail("Was moechtest Du an das Schluesselbrett haengen?\n");
+  if ( !stringp(was) ) 
+    return 0;
+
+  notify_fail("Woran willst Du das denn haengen?\n");
+  if ( strstr(woran, "haken", 0)==-1 && !id(woran) )
+    return 0;
+
+  // Test, ob es Objekte dieses Namens gibt.
+  object *obs = TP->find_obs(was, PUT_GET_NONE);
+  // Aus der Liste der gefundenen Objekte alle rausfiltern, die keine
+  // Schluessel sind. Als Schluessel gelten hier alle Objekte, die die
+  // ID "schluessel" haben oder die mittels QueryDoorKey() einer bestimmten
+  // Tuer zugeordnet sind.
+  obs = filter(obs, #'IsValidKey);
+  notify_fail("Keine(n) Schluessel mit dem Namen gefunden.\n");
+  if ( !sizeof(obs) )
+    return 0;
+
+  int nr = GetNextFreeSlot();
+  notify_fail("Am Schluesselbrett ist kein Haken mehr frei.\n");
+  if ( !nr )
+    return 0;
+
+  // Wenn nur ein Schluessel gefunden wurde, wird genauer geschaut, ob
+  // der Spieler gesagt hat, wo der hinsoll.
+  if ( sizeof(obs) == 1 ) {
+    if ( woran != "haken" || !id(woran) )
+      sscanf(woran, "haken %d", nr);
+  }
+
+  notify_fail("Es gibt nur die Haken 1 bis 16.\n");
+  if ( nr < 1 || nr > 16 )
+    return 0;
+
+  notify_fail("Der Haken ist nicht mehr frei.\n");
+  if ( objectp(haken[nr,HOOK_OB]) )
+    return 0;
+
+  // Alle gefundenen Schluesselobjekte ans Brett haengen.
+  foreach( object key : obs ) {
+    switch (key->move(ME, M_PUT)) {
+      // Die Kapazitaet ist ueber P_MAX_OBJECTS begrenzt. Alle
+      // Schleifendurchlaeufe, die die Kapazitaetsgrenze erreichen, landen
+      // in default und beenden damit die Schleife. Daher muessen sie 
+      // nicht gesondert behandelt werden.
+      case MOVE_OK :
+        // Falls das Brett voll sein sollte, aber faelschlicherweise 
+        // dennoch ein weiterer Schluessel hineinbewegt wurde, ist nr==0,
+        // und es wird ein Fehler ausgeloest, damit nicht hinterher ein
+        // Schluessel an Haken 0 haengt.
+        if ( !nr ) {
+          raise_error("Fehler: Haken 0 darf nicht belegt werden.");
+          break;
+        }
+        tell_object(TP, BS("Du haengst "+obs[0]->name(WEN,1)+" an Haken "+
+          nr+"."));
+        // Nur wenn ein Schluessel erfolgreich drangehaengt wurde, wird er
+        // in die Liste eingetragen. Etwaige Beschriftungen bleiben bestehen,
+        haken[nr, HOOK_OB] = key;
+        // und nur dann wird der naechste Slot probiert. Wenn nur ein 
+        // Schluessel verarbeitet wird, ist das hier unschaedlich, weil es 
+        // nicht nochmal ausgewertet wird.
+        nr = GetNextFreeSlot();
+        // Schluessel wurde verarbeitet und Meldung ausgegeben
+        obs -= ({key});
+        break;
+      case ME_CANT_LEAVE_ENV :
+      case ME_CANT_BE_INSERTED :
+      case ME_CANT_BE_DROPPED :
+        // Schluessel wurde nicht erfolgreich drangehaengt.
+        tell_object(TP, BS(key->Name(WER,1)+" weigert sich, ans "
+          "Schluesselbrett gehaengt zu werden."));
+        // Meldung wurde ausgegeben, nichts weiter zu tun.
+        obs -= ({key});
+        break;
+      // TOO_MANY_OBJECTS wird nicht hier behandelt, sondern weiter unten,
+      // um eine Auflistung der Schluesselnamen ausgeben zu koennen, statt
+      // eine Zeile pro Schluessel. Die anderen Rueckgabewerte von move() 
+      // sind bei dieser Art der Bewegung nicht zu erwarten.
+      default: break;
+    }
+  }
+  // Fuer alle uebrigen war wohl TOO_MANY_OBJECTS der Rueckgabewert, denn
+  // das Schluesselbrett erlaubt nur P_MAX_OBJECTS = 16.
+  if ( sizeof(obs) ) {
+    tell_object(TP, BS("Fuer "+CountUp(obs->name(WEN))+" ist leider kein "
+      "Haken mehr am Schluesselbrett frei."));
+  }
+  return 1;
+}
+
+// Schluessel abnehmen
+static int schluessel_von_haken_nehmen(string str) {
+  if( !stringp(str) || !sizeof(str) ) 
+    return 0;
+
+  string was, woraus;
+  if ( sscanf(str, "%s aus %s", was, woraus) != 2 && 
+       sscanf(str, "%s von %s", was, woraus) != 2 )
+    return 0;
+
+  notify_fail("Das darfst Du nicht!\n");
+  if(!erlaubt()) 
+    return 0;
+ 
+  notify_fail("Woraus willst Du das denn nehmen?\n");
+  if ( !id(woraus) && strstr(woraus, "haken", 0) == -1 ) 
+    return 0;
+
+  notify_fail("Was willst Du denn vom Schluesselbrett nehmen?\n");
+  if( !stringp(was) ) 
+    return 0;
+  
+  notify_fail("Das Schluesselbrett ist doch aber leer.\n");
+  if ( !sizeof(all_inventory(ME)) )
+    return 0;
+
+  int hakennr;
+  object *keys = ({});
+  // Es muessen auch Schluessel von bestimmten Haken abgenommen
+  // werden koennen, nicht nur jeweils der erste mit der angegebenen ID.
+  // Dies hat auch Prio gegenueber der allgemeinen Begriffssuche mit
+  // find_obs().
+  if ( sscanf(woraus, "haken %d", hakennr) == 1 ) {
+    notify_fail("Es gibt nur die Haken 1 bis 16.\n");
+    if ( hakennr < 1 || hakennr > 16 ) 
+      return 0;
+    notify_fail("An diesem Haken haengt aber doch kein Schluessel.\n");
+    if ( !objectp(haken[hakennr,HOOK_OB]) )
+      return 0;
+    
+    keys += ({ haken[hakennr,HOOK_OB] });
+  }
+
+  // Keiner gefunden? Vielleicht ist ja einer mit einer bestimmten 
+  // Beschriftung gemeint?
+  if ( !sizeof(keys) ) {
+    // Schluessel mit dem angegebenen Namen suchen
+    keys = TP->find_obs(was+" in brett in raum");
+    // Hakennummer ermitteln, wenn eine Beschriftung angegeben wurde.
+    string wanted_desc;
+    sscanf(was, "schluessel fuer %s", wanted_desc);
+    object wanted_key = GetKeyForLabel(wanted_desc);
+    if ( objectp(wanted_key) )
+      keys += ({wanted_key});
+  }
+  // Immer noch nix gefunden? Dann muss sich der Spieler was anderes 
+  // einfallen lassen.
+  notify_fail("Am Schluesselbrett haengt kein solcher Schluessel.\n");
+  if ( !sizeof(keys) )
+    return 0;
+
+  // Alle gefundenen Schluessel verarbeiten. Alle, die nicht bewegt werden
+  // koennen, verbleiben in der Liste.
+  foreach( object key : keys ) {
+    int current_hook = GetHookNumberForKey(key);
+    if ( key->move(TP,M_GET) == MOVE_OK ) {
+      keys -= ({ key });
+      tell_object(TP, BS("Du nimmst "+key->name(WEN,1)+" von Haken "+
+        current_hook+" ab."));
+      // Schluessel austragen; bestehende Beschriftungen bleiben erhalten
+      haken[current_hook, HOOK_OB] = 0;
+    }
+  }
+  // Von allen nicht vom Haken genommenen Schluesseln die Namen ermitteln
+  // und auflisten.
+  if ( sizeof(keys) ) {
+    tell_object(TP, BS(capitalize(CountUp(keys->name(WER,1)))+" "+
+      (sizeof(keys)==1?"konnte":"konnten")+" nicht vom Schluesselbrett "
+      "abgenommen werden."));
+  }
+  return 1;
+}
+
+// Verfuegbare Kommandos auflisten.
+varargs int skommandos(string str) {
+  notify_fail( "Fehler: Dieser Befehl benoetigt eine gueltige Objekt-Id als "
+    +"Parameter.\nBeispiel: skommandos [schluessel]brett\n");
+  
+  if( !id(str) ) return 0;
+
+  write(
+    "==================================================================="
+    "==========\n"
+    "Aktuelle Version: "+QueryProp("cnt_version_std")+
+      QueryProp("cnt_version_obj")+"\n"+
+    BS(Name(WER,1)+" kann nur in diesem Seherhaus verwendet werden, "
+    "da "+QueryPronoun(WER)+" speziell dafuer gekauft wurde. "+
+    CAP(QueryPronoun(WER))+" verfuegt ueber folgende Kommandos:")+
+    "----------------------------------------------------------------------"
+    "-------\n"
+    "serlaube [schluessel]brett [spielername|\"hausfreunde\"|\"zweities\"]\n"
+    "  Erlaubt Personen, "+name(WEN,1)+" mitzubenutzen.\n"
+    "  serlaube ohne Angabe eines Arguments listet alle Personen mit Zugriff "
+      "auf\n  "+name(WEN,1)+" auf.\n\n"
+    "verschiebe [schluessel]brett nach [ausgang]\n"
+    "  Damit kannst Du "+name(WEN,1)+" innerhalb Deines Seherhauses "
+    "verschieben.\n\n"
+    "sverstecke [schluessel]brett\n"
+    "  Damit machst Du "+name(WEN,1)+" unsichtbar.\n"
+    "shole [schluessel]brett hervor\n"
+    "  Damit machst Du "+name(WEN,1)+" wieder sichtbar.\n"
+    "zertruemmer [schluessel]brett\n"
+    "  Damit zerstoerst Du das Schluesselbrett.\n"
+    "sbeschrifte haken <nr> mit <text>|nichts\n"
+    "  Eine Beschriftung an einem Haken anbringen oder loeschen.\n"
+    "sliste lang|kurz\n"
+    "  Schluesselanzeige konfigurieren: alle oder nur belegte auflisten.\n"
+    "haenge <schluesselname> an haken [nr]\n"
+    "haenge <schluesselname> an [schluessel]brett\n"
+    "  Damit haengst Du einen Schluessel an das Brett.\n"
+    "nimm schluessel von haken <nr>\n"
+    "nimm <schluesselname> von [schluessel]brett\n"
+    "nimm schluessel fuer <beschriftung> von [schluessel]brett.\n"
+    "  Damit nimmst Du einen Schluessel vom Schluesselbrett.\n"
+    "==================================================================="
+    "==========\n");
+  return 1;
+}
+
+static int erlaubnis_liste()
+{
+  if( QueryHausbesitzer() != QueryTP() && !QueryProp("test") )
+  {
+    tell_object(TP, BS("Nur "+QueryHausbesitzer()+" darf Berechtigungen "
+      +name(WESSEN,1)+" abfragen!"));
+    return 1;
+  }
+  
+  string *strs;
+  string str = 
+    "==================================================================="
+    "==========\n";
+  if ( hauserlaubnis ) {
+    strs = SHVERWALTER->HausProp(LOWER(QueryHausbesitzer()), 2);
+    str += "Folgende Freunde Deines Hauses duerfen "+name(WEN,1)+
+      " mitbenutzen:\n";
+    if(sizeof(strs)) {
+      str += BS(CountUp(strs));
+    }
+    else {
+      str += BS("Du hast keiner Person Zugriff auf Dein Haus gewaehrt...");
+    }
+  }
+  else {
+    str+= BS("Die Freunde Deines Hauses duerfen "+name(WEN,1)+
+      " nicht mitbenutzen.");
+  }
+
+  str += 
+    "-------------------------------------------------------------------"
+    "----------\n";
+
+  if( zweitieerlaubnis!="" ) {
+    if( zweitieerlaubnis==geteuid(TP) )
+      str += BS("Alle Deine Zweities duerfen "+name(WEN,1)+" mitbenutzen.");
+    else
+      str += BS("Alle Zweities von "+CAP(zweitieerlaubnis)+" duerfen "
+        +name(WEN,1)+" mitbenutzen.");
+    str +=
+      "-------------------------------------------------------------------"
+      "----------\n";
+  }
+  
+  strs=QueryProp("cnt_erlaubnis");
+
+  if(sizeof(strs)) {
+    str += BS("Folgende sonstige Personen duerfen "+name(WEN,1)+
+      " mitbenutzen:");
+    str += CountUp(strs);
+  }
+  else {
+    str += BS("Es gibt keine sonstigen Personen, die "+name(WEN,1)+
+      " mitbenutzen duerfen.");
+  }
+  str +=
+    "==================================================================="
+    "==========\n";
+  
+  return 1;
+}
+
+// Haken beschriften.
+static int cmd_beschriften(string str) {
+  string nfm = "Syntax: sbeschrifte haken <hakennummer> mit "
+    "<text>|nichts\n"
+    "Fuer <text> kannst Du einen beliebigen Text mit bis zu 30 Zeichen "
+    "angeben,\n"
+    "'nichts' loescht die Beschriftung eines Schildes.\n";
+
+  notify_fail("Das darfst Du nicht!\n");
+  if(!erlaubt()) 
+    return 0;
+  
+  string text;
+  int hnr;
+  str = TP->_unparsed_args(0);
+  notify_fail(nfm);
+  if ( !stringp(str) || !sizeof(str) ) 
+    return 0;
+  if ( sscanf(str,"haken %d mit %s", hnr, text)!=2 )
+    return 0;
+
+  notify_fail("Welchen Haken moechtest Du beschriften?\n"+nfm);
+  if(!hnr) 
+    return 0;
+  
+  notify_fail("Es gibt nur die Haken 1 bis 16.\n");
+  if ( hnr < 1 || hnr > 16 ) 
+    return 0;
+
+  notify_fail("Womit moechtest Du den Haken beschriften?\n"+nfm);
+  if( !stringp(text) || !sizeof(text) )
+    return 0;
+
+  notify_fail("Der Text sollte nicht laenger als 30 Zeichen sein.\n");
+  if(sizeof(text) > 30) 
+    return 0;
+
+  if ( lower_case(text) == "nichts" ) {
+    if ( stringp(haken[hnr,HOOK_LABEL]) ) {
+      tell_object(TP, BS("Sorgfaeltig wischst Du die Beschriftung des "
+        "Hakens "+hnr+" weg."));
+      haken[hnr,HOOK_LABEL]=0;
+    }
+    else {
+      tell_object(TP, BS("Du musst Dich geirrt haben. Haken "+hnr+" ist "
+        "gar nicht beschriftet."));
+    }
+  }
+  else if ( lower_case(text) == "schluessel" ) {
+    tell_object(TP, BS(
+      "Du solltest Dir etwas Aussagekraeftigeres einfallen lassen."));
+  }
+  else {
+    tell_object(TP, BS("Du beschriftest das Schildchen ueber Haken "+hnr+
+      " mit "+text+"."));
+    tell_room(environment(), BS(
+      TP->Name(WER)+" schreibt etwas ans Schluesselbrett."), ({TP}));
+    haken[hnr,HOOK_LABEL] = text;
+  }
+  return 1;
+}
+
+/***** HILFSFUNKTIONEN *****/
+
+// Beschreibung eines Hakens erzeugen. Wenn <keynum> angegeben wird, 
+// wird nur der gesuchte Haken angezeigt, egal ob leer oder nicht. 
+// Ansonsten werden die belegten Haken angezeigt, ausser wenn 
+// <hooklist_long> gesetzt ist. Dann werden alle Haken aufgelistet.
+private varargs string KeyDescription(int keynum) {
+  string desc="";
+  mapping keylist=([:2]);
+
+  // Liste derHaken auf den/die gesuchten einschraenken.
+  // Nur ein Haken soll angeschaut werden. Dies hat immer Prioritaet,
+  // d.h. auch bei <sliste alle> wird nur ein Haken gelistet.
+  if ( keynum ) {
+    m_add(keylist, keynum, m_entry(haken, keynum)...);
+  }
+  // Wenn <sliste alle> gesetzt ist, alle ausgeben.
+  else if ( hooklist_long ) {
+    keylist = haken;
+  }
+  // Ansonster nur die belegten.
+  else {
+    keylist = filter(haken, 
+      function int (int num, <string|object>* values) {
+        return objectp(values[0]);
+      });
+  }
+
+  // Ueber das Mapping mit den selektierten Haken laufen und Ausgaben
+  // erzeugen.
+  foreach(int num : 1..16) {
+    // Hier wird der aktuelle Wert uebersprungen, wenn er nicht enthalten 
+    // ist, da die Zuweisung in <key> und <keydesc> auch dann eine 0 ergeben
+    // wuerde, und somit Keys mit leeren Values nicht von nicht existierenden
+    // Keys zu unterscheiden waeren.
+    if ( member(m_indices(keylist), num) == -1 )
+      continue;
+    string keydesc = keylist[num, HOOK_LABEL];
+    object key = keylist[num, HOOK_OB];
+    desc += "Haken " + num + (stringp(keydesc)?" ["+keydesc+"]: " : ": ");
+    desc += (objectp(key) ? key->short() : "leer\n");
+  }
+  return desc;
+}
+
+// Rueckgabewert: 1, wenn es sich um ein Schluesselobjekt handelt, sonst 0.
+// Schluessel werden anhand der ID "schluessel" erkannt oder daran, dass
+// QueryDoorKey() einen Wert zurueckgibt, d.h. dass dieses Objekt eine
+// Standard-Doormaster-Tuer oeffnet.
+private int IsValidKey(object ob) {
+  return (objectp(ob) && (ob->id("schluessel") || ob->QueryDoorKey()!=0));
+}
+
+// Gibt die Nummer des naechsten freien Hakens zurueck oder 0, wenn
+// keiner frei ist. Da Mappings nicht sortiert sind, muss von 1-16 numerisch
+// iteriert werden, damit immer der erste freie Haken gefunden wird und nicht 
+// irgendeiner.
+// Rueckgabewert: Hakennummer von 1-16 oder 0, wenn kein Haken frei ist.
+private int GetNextFreeSlot() {
+  int slot;
+  foreach(int i : 1..16) {
+    if ( !objectp(haken[i,HOOK_OB]) ) {
+      slot = i;
+      break;
+    }
+  }
+  return slot;
+}
+
+// Gibt zu einer Schild-Beschriftung die zugehoerige Hakenposition aus.
+// Es wird die kleingeschriebene Variante gesucht, so dass Spieler zwar
+// Grossschreibung in den Beschriftungen verwenden koennen, diese aber
+// nicht beruecksichtigt wird. Ansonsten koennte es zu Schwierigkeiten mit
+// Dopplungen wie "Vesray" und "vesray" kommen.
+// Rueckgabewert: Hakennummer von 1-16 oder 0, wenn der Text nicht gefunden
+// wurde.
+private object GetKeyForLabel(string label) {
+  if ( label ) 
+    label = lower_case(label);
+  foreach(int i: 1..16) {
+    if ( haken[i, HOOK_LABEL] && label &&
+         lower_case(haken[i,HOOK_LABEL]) == label )
+      return haken[i,HOOK_OB];
+  }
+  return 0;
+}
+
+// Gibt zu dem uebergebenen Objekt die Nummer des Hakens zurueck, an dem
+// es haengt.
+private int GetHookNumberForKey(object ob) {
+  foreach(int num, object key : haken) {
+    if ( key == ob )
+      return num;
+  }
+  return 0;
+}
+
+// Bereinigt Datenstruktur in <haken> und das Inventar des Brettes, indem
+// a) geprueft wird, ob alle in <haken> eingetragenen Objekte sich auch im 
+//    Brett befinden und
+// b) geprueft wird, ob alle im Inventar befindlichen Objekte auch korrekt in 
+//    <haken> eingetragen sind.
+// Ueberzaehlige Objekte werden rausgeworfen.
+private void ConsolidateInventory() {
+  foreach(int i, object ob : haken) {
+    // Objekt existiert, ist aber nicht im Schluesselbrett? Dann austragen.
+    if (objectp(ob) && environment(ob) != ME) {
+      m_delete(haken, i);
+      // Wird auch vom reset() aus gerufen, dann ist TP == 0.
+      if ( objectp(TP) )
+        tell_object(TP, BS("Hoppla! "+ob->Name(WER,1)+" scheint vom "
+          "Schluesselbrett verschwunden zu sein!"));
+    }
+  }
+  object *resterampe = all_inventory(ME) - m_values(haken, HOOK_OB);
+  if (sizeof(resterampe)) {
+    resterampe->move(environment(),M_PUT);
+    tell_room(environment(), BS("Ploetzlich faellt etwas vom "
+      "Schluesselbrett zu Boden, das Du zuvor gar nicht gesehen hattest."));
+  }
+}
+
+string short() {
+  string sh=QueryProp(P_SHORT);
+
+  // Unsichtbar? Dann gibts nichts zu sehen ...
+  if ( QueryProp(P_INVIS) || !sh )
+    return 0;
+  if ( QueryProp("versteckt") == 1 ) 
+    sh = "";
+  else 
+    sh += ".";
+
+  return process_string(sh)+"\n";
+}
+
+// Im Reset vorsichtshalber auch mal aufraeumen.
+void reset() {
+  ConsolidateInventory();
+  return ::reset();
+}
+
+varargs int PreventInsert(object ob) {
+  // Kein Schluessel? Hat in diesem Container nix verloren!
+  if( !IsValidKey(ob )) {
+    return 1;
+  }
+  ConsolidateInventory();
+  return ::PreventInsert(ob);
+}
+
+// Wenn ein Schluessel sich aufloest, muss die Liste abgeglichen werden.
+void NotifyRemove(object ob) {
+  tell_room(environment(ME), BS("Hoppla! "+ob->Name(WER,1)+" hat sich "
+    "gerade in Wohlgefallen aufgeloest."));
+  // Das Objekt <ob> zerstoert sich erst nach dem Aufruf dieser Funktion,
+  // daher per call_out() aufraeumen.
+  call_out(#'ConsolidateInventory, 1);
+}
+
+// Zesstra, 1.7.07, fuers Hoerrohr
+// Darf ich da Arathorn eintragen? ;-)
+string GetOwner() {
+  return "seleven";
+}
+
diff --git a/d/seher/haeuser/moebel/schraenker_gutschein.c b/d/seher/haeuser/moebel/schraenker_gutschein.c
new file mode 100644
index 0000000..9c89204
--- /dev/null
+++ b/d/seher/haeuser/moebel/schraenker_gutschein.c
@@ -0,0 +1,44 @@
+//--------------------------------------------------------------------------------
+// Name des Objects:    Schraenger-Gutschein
+// Letzte Aenderung:    05.05.2001
+// Magier:              Swift
+//--------------------------------------------------------------------------------
+
+#include "schrankladen.h"
+#include <ansi.h>
+inherit "std/thing";
+
+create()
+{
+  if (!clonep(TO)) return;
+  ::create();
+  SetProp(P_SHORT, "Ein Gutschein");
+  SetProp(P_LONG, "@@longtext@@");
+  AddId(({"gutschein"}));
+  SetProp(P_NAME, "Gutschein");
+  SetProp(P_GENDER, MALE);
+  SetProp(P_WEIGHT, 5);            // Gewicht 5g
+  SetProp(P_VALUE, 0);             // Kein materieller Wert. Ist eh nicht verkaufbar.
+  SetProp(P_NOBUY, 1);             // Wird im Laden zerstoert, falls er verkauft wird.
+  SetProp(P_MATERIAL, ({MAT_PAPER}) );
+  SetProp(P_INFO, "Dieser Gutschein ist nur fuer einen Seher mit Eigenheim von Interesse!\n");
+  SetProp(P_AUTOLOADOBJ, 1);
+}
+
+string longtext()
+{
+  string str,aussteller,inhaber,text;
+  int wert;
+  aussteller="Seleven";
+  inhaber="Filli";
+  wert=5000;
+  text="";
+  str="***********************************************************************\n\n"
+     +"  D E R   S C H R A E N K E R\n\n"
+     +"  E I N K A U F S - G U T S C H E I N    .\n\n"
+     +"  Ausgestellt von "+aussteller+" fuer "+inhaber+".\n\n"
+     +"  Wert: "+to_string(wert)+" Muenzen.\n\n"
+     +text
+     +"***********************************************************************\n";
+  return str;
+}
diff --git a/d/seher/haeuser/moebel/schrankladen.c b/d/seher/haeuser/moebel/schrankladen.c
new file mode 100644
index 0000000..bcaf25c
--- /dev/null
+++ b/d/seher/haeuser/moebel/schrankladen.c
@@ -0,0 +1,436 @@
+//----------------------------------------------------------------------------
+// Name des Objects:    SCHRAENKER
+// Letzte Aenderung:    06.04.2006 P_LOG_FILE (Seleven)
+// Magier:              Swift
+//----------------------------------------------------------------------------
+#pragma strong_types,rtt_checks
+inherit "/std/room";
+
+#include <properties.h>
+#include <language.h>
+#include "schrankladen.h"
+
+
+protected void create()
+{
+  ::create();
+  SetProp(P_LOG_FILE,"seleven/schraenker"); // Seleven 06.04.2006
+  SP(P_INT_SHORT, "Im SCHRAENKER");
+  SP(P_INT_LONG, BS(
+     "Du stehst in einem gemuetlichen kleinen Laden. Ein flauschiger "
+    +"Teppichboden daempft Deine Schritte, und der Geruch verschiedener "
+    +"Hoelzer kitzelt angenehm in der Nase. Irgendwoher erklingt eine "
+    +"leise, beruhigende Melodie. An den Waenden haengen Bilder und "
+    +"Zeichnungen verschiedenster Art, sowie eine grosse Preisliste. "
+    +"Wenn Du nicht den Eindruck haettest, dass man hier an Deine Boerse "
+    +"moechte, koenntest Du Dich hier richtig wohl fuehlen.",78));
+
+  SP(P_LIGHT, 1);
+  SP(P_INDOORS, 1);
+
+  AD( ({"zeit"}), BS(
+     "Die aktuelle Zeit: "+ctime(time()),78));
+  AD( ({"ausgang"}), BS(
+     "Nach Osten geht's raus.",78));
+  AD( ({"ausgaenge"}), BS(
+     "So sehr Du auch suchst, mehr als den einen Ausgang findest Du "
+    +"einfach nicht.",78));
+  AD( ({"geldboerse", "boerse"}), BS(
+     "Man redet halt von Boerse, auch wenn Du keine dabeihast. Es geht "
+    +"halt um Dein Geld!",78));
+  AD( ({"geld"}), BS(
+     "Irgendwo wirst Du schon Kohle haben! :)",78));
+  AD( ({"kohle", "zaster", "moneten", "piepen", "maeuse"}), BS(
+     "Kohle, Zaster, Moneten, Piepen, Maeuse... alles dasselbe! :)",78));
+  AD( ({"boden"}), BS(
+     "Ein flauschiger, aber auch sehr strapazierfaehiger Teppich bedeckt "
+    +"den ganzen Boden des Ladens. Billig sieht er nicht aus.",78));
+  AD( ({"teppich", "teppichboden"}), BS(
+     "Es handelt sich um einen echten Vorberg-Teppich. Er wurde "
+    +"von einem Fachmann verlegt und scheint aus einem einzigen grossen "
+    +"Stueck zu sein.",78));
+  AD( ({"stueck"}), BS(
+     "Der Teppich scheint aus einem einzigen grossen Stueck zu sein. So gut "
+    +"kann das eigentlich nur ein Fachmann.",78));
+  AD( ({"fachmann"}), BS("Es ist keiner zu sehen, aber es ist anzunehmen, dass "
+    +"es sich um einen professionellen Teppichleger handelte."));
+  AD( ({"teppichleger"}), "Wie gesagt, keiner zu sehen. Der Teppich liegt ja "
+    +"schon, und der wird auch noch eine Weile halten.\n");
+  AD( ({"weile"}), "Schon noch ein paar Jaehrchen!\n");
+  AD( ({"jaehrchen"}), "Teppiche der Firma Vorberg koennen lange halten.\n");
+  AD( ({"vorberg", "vorbergteppich", "vorberg-teppich"}), BS(
+     "Die Firma Vorberg stellt, im Gegensatz zur Firma Hinterberg, sehr gute "
+    +"Teppiche her, wie jeder weiss.",78));
+  AD( ({"gegensatz"}), "Das weiss wirklich Jeder!\nDu koenntest Ihn fragen, "
+    +"waere er nicht gebanisht. :)\n");
+  AD( ({"ihn"}), BS("Wen IHN ? Meinst Du Jeder? Der ist doch gebanisht. Aus gutem "
+    +"Grund. Wenn irgendwo was wegkommt, dann koennte das Jeder gewesen sein. "
+    +"Das reicht doch, um ihn zu banishen, oder? :)"));
+  AD( ({"hinterberg", "hinterbergteppich", "hinterberg-teppich"}), BS(
+     "Das hier ist ein Teppich der Firma Vorberg. Niemand mit Geschmack wuerde "
+    +"den billigen Abklatsch der Firma Hinterberg kaufen.",78));
+  AD( ({"jeder"}), BS(
+     "Der ist nicht da. Siehst Du ihn etwa?",78));
+  AD( ({"grund", "gruende"}), BS(
+     "Gruende lassen sich immer finden, sei also vorsichtig! :)",78));
+  AD( ({"geschmack"}), BS(
+     "Ueber den laesst sich bekanntlich streiten.",78));
+  AD( ({"teppiche"}), BS(
+     "Du siehst hier einen. Der aber fuellt den ganzen Raum aus.",78));
+  AD( ({"abklatsch"}), BS(
+     "Vorberg-Teppiche sind halt das einzig Wahre!",78));
+  AD( ({"laden"}), BS(
+     "Der Laden ist bekannt unter dem Namen \"SCHRAENKER\". Aber das weisst "
+    +"Du sicher.",78));
+  AD( ({"namen"}), BS(
+     "Der Namen des Ladens ist \"SCHRAENKER\".",78));
+  AD( ({"schraenker"}), BS(
+     "Ja, schau Dich nur um!",78));
+  AD( ({"melodie"}), BS(
+     "Lausche ihr besser.",78));
+  AD( ({"geruch"}), BS(
+     "Sehen kannst Du den nicht. Vielleicht solltest Du Deine Nase benutzen?",78));
+  AD( ({"schritte"}), BS(
+     "Du gehst testweise ein paar Schritte, der Teppich daempft sie tatsaechlich "
+    +"so gut, dass Du nicht das geringste hoeren kannst.",78));
+  AD( ({"schritt"}), BS(
+     "Mach das doch irgendwo, wo es keiner sieht!",78));
+  AD( ({"nase"}), BS(
+     "Du fasst Dir an die Nase. Ein Glueck, sie ist noch da!",78));
+  AD( ({"glueck"}), BS(
+     "Ohne Nase koenntest Du hier gar nichts riechen, stell Dir das nur "
+    +"mal vor!",78));
+  AD( ({"raum", "ort"}), BS(
+     "Du stehst in einem noblen Laden. Mach einfach \"schau\".",78));
+  AD( ({"firma"}), BS(
+     "Du stehst hier in einem Laden. Natuerlich ist das eine Firma, und der "
+    +"Ladeninhaber ist ebenso natuerlich der Firmenbesitzer. Hattest Du denn "
+    +"etwas anderes erwartet?",78));
+  AD( ({"eindruck"}), BS(
+     "Es ist ein Laden. Er sieht nobel aus, Preise wie bei ALDI wird's hier also "
+    +"wohl nicht geben. Und ausserdem ist der erste Eindruck meist der richtige.",78));
+  AD( ({"aldi"}), BS(
+     "NEIN, Du bist hier NICHT bei ALDI !!!",78));
+  AD( ({"preis", "preise", "liste", "preisliste"}), BS(
+     "An der Wand haengt eine grosse Preisliste. Vielleicht solltest Du sie "
+    +"lesen?",78));
+  AD( ({"inhaber", "ladeninhaber", "besitzer", "firmenbesitzer", "verkaeufer"}), BS(
+     "Ist der denn gerade nicht da? Das ist sehr verwunderlich, echt ehrlich.",78));
+  AD( ({"elf", "elfen", "person"}), BS(
+     "Schau Dir halt das Portrait an!",78));
+  AD( ({"darstellung", "darstellungen"}), BS(
+     "Die Bilder zeigen Moebelstuecke, hauptsaechlich Schraenke.",78));
+  AD( ({"reihe"}), BS(
+     "Bei den meisten Bildern handelt es sich um Darstellung von Moebelstuecken. "
+    +"Nur ein einziges Portrait ist dabei, das eine Person zeigt.",78));
+  AD( ({"art"}), BS(
+     "Bei den meisten Bildern handelt es sich um Darstellungen von Moebelstuecken, "
+    +"zumeist von Schraenken. Ein Portrait faellt Dir allerdings auf, das nicht in "
+    +"die Reihe der anderen Bilder passt.",78));
+  AD( ({"bilder"}), BS(
+     "Es gibt mehrere Darstellungen von verschiedenen Moebelstuecken. Zumeist "
+    +"handelt es sich dabei um Schraenke verschiedener Bauweise. Ausserdem ist "
+    +"da noch ein Portrait.",78));
+  AD( ({"bauart", "bauweise", "moebelstueck", "moebelstuecke", "arten"}), BS(
+     "Es gibt Waffenschraenke, Kleiderschraenke, Kuehlschraenke (JA!), Kommoden, "
+    +"sonstige Schraenke (Du kannst ihren Zweck nicht mal erahnen) und einige "
+    +"Truhen, die zwar keine Schraenke im eigentlichen Sinne sind, aber Zeug "
+    +"bringt man darin mit Sicherheit auch unter. Sogar eine Vitrine siehst "
+    +"Du.",78));
+  AD( ({"zweck"}), BS(
+     "Stauraum fuer irgendwelches Zeugs. Das muss es sein. Was fuer einen "
+    +"Zweck koennte es sonst noch geben?",78));
+  AD( ({"vitrine"}), BS("Die Vitrine ist leer, aber das aendert sich sicher, "
+    +"sobald Du eine gekauft hast.",78));
+  AD( ({"kleiderschrank", "kleiderschraenke"}), BS(
+     "Sicher eignet sich solch ein Schrank sehr gut, um darin Ruestungen "
+    +"aufzubewahren.",78));
+  AD( ({"waffenschrank", "waffenschraenke"}), BS(
+     "In einem Waffenschrank kannst Du eine Menge verschiedener Waffen "
+    +"unterbringen, und der Vorteil dabei ist, dass sie dann auch sauber "
+    +"sortiert im Schrank haengen.",78));
+  AD( ({"kommoden"}), BS(
+     "Die kann man nicht nur in einen Flur stellen, sondern auch in jeden "
+    +"anderen Raum!",78));
+  AD( ({"flur"}), BS(
+     "Die meisten Haeuser haben einen.",78));
+  AD( ({"haeuser"}), BS(
+     "HIER ???",78));
+  AD( ({"menge"}), BS(
+     "Mehr als Du brauchst, es sei denn Du bist Sammler.",78));
+  AD( ({"zeugs", "dinge"}), BS(
+     "Dinge halt.",78));
+  AD( ({"waffen"}), BS(
+     "Du kannst sie in einem Waffenschrank unterbringen, wenn Du einen "
+    +"besitzt. Wenn nicht kannst Du ja einen kaufen.",78));
+  AD( ({"waffe"}), BS(
+     "Welche Waffe meinst Du?",78));
+  AD( ({"ruestungen"}), BS(
+     "Du kannst sie in einem Kleiderschrank unterbringen, wenn Du einen "
+    +"besitzt. Wenn nicht koenntest Du Dir einen zulegen.",78));
+  AD( ({"ruestung"}), BS(
+     "Von welcher Ruestung redest Du?",78));
+  AD( ({"vorteil"}), BS(
+     "Jeder ist doch auf seinen persoenlichen Vorteil bedacht.",78));
+  AD( ({"kuehlschrank", "kuehlschraenke"}), BS(
+     "In so einem Kuehlschrank kann man eigentlich alles reinstecken, aber "
+    +"natuerlich bietet er sich besonders fuer Getraenke und Speisen aller "
+    +"Art an. Wie z.B. Schnellhaerter, Broetchen usw.",78));
+  AD( ({"getraenke", "speisen"}), BS(
+     "Das hier ist keine Kneipe. Sowas gibt's hier nicht!",78));
+  AD( ({"kneipe"}), BS(
+     "Das hier ist KEINE Kneipe !!!",78));
+  AD( ({"truhe", "truhen"}), BS(
+     "Es gibt grosse und kleine, aus verschiedenem Material.",78));
+  AD( ({"material"}), BS(
+     "Total verschieden, wirklich.",78));
+  AD( ({"schnellhaerter", "broetchen"}), BS(
+     "Besorg Dir welche, bevor Du sie untersuchen willst!",78));
+  AD( ({"sammler"}), BS(
+     "Bist Du einer?",78));
+  AD( ({"sicherheit"}), BS(
+     "Jo, in so eine Truhe passt viel Zeug rein.",78));
+  AD( ({"zeug"}), BS(
+     "Alles, was Du so mit Dir rumschleppst. Das meiste davon brauchst "
+    +"Du sowieso nie.",78));
+  AD( ({"bild"}), BS(
+     "Es gibt mehrere Darstellungen von verschiedenen Moebelstuecken und ein "
+    +"Portrait. Welches Bild meinst Du?",78));
+  AD( ({"portrait"}), BS(
+     "Es zeigt einen Elf mit strahlend blauen Augen und den typisch spitzen "
+    +"Elfenohren, die frech aus einer beeindruckenden, silbergrauen Loewenmaehne "
+    +"hervorschauen. Der Spitzhut, der ihm auf dem Kopf sitzt, laesst darauf "
+    +"schliessen, dass es sich um einen Zauberer handelt. Unten in der rechten "
+    +"Bildecke ist eine Widmung angebracht.",78));
+  AD( ({"sinn", "sinne"}), BS(
+     "Schraenke und Truhen sehen schon etwas veschieden aus.",78));
+  AD( ({"swift"}), BS(
+     "Siehst Du ihn hier etwa gerade?",78));
+  AD( ({"bildecke"}), BS(
+     "Unten in der rechten Bildecke ist eine Widmung angebracht.",78));
+  AD( ({"augen"}), BS(
+     "Der Elf auf dem Portrait hat strahlend blaue Augen.",78));
+  AD( ({"widmung"}), BS(
+     "Sieht aus als ob man die sogar lesen kann!",78));
+  AD( ({"maehne", "loewenmaehne"}), BS(
+     "Der Elf auf dem Bild hat eine silbergraue Loewenmaehne.",78));
+  AD( ({"zauberer", "zauberhut", "zaubererhut", "spitzhut"}), BS(
+     "Der Zauberhut macht den Elfen auf dem Portrait erst zu einem waschechten "
+    +"Zauberer.",78));
+  AD( ({"ohren", "elfenohren"}), BS(
+     "Die Ohren des Elfen auf dem Portrait sind so spitz, wie man das von "
+    +"einem Elfen erwartet.",78));
+  ARD( ({"widmung"}),
+     "Dank an Geordi fuer diese grossartige Geschaeftsidee.\n"
+    +"Moegen Dir Deine Zauber gelingen und die Spellpunkte niemals ausgehen.\n"
+    +"(Darunter hat jemand unterschrieben, aber das Gekrakel kannst Du nicht "
+    +"identifizieren)\n");
+  AD( ({"unterschrift"}), BS(
+     "Meinst Du das Gekrakel?",78));
+  AD( ({"rotfaerbung", "farbe"}), BS(
+     "Das Holz hat eine leicht roetliche Farbe.",78));
+  AD( ({"ruhe"}), BS(
+     "Aaaahhhhh. Ruhe tut gut. Und dank der leisen Melodie entspannst Du "
+    +"Dich allmaehlich.",78));
+  AD( ({"chaosdaemon"}), BS(
+     "Keiner da. Weder Swift noch ein anderer. Glueck fuer Dich!",78));
+  AD( ({"sachen"}), BS(
+     "Was auch immer.",78));
+  AD( ({"klaue"}), BS(
+     "Wahrscheinlich kann Swift damit andere Sachen besser erledigen als "
+    +"schreiben. Schliesslich ist er ein Chaosdaemon.",78));
+  AD( ({"gekrakel"}), BS(
+     "Du nimmst Dir Zeit und schaust die Unterschrift doch nochmal in aller "
+    +"Ruhe an. Endlich kommt Dir die Erleuchtung. Das soll \"Swift\" heissen. "
+    +"Mann, hat der ne Klaue! (Naja, bei einem Chaosdaemonen wundert das "
+    +"eigentlich nicht)",78));
+  AD( ({"erleuchtung"}), BS(
+     "Sie fand in Deinem Kopf statt. Den muesstet Du schon oeffnen, wenn Du "
+    +"die Erleuchtung physisch untersuchen moechtest. Und das kann sich "
+    +"negativ auf Deine Gesundheit auswirken. Lass es lieber!",78));
+  AD( ({"gesundheit"}), BS(
+     "Mit Kopf bist Du gesund. Das ist gewiss.",78));
+  AD( ({"wand", "waende"}), BS(
+     "Die Waende bestehen aus einem feinen, exotischen Holz mit leichter "
+    +"Rotfaerbung. Sieht sehr edel aus. Mehrere Bilder wurden an den Waenden "
+    +"aufgehaengt und verteilen sich gleichmaessig ueber den Raum.",78));
+  AD( ({"kopf"}), BS(
+     "Ein Glueck, er ist noch dran. Genauso wie bei dem Elfen auf dem "
+    +"Portrait!",78));
+  AD( ({"schrank", "schraenke"}), BS(
+     "Es gibt verschiedene Arten von Schraenken.",78));
+  AD( ({"zeichnung"}), BS(
+     "Es gibt mehrere davon.",78));
+  AD( ({"zeichnungen"}), BS(
+     "Sie zeigen - teilweise skizzenhaft - den Aufbau verschiedener "
+    +"Moebelstuecke - vorzugsweise Schraenke.",78));
+  AD( ({"aufbau", "zusammensetzung"}), BS(
+     "Mit dem Aufbau ist die Zusammensetzung gemeint - und umgekehrt.",78));
+  AD( ({"holz", "hoelzer"}), BS(
+     "Schon hier im Raum wurde mit verschiedensten Hoelzern gearbeitet, "
+    +"ihr edler Duft vermischt sich und bietet einen erhebenden Geruch. "
+    +"Leider sind die meisten Holzarten so exotisch, dass Du beim besten "
+    +"Willen nicht sagen kannst, um was fuer einen Baum es sich da mal "
+    +"gehandelt hat.",78));
+  AD( ({"holzart", "holzarten"}), BS(
+     "Sehr exotische Holzarten. Du bist kein Experte fuer sowas, und "
+    +"vermutlich hast Du auch keine Lust, einer zu werden.",78));
+  AD( ({"experte"}), BS(
+     "Keiner da.",78));
+  AD( ({"lust"}), BS(
+     "Wenn jemand seine Lust untersucht/ueberprueft, bekundet er damit "
+    +"eigentlich schon in Wirklichkeit seine Unlust.",78));
+  AD( ({"unlust"}), BS(
+     "Tja, Unlust kennzeichnet den Faulpelz.",78));
+  AD( ({"faulpelz"}), BS(
+     "Du bist gemeint!",78));
+  AD( ({"wirklichkeit", "realitaet"}), BS(
+     "Die Wirklichkeit ist die Realitaet - und andersrum. Meistens "
+    +"jedenfalls.",78));
+  AD( ({"meistens"}), BS(
+     "Hier schon.",78));
+  AD( ({"hier"}), BS(
+     "Hier halt!",78));
+  AD( ({"baum", "baeume"}), BS(
+     "Hier gibt es keine Baeume. Die wurden bereits alle verarbeitet.",78));
+  AD( ({"duft"}), BS(
+     "Rieche halt mal!",78));
+  AD( ({"wille", "willen"}), BS(
+     "Dein Wille ist stark...",78));
+  AD( ({"decke"}), BS(
+     "Maechtige Balken bilden die Decke. Es koennte sich um Eiche handeln, aber "
+    +"genausogut koennte es irgendeine aehnliche, exotische Holzart sein. "
+    +"Ein herrlicher Kronleuchter haengt von der Mitte herab.",78));
+  AD( ({"eiche", "eichenbalken"}), BS(
+     "Es ist nicht sicher, dass es sich um Eichenbalken handelt, aber Balken "
+    +"sind's auf jeden Fall.",78));
+  AD( ({"fall"}), BS(
+     "Echt ehrlich.",78));
+  AD( ({"balken"}), BS(
+     "Sie bilden die Decke. Ein herrlich anzusehender Kronleuchter haengt "
+    +"daran herab.",78));
+  AD( ({"kronleuchter"}), BS(
+     "Er haengt von der Decke herab und muss ein Vermoegen wert sein. Reines "
+    +"Bergkristall mit einer Unzahl von Kerzen. Was das fuer ein Aufwand sein "
+    +"muss, die immer am Brennen zu halten.",78));
+  AD( ({"vermoegen"}), BS(
+     "Mehr als Du tragen kannst.",78));
+  AD( ({"bergkristall"}), BS(
+     "Nur Bergkristall hat diesen Glanz.",78));
+  AD( ({"brennen"}), BS(
+     "Die Kerzen flackern munter vor sich hin.",78));
+  AD( ({"unzahl"}), BS(
+     "1, 2, ...viele!",78));
+  AD( ({"glanz"}), BS(
+     "Herrlich!",78));
+  AD( ({"mitte"}), BS(
+     "Von der Mitte der Decke haengt ein Kronleuchter herab.",78));
+  AD( ({"kerzen"}), BS(
+     "Dir faellt auf, dass die Kerzen sich gar nicht verbrauchen. Es muss "
+    +"sich um magische Kerzen handeln.",78));
+  AD( ({"aufwand"}), BS(
+     "Entsetzt denkst Du . o O (Das schlaegt sich bestimmt auf den Preis nieder.)",78));
+  AD( ({"ecken"}), BS(
+     "In den Ecken entdeckst Du kleine, edle Lautsprecher, aus denen die "
+    +"Melodie zu kommen scheint.",78));
+  AD( ({"lautsprecher"}), BS(
+     "Du wusstest gar nicht, dass sowas im MorgenGrauen schon erfunden wurde.",78));
+  AD( ({"morgengrauen"}), BS(
+     "Tust Du das nicht schon die ganze Zeit?",78));
+
+  AddSmells(SENSE_DEFAULT, "Es riecht hier angenehm nach verschiedenen "
+                          +"Hoelzern.\n");
+  AddSmells(({"hoelzer", "holz", "holzarten"}), BS("Du kannst nicht sagen, "
+    +"um was fuer Holzarten es sich handelt, aber der Geruch laesst auf viele "
+    +"verschiedene schliessen. Eine Trennung des Geruchs ist Dir nicht moeglich.") );
+  AddSmells(({"geruch", "gerueche"}), BS("Es riecht nach verschiedenen "
+    +"Holzarten.") );
+
+  AddSounds(SENSE_DEFAULT, "Ganz leise hoerst Du eine angenehme, beruhigende "
+                          +"Melodie.\n");
+  AddSounds(({"melodie"}), "Sie scheint von allen Ecken des Ladens zu kommen.\n");
+
+  AddItem( LADEN("verkaeufer"), REFRESH_DESTRUCT);
+
+  AddCmd(({"oeffne"}), "kopf_oeffnen");
+  AddCmd(({"lies", "les", "lese"}), "preisliste_lesen");
+  AddCmd(({"idee"}), "idee_loggen");
+  AddCmd(({"trenn", "trenne"}), "gerueche_trennen");
+  AddCmd(({"werd", "werde"}), "experte_werden");
+  AddCmd(({"zaehl", "zaehle"}), "kerzen_zaehlen");
+
+  AddSpecialExit("osten", "rausgehen");
+}
+
+int kerzen_zaehlen(string str)
+{
+  notify_fail("Was moechtest Du zaehlen?\n");
+  if(!str) return 0;
+  if(str!="kerzen") return 0;
+  write("1..2..viele.\n");
+  return 1;
+}
+
+int rausgehen(string dir)
+{
+  return TP->move(RAUM_VOR_LADEN, M_GO, 0,
+    "verlaesst den Laden", "kommt aus dem Laden");
+}
+
+varargs string GetExits( object viewer )
+{
+  return "Der Ausgang befindet sich im Osten.\n";
+}
+
+int kopf_oeffnen(string str)
+{
+  notify_fail("Was moechtest Du oeffnen?\n");
+  if(!str) return 0;
+  if(str!="kopf" && str!="meinen kopf" && str!="deinen kopf")
+    return 0;
+  write( BS("Neugierig, wie Du bist, greifst Du Dir an den Kopf. Da faellt Dir "
+    +"ein, dass das oeffnen Deines Kopfes evtl. eine Copyright-Verletzung "
+    +"darstellen koennte, Du heisst ja schliesslich nicht Hannibal. Also laesst "
+    +"Du es dann doch bleiben."));
+  return 1;
+}
+
+int preisliste_lesen(string str)
+{
+  notify_fail("Was moechtest Du lesen?\n");
+  if(!str) return 0;
+  if(str!="preisliste" && str!="liste")
+    return 0;
+  TP->More( read_file(LADEN("preisliste.txt")) );
+  return 1;
+}
+
+int idee_loggen(string str)
+{
+  string txt;
+  str=TP->_unparsed_args();
+  txt=BS(str, 78, CAP(geteuid(TP))+"............."[0..12], BS_INDENT_ONCE);
+  write_file( LADEN(IDEEN_LOG), txt+"\n");
+  write("Vielen Dank fuer Deine Idee!\n");
+  return 1;
+}
+
+int gerueche_trennen(string str)
+{
+  notify_fail("Was willst Du trennen?\n");
+  if(!str) return 0;
+  if(str!="geruch" && str!="gerueche")
+    return 0;
+  write("Du versuchst es, aber Du schaffst es einfach nicht.\n");
+  return 1;
+}
+
+int experte_werden(string str)
+{
+  notify_fail("Was willst Du werden?\n");
+  if(!str) return 0;
+  if(str!="experte" && str!="fachmann")
+    return 0;
+  write("Tja, so einfach geht das nicht, aber das haettest Du Dir denken koennen.\n");
+  return 1;
+}
diff --git a/d/seher/haeuser/moebel/schrankladen.h b/d/seher/haeuser/moebel/schrankladen.h
new file mode 100644
index 0000000..1fc76a9
--- /dev/null
+++ b/d/seher/haeuser/moebel/schrankladen.h
@@ -0,0 +1,36 @@
+#include "moebel.h"
+
+#define SCHRANKMASTER2 "/players/swift/workroom"
+
+#include <language.h>
+#include <defines.h>
+#include <combat.h>
+#include <properties.h>
+#include <wizlevels.h>
+#include <moving.h>
+#include <rooms.h>
+
+#define BS   break_string
+#define ENV(x)  environment(x)
+#define ETO environment(this_object())
+#define ETP environment(this_player())
+#define TP   this_player()
+#define TO   this_object()
+
+#define SP SetProp
+#define QP QueryProp
+#define AD AddDetail
+#define ARD AddReadDetail
+
+#define SUID seteuid(getuid(this_object()))
+
+//#define CAP(x) capitalize(x)
+#define LOWER(x) lower_case(x)
+
+#define CLONEME(x) clone_object(x)->move(ME)
+#define CLONEOB(x) clone_object(x)
+#define CLONE(x,y) clone_object(x)->move(y)
+#define IST_ZAHL(x) (string)to_int(x)==x
+
+#define RIGHT(x,y) (y>sizeof(x)?x:extract(x,sizeof(x)-y,sizeof(x)-1))
+#define LEFT(x,y) (y>sizeof(x)?x:extract(x,0,y-1))
diff --git a/d/seher/haeuser/moebel/schrankmaster.c b/d/seher/haeuser/moebel/schrankmaster.c
new file mode 100644
index 0000000..c602ddc
--- /dev/null
+++ b/d/seher/haeuser/moebel/schrankmaster.c
@@ -0,0 +1,233 @@
+//--------------------------------------------------------------------------------
+// Name des Objects:    Schrankmaster
+// Letzte Aenderung:    19.03.2001
+// Magier:              wurzel
+//--------------------------------------------------------------------------------
+/* Changelog:
+   * 21.06.2007, Zesstra
+           call_out ohne Verzoegerung beim Updaten durch eines mit 2s Verzoegerung ersetzt.
+*/
+#pragma strong_types,rtt_checks
+
+inherit "/std/room";
+
+#include <properties.h>
+#include <language.h>
+#include "schrankladen.h"
+
+mapping schraenke;
+string *cnts;
+int update_laeuft;
+int reset_laeuft;
+
+protected void create() 
+{
+  ::create();
+  SP(P_INT_SHORT, "Irgendwo und Nirgends");
+  SP(P_INT_LONG,
+     "Dies ist der Master-Raum fuer den SCHRAENKER.\n"
+    +"Hier merkt sich August die Anzahl der verkauften Container.\n"
+    +"Davon sind momentan @@ANZAHL@@ registrierte im Umlauf!\n"
+    +"Folgende Befehle sind verfuegbar:\n"
+    +"  schrankliste.........Listet registrierte, im Spiel befindliche Container.\n"
+    +"  schrankupdate........Fuehrt ein Update aller registrierten Container durch.\n");
+
+  SP(P_LIGHT, 1);
+  SP(P_INDOORS, 1);
+  if( SCHRANKMASTER2->QueryProp("schraenke") )  // Der Sicherungsraum hat Daten?
+    schraenke=SCHRANKMASTER2->QueryProp("schraenke");  // Daten holen...
+  else
+    schraenke=([]);
+  SetProp("schraenke", schraenke );
+
+  update_laeuft=0;
+
+  // unnoetig, SCHRANKMASTER2 ist jetzt schon geladen, s.o.
+  //load_object(SCHRANKMASTER2);
+  set_next_reset(3600); // Reset 1 x pro Std.
+
+  AddCmd(({"schrankliste"}), "Schrankliste");
+  AddCmd(({"schrankupdate"}), "SchrankUpdate");
+}
+
+public int clean_up(int ref) {return 0;}   // verhindert Ausswappen des Raumes
+
+public varargs string GetExits( object viewer ) 
+{
+  return "";
+}
+
+string ANZAHL()
+{
+  return to_string( sizeof(schraenke) );
+}
+
+
+// cnt = Object des Containers
+// ver = Version des Containers (VERSION_STD+VERSION_OBJ von std.cont. + objekt...)
+// seher=Der Besitzer/Kaeufer
+// standort=Raum in dem der Container steht
+void RegisterCnt(mixed cnt, mixed ver, mixed seher, mixed standort)
+{
+  if (objectp(standort)) standort=object_name(standort);
+  if( !objectp(cnt) || !stringp(ver) || !stringp(seher) || !stringp(standort) )
+  {
+    log_file("swift/schraenker/bugs.log", "schrankmaster (RegisterCnt) *"
+      +to_string(cnt)+"*"+to_string(ver)+"*"+to_string(seher)+"*"
+      +to_string(standort)+"*\n");
+    return;
+  }
+  m_delete(schraenke,object_name(cnt));
+  schraenke+=([object_name(cnt): ver; seher; to_string(standort)]);
+  SetProp("schraenke", schraenke );
+  SCHRANKMASTER2->SetProp("schraenke", schraenke );
+}
+
+void RemoveCnt(mixed cnt, mixed seher)
+{
+  if( !objectp(cnt) || !stringp(seher) )
+  {
+    log_file("swift/schraenker/bugs.log", "schrankmaster (RemoveCnt) *"
+      +to_string(cnt)+"*"+to_string(seher)+"*\n");
+    return;
+  }
+  schraenke-=([object_name(cnt)]);
+  SetProp("schraenke", schraenke );
+  SCHRANKMASTER2->SetProp("schraenke", schraenke );
+}
+
+string fn(string was)
+{
+  string str,*strs;
+  strs=old_explode( was, "/" );
+  str=strs[sizeof(strs)-1];
+  strs=old_explode( str, "#" );
+  str=strs[0];
+  return str;
+}
+
+int Schrankliste()
+{
+  int i;
+  string str, *strs;
+  object cnt;
+  if(update_laeuft && !reset_laeuft) // Nicht waehrend eines Updates der Schraenke!
+  {
+    write("Update wird durchgefuehrt. Bitte bis zum Ende warten!\n");
+    return 1;
+  }
+  str="----------------------------------------------------------------------\n";
+  strs=m_indices(schraenke);
+  for(i=0;i<sizeof(strs);i++)
+  {
+    if( cnt=find_object(strs[i]) )
+    {
+      str+=(fn(object_name(cnt))+"....................")[0..20]+" ";
+      str+=schraenke[strs[i], 0]+" ";
+      str+=(schraenke[strs[i], 1]+"....................")[0..20]+" ";
+      str+=fn(schraenke[strs[i], 2])+"\n";
+    }
+    else
+    {
+      str+="Nicht auffindbaren Container aus Liste geloescht!\n";
+      schraenke-=([strs[i]]);
+      SetProp("schraenke", schraenke );
+      SCHRANKMASTER2->SetProp("schraenke", schraenke );
+    }
+  }
+  str+="----------------------------------------------------------------------\n";
+  if( TP && present(TP) ) //wurzel 19.03.01 
+    TP->More(str);
+  return 1;
+}
+
+void Update_naechster_Schrank()
+{
+  int i;
+  object cnt, cnt_neu, *inv;
+  if( sizeof(cnts) )    // Es gibt noch Schraenke zum abarbeiten...
+  {
+    cnt=find_object(cnts[0]); // Schrank auswaehlen + Objekt suchen
+    if(cnt)
+    {
+      // Autoloadertruhe ist etwas spezieller zu updaten... Daher alternativer
+      // Mechanismus: UpdateMe() im Moebelstueck aufrufen. Wenn die Funktion
+      // etwas != 0 liefert, wird angenommen, dass diese Funktion das Update
+      // gemacht hat oder sich in Kuerze darum kuemmert. Sonst wird das alte
+      // Update gemacht.
+      // Das neue Moebelobjekt ist dafuer verantwortlich, sich beim
+      // Schrankmaster zu (de-)registrieren!
+      object oldenv=environment(cnt);
+      if (cnt->UpdateMe())
+      {
+          tell_room(TO, "...Update "+CAP(fn(cnts[0]))
+              +" in " + object_name(oldenv) + "\n" );
+      }
+      else
+      {
+          tell_room(TO, CAP(fn(cnts[0]))
+              +" in " + object_name(oldenv) 
+              + " hat kein UpdateMe()!\n" );
+      }
+    }
+    else
+    {
+      tell_room(TO, "Nicht auffindbaren Container aus Liste geloescht!\n");
+      schraenke-=([cnts[0]]);
+    }
+    cnts-=({cnts[0]});   // Schrank aus Liste nehmen
+    call_out("Update_naechster_Schrank", 2);  // Nur 1 Schrank-Update pro heart_beat!
+  }
+  else  // Alle Schraenke abgearbeitet:
+  {
+    tell_room(TO, "*** Update abgeschlossen.\n");
+    SetProp("schraenke", schraenke );
+    SCHRANKMASTER2->SetProp("schraenke", schraenke );
+    update_laeuft=0;
+  }
+}
+
+int SchrankUpdate()
+{
+  if(update_laeuft)   // Nicht waehrend eines Updates der Schraenke!
+  {
+    write("Update wird durchgefuehrt. Bitte bis zum Ende warten!\n");
+    return 1;
+  }
+  update_laeuft=1;    // Ab sofort laeuft Update!
+  cnts=m_indices(schraenke);
+  tell_room(TO, "*** Update wird gestartet...\n");
+  Update_naechster_Schrank();
+  return 1;
+}
+
+
+void reset()
+{
+  reset_laeuft=1;
+  set_next_reset(3600); // Reset 1 x pro Std.
+  ::reset();
+  // Wirft Schraenke aus der Liste, die aus welchem Grund auch immer nicht mehr existieren
+  Schrankliste();
+  if( !(schraenke==QueryProp("schraenke")==SCHRANKMASTER2->QueryProp("schraenke")) )
+    log_file("swift/schraenker/reset.log", "schrankmaster (reset) "
+      +sizeof(schraenke)+" "
+      +sizeof(QueryProp("schraenke"))+" "
+      +sizeof(SCHRANKMASTER2->QueryProp("schraenke"))+"\n");
+  if( present("Interactive") )
+    tell_room(TO, "*** RESET ***\n");
+  reset_laeuft=0;
+}
+
+/*
+// Veraltete Funktionen, um Fehler abzufangen. Kann nach dem naechsten Reboot
+// geloescht werden !!!
+void AddCnt(mixed cnt, mixed ver, mixed seher, mixed standort)
+{
+  log_file("swift/schraenker/verloren.log", to_string(cnt)+"\n");
+}
+void EditCnt(mixed cnt, mixed ver, mixed seher, mixed standort)
+{
+  log_file("swift/schraenker/verloren.log", to_string(cnt)+"\n");
+}
+*/
diff --git a/d/seher/haeuser/moebel/spind.c b/d/seher/haeuser/moebel/spind.c
new file mode 100644
index 0000000..7473b10
--- /dev/null
+++ b/d/seher/haeuser/moebel/spind.c
@@ -0,0 +1,208 @@
+//--------------------------------------------------------------------------------
+// Name des Objects:    Spind
+// Letzte Aenderung:    17.03.2001
+// Magier:              Swift
+//--------------------------------------------------------------------------------
+#pragma strong_types,rtt_checks
+
+#include "schrankladen.h"
+#include "ansi.h"
+inherit LADEN("swift_std_container");
+
+#define VERSION_OBJ "3"
+
+string strall;
+
+protected void create()
+{
+  if (!clonep(TO)) return;
+  swift_std_container::create();
+  SetProp(P_SHORT, "Ein Spind");
+  SetProp(P_LONG, BS(
+     "Dieser Stahlschrank ist vor allem fuer spartanische Raeume gedacht. Ebenso "
+    +"wie sein Gegenstueck, der Kleiderschrank, verfuegt er ueber eine Menge "
+    +"Regale, in denen er riesige Ausruestungsmengen aufnehmen kann.")
+    +"@@cnt_status@@");
+  AddId(({"spind", "schrank", "stahlschrank"}));
+  SetProp("cnt_version_obj", VERSION_OBJ);
+  SetProp(P_NAME, "Spind");
+  SetProp(P_GENDER, MALE);
+  SetProp(P_WEIGHT, 5000);         // Gewicht 5 Kg
+  SetProp(P_MAX_WEIGHT, 1000000);  // Es passen fuer 1000 kg Sachen rein.
+  SetProp(P_WEIGHT_PERCENT, 100);  // Dafuer macht er auch nix leichter :)
+  SetProp(P_MAX_OBJECTS, 100);     // Mehr sollte nicht sein, lt. Tiamak.
+  SetProp(P_VALUE, 0);             // Kein materieller Wert. Ist eh nicht verkaufbar.
+  SetProp(P_NOBUY, 1);             // Wird im Laden zerstoert, falls er verkauft wird.
+  SetProp(P_NOGET, "Das geht nicht. "+Name(WER,1)+" haftet wie magisch am Boden.\n");
+  SetProp(P_MATERIAL, ({MAT_MISC_METAL, MAT_MISC_MAGIC}) );
+  SetProp(P_INFO, "Versuchs mal mit: \"skommandos "+QueryProp(P_IDS)[1]+"\" !\n");
+  SetProp("obj_cmd", "sliste [Objekt-Id] [Kleidungs-/Ruestungstyp]\n"
+                    +"  Kleidungs-/Ruestungstypen: Helme, Umhaenge, Ruestungen, Hosen, Schuhe,\n"
+                    +"                             Handschuhe, Guertel, Amulette, Ringe, Koecher,\n"
+                    +"                             Schilde, Sonstiges\n");
+  AD(({"regal", "regale"}), BS("Durch die Regale kommt etwas Ordnung in die "
+    +"vielen Sachen, die man in den Schrank stecken kann. Du kannst Dir z.B. "
+    +"eine Liste bestimmter Kleidungs-/Ruestungstypen des Schrankinhaltes "
+    +"mit dem Befehl \"sliste\" anschauen. (Das geht natuerlich nur bei "
+    +"offenem Schrank!"));
+
+  AddCmd(({"sliste"}), "auflistung");
+}
+
+varargs int PreventInsert(object ob)
+{
+  // Nur Ruestung/Kleidung hat in diesem Container was verloren!
+  if ((ob->IsClothing() || ob->QueryProp(P_ARMOUR_TYPE))
+      && !ob->QueryProp(P_WEAPON_TYPE) )
+  {
+    return ::PreventInsert(ob);
+  }
+
+  write( BS("In "+name(WEN,1)+" kannst Du nur Ruestungs-/Kleidungsstuecke legen!"));
+  return 1;
+}
+
+int auflistung2(string was, string nf_str1, string nf_str2, int alles)
+{
+  string obshort, suche, *strs;
+  object *obs;
+  int i;
+  mapping suchobs;
+  switch(was)
+  {
+    case "helme"      : suche=AT_HELMET; break;
+    case "umhaenge"   : suche=AT_CLOAK; break;
+    case "ruestungen" : suche=AT_ARMOUR; break;
+    case "hosen"      : suche=AT_TROUSERS; break;
+    case "schuhe"     : suche=AT_BOOT; break;
+    case "handschuhe" : suche=AT_GLOVE; break;
+    case "guertel"    : suche=AT_BELT; break;
+    case "amulette"   : suche=AT_AMULET; break;
+    case "ringe"      : suche=AT_RING; break;
+    case "koecher"    : suche=AT_QUIVER; break;
+    case "schilde"    : suche=AT_SHIELD; break;
+    case "sonstiges"  : suche=AT_MISC; break;
+    default           : write("Fehler: Ungueltiger Kleidungs-/Ruestungstyp. "
+                             +"Folgende Typen gibt es:\n"+nf_str1+nf_str2);
+                        return 1; break;
+  }
+  obs=all_inventory();
+  suchobs=([]);
+  for(i=0;i<sizeof(obs);i++)
+  {
+    obshort=obs[i]->QueryProp(P_SHORT);
+    if(obshort=="Nichts besonderes") // keine P_SHORT ?
+      obshort=obs[i]->Name(WER);     //   Hoffen wir mal dass das Obj. nen Namen hat.
+    if(obs[i]->QueryProp(P_ARMOUR_TYPE)==suche)    // Gesuchter ArmourType gefunden...
+    {
+      if(suchobs[obshort])                         // P_SHORT des Obj. schon im mapping?
+      {
+        if( obs[i]->QueryProp(P_AMOUNT) )
+          suchobs[obshort]+=obs[i]->QueryProp(P_AMOUNT); //   Dann den Zaehler um Amount hoch!
+        else
+          suchobs[obshort]+=1;                     //   Dann den Zaehler um 1 hoch!
+      }
+      else
+      {
+        if( obs[i]->QueryProp(P_AMOUNT) )
+          suchobs+=([obshort: obs[i]->QueryProp(P_AMOUNT)]);
+        else
+          suchobs+=([obshort: 1]);
+      }
+    }
+  }
+  strs=m_indices(suchobs);
+  if(sizeof(strs))
+  {
+    if(!alles)
+    {
+      strall+=Name(WER,1)+" enthaelt folgende "+CAP(was)+":\n";
+      strall+="------------------------------------------------------------\n";
+    }
+    else
+      strall+=ANSI_BOLD+"=== "+CAP(was)+":\n"+ANSI_NORMAL;
+    for(i=0;i<sizeof(strs);i++)
+    {
+      if(suchobs[strs[i]] > 1)
+        strall+=strs[i]+". ("+suchobs[strs[i]]+")\n";
+      else
+        strall+=strs[i]+".\n";
+    }
+  }
+  else
+    if(!alles)
+      strall+=Name(WER,1)+" enthaelt keine "+CAP(was)+"!\n";
+  return 1;
+}
+
+int auflistung(string str)
+{
+  string *strs, ob_id, was, nf_str1,nf_str2;
+  strall="";
+  nf_str1="   (Helme, Umhaenge, Ruestungen, Hosen, Schuhe, Handschuhe,\n"
+         +"    Guertel, Amulette, Ringe, Koecher, Schilde, Sonstiges)\n";
+  nf_str2="Syntax: sliste [Objekt-Id] [Kleidungs-/Ruestungstyp|\"alles\"]\n"
+         +"Bsp.:   sliste "+QueryProp(P_IDS)[1]+" "+"helme\n"
+         +"        sliste "+QueryProp(P_IDS)[1]+" alles\n";
+  notify_fail("Fehler: Ohne Parameter klappt das nicht.\n"+nf_str2);
+  if(!str) return 0;
+  if(present(str)==TO)   // Ueberpruefe, ob dieses Objekt gemeint ist!
+  {
+    write("Fehler: Es fehlt ein Kleidungs-/Ruestungstyp. Folgende Typen gibt es:\n"
+         +nf_str1+nf_str2);
+    return 1;
+  }
+  strs=old_explode(str, " ");
+  notify_fail("Fehler: Du musst eine gueltige Objekt-Id angeben!\n"
+             +nf_str2);
+  if( sizeof(strs) < 2 ) return 0;   // Nur 1 Par. und der ist nicht die Objekt-Id
+  if( sizeof(strs) == 2 )   // Anzahl Par. = 2
+  {
+    ob_id=strs[0];
+    was=strs[1];
+    if( IST_ZAHL(was) )     // Objekt-Id z.B. mit "schrank 2" angesprochen?
+      if(present(ob_id+" "+was)==TO)   // Falls dieses Objekt gemeint ist und kein 3. Par!
+      {
+        write("Fehler: Es fehlt ein Kleidungs-/Ruestungstyp. Folgende Typen gibt es:\n"
+              +nf_str1+nf_str2);
+        return 1;
+      }
+      else
+        return 0;
+  }
+  else if( sizeof(strs) == 3 )
+  {
+    ob_id=strs[0]+" "+strs[1];
+    was=strs[2];
+  }
+  else        // Anzahl erforderlicher Parameter ueberschritten!
+    return 0;
+  if(present(ob_id)!=TO)   // Ueberpruefe, ob auch dieses Objekt gemeint ist!
+    return 0;
+  if(QueryProp(P_CNT_STATUS)!=CNT_STATUS_OPEN)
+  {
+    write("Dazu muesste "+name(WER,1)+" geoeffnet sein.\n");
+    return 1;
+  }
+//--- Hier ist Parameterpruefung zu Ende.
+  was=LOWER(was);
+  if(was!="alles")
+    auflistung2(was, nf_str1, nf_str2, 0);
+  else
+  {
+    auflistung2("helme", nf_str1, nf_str2, 1);
+    auflistung2("umhaenge", nf_str1, nf_str2, 1);
+    auflistung2("ruestungen", nf_str1, nf_str2, 1);
+    auflistung2("hosen", nf_str1, nf_str2, 1);
+    auflistung2("schuhe", nf_str1, nf_str2, 1);
+    auflistung2("handschuhe", nf_str1, nf_str2, 1);
+    auflistung2("guertel", nf_str1, nf_str2, 1);
+    auflistung2("amulette", nf_str1, nf_str2, 1);
+    auflistung2("ringe", nf_str1, nf_str2, 1);
+    auflistung2("koecher", nf_str1, nf_str2, 1);
+    auflistung2("schilde", nf_str1, nf_str2, 1);
+    auflistung2("sonstiges", nf_str1, nf_str2, 1);
+  }
+  TP->More(strall);
+  return 1;
+}
diff --git a/d/seher/haeuser/moebel/swift_std_container.c b/d/seher/haeuser/moebel/swift_std_container.c
new file mode 100644
index 0000000..90f4986
--- /dev/null
+++ b/d/seher/haeuser/moebel/swift_std_container.c
@@ -0,0 +1,611 @@
+//----------------------------------------------------------------------------
+// Name des Objects:    Standard_Container
+// Letzte Aenderung:    21.03.2001
+// Magier:              Swift
+// Dieses File wird anstelle von /std/container inherited, so dass dem Objekt
+// erweiterte Moeglichkeiten zur Verfuegung stehen.
+//
+// 07.12.2005 (Seleven): Kurzbeschreibung ausblendbar gemacht
+// 30.06.2007 (Zesstra): create der BP wird nicht mehr abgebrochen. Auf die
+//   Art wird es dem Nutzer dieses Standardobjekt ueberlassen, ob er die BP
+//   initialisieren will oder nicht.
+// 01.07.2007 (Zesstra): Update der Moebel ruft erstmal UpdateMe() in den
+//   Moebeln auf. Wenn das != 0 liefert, ist UpdateMe() fuer das Update
+//   zustaendig und muss das machen.
+//   Ausserdem kleine Aenderung im Registrieren (nimmt auch Obekte als
+//   Standort)
+//   Weiterhin Moebel umgezogen nach /p/seher/moebel/ und in diesem File
+//   GetOwner() definiert, welches "Swift" zurueckgibt. Wer hiervon erbt,
+//   sollte damit also sein eigenes GetOwner() definieren.
+//   glob. Variablen auf 'nosave' geaendert.
+//----------------------------------------------------------------------------
+
+
+// Fuer Testzwecke ist es moeglich, dem entsprechenden Objekt die Property
+// "test" auf 1 zu setzen, damit ist dann so ziemlich alles erlaubt.
+// Man sollte die Property aber unbedingt wieder entfernen, sonst ist es z.B.
+// moeglich, einen Schrank von Seherhaus A nach Seherhaus B oder sogar hinaus
+// zu verschieben !!!
+
+#pragma strong_types,save_types,rtt_checks
+
+#include <container.h>
+inherit "/std/container";
+
+#include "schrankladen.h"
+
+#define VERSION_STD "9"
+
+nosave int hauserlaubnis;
+nosave string zweitieerlaubnis;
+nosave string *erlaubnis;
+
+int erlaubt();
+
+protected void create()
+{
+  //if (!clonep(TO)) return;
+  ::create();
+  SetProp(P_SHORT, "Ein Standard_Container von Swift");
+  SetProp(P_CNT_STATUS,CNT_STATUS_CLOSED);
+  SetProp(P_TRANSPARENT, 0);
+  SetProp(P_LOG_FILE,"seleven/schraenker"); // Seleven 06.04.2006
+  SetProp("cnt_hausfreunde", ({}) );
+  SetProp("cnt_erlaubnis", ({}) );
+  SetProp("cnt_zweitieerlaubnis", "" );
+  SetProp("cnt_version_std", VERSION_STD);
+
+  hauserlaubnis=0;
+  zweitieerlaubnis="";
+  erlaubnis=({});
+
+  set_next_reset(3600); // 1 x pro Std. Reset!
+
+  AddCmd(({"oeffne"}), "oeffnen");
+  AddCmd(({"schliess", "schliesse"}), "schliessen");
+  AddCmd(({"serlaube"}), "erlaubnis");
+  AddCmd(({"skommandos"}), "skommandos");
+  AddCmd(({"verschieb", "verschiebe"}), "verschieben");
+  AddCmd(({"zertruemmer", "zertruemmere"}), "zertruemmern");
+  //Seleven 07.12.2005:
+  AddCmd(({"sverstecke","sversteck"}),"verstecken");
+  AddCmd(({"shole","shol"}),"zeigen");
+}
+
+// Zesstra, 1.7.07, fuers Hoerrohr
+string GetOwner() {return "swift";}
+
+static string QueryHausbesitzer()
+{
+  return CAP(to_string(ETO->QueryOwner()));    // z.B.: Swift
+}
+
+
+
+static string QueryTP()
+{
+  return CAP(geteuid(TP));  // z.B.: Swift
+}
+
+int oeffnen(string str)
+{
+  notify_fail("Was moechtest Du oeffnen?\n");
+  if(!str) return 0;
+  if(present(str)!=TO)  // Ueberpruefe, ob auch dieses Objekt gemeint ist!
+      return 0;
+  if(QueryProp(P_CNT_STATUS)==CNT_STATUS_OPEN)
+  {
+    write(Name(WER,1)+" ist doch schon geoeffnet!\n");
+    return 1;
+  }
+  if( !erlaubt() )
+  {
+    write("Ein magisches Kraftfeld verhindert das Oeffnen "+name(WESSEN,1)+"!\n");
+    return 1;
+  }
+  write("Du oeffnest "+name(WEN)+".\n");
+  say(TP->Name(WER)+" oeffnet "+name(WEN)+".\n", ({TP}) );
+  SetProp(P_CNT_STATUS,CNT_STATUS_OPEN);
+  SetProp(P_TRANSPARENT, 1);
+  return 1;
+}
+
+int schliessen(string str)
+{
+  notify_fail("Was moechtest Du schliessen?\n");
+  if(!str) return 0;
+  if(present(str)!=TO)   // Ueberpruefe, ob auch dieses Objekt gemeint ist!
+    return 0;
+  if(QueryProp(P_CNT_STATUS)==CNT_STATUS_CLOSED)
+  {
+    write(Name(WER,1)+" ist doch schon geschlossen!\n");
+    return 1;
+  }
+  if( !erlaubt() )
+  {
+    write("Ein magisches Kraftfeld verhindert das Schliessen "+name(WESSEN,1)+"!\n");
+    return 1;
+  }
+  write("Du schliesst "+name(WEN)+".\n");
+  say(TP->Name(WER)+" schliesst "+name(WEN)+".\n", ({TP}) );
+  SetProp(P_CNT_STATUS,CNT_STATUS_CLOSED);
+  SetProp(P_TRANSPARENT, 0);
+  return 1;
+}
+
+string cnt_status()
+{
+  return Name(WER,1)+" ist "
+    +(QueryProp(P_CNT_STATUS)?"geschlossen":"geoeffnet")+".\n";
+}
+
+int erlaubt()
+{
+  if( QueryProp("test") ) return 1;       // Zu Testzwecken!
+  if( QueryHausbesitzer()=="0" )          // Schrank steht nicht in einem Seherhaus!
+  {
+    tell_room(ETO, Name(WER,1)+" sollte nicht ausserhalb eines Seherhauses stehen.\n"
+      +"Bitte Mail an "+VERANTWORTLICHER_MAGIER+"!\n");
+    return 0;
+  }
+  if( QueryTP() == QueryHausbesitzer() )  // Der Besitzer des Hauses selbst
+    return 1;
+  if(hauserlaubnis)
+  {
+    if( member(SHVERWALTER->HausProp(LOWER(QueryHausbesitzer()), 2),
+        QueryTP()) != -1 )                // Hausfreunde
+      return 1;
+  }
+  if(zweitieerlaubnis!="")                // Zweities
+  {
+    if( TP->QueryProp(P_SECOND) == zweitieerlaubnis )
+      return 1;
+  }
+  if( sizeof(erlaubnis) )
+  {
+    if( member(erlaubnis, QueryTP()) != -1 ) // Sonstige Personen die berechtigt sind
+      return 1;
+  }
+  return 0;
+}
+
+void cnt_open()
+{
+  SetProp(P_CNT_STATUS,CNT_STATUS_OPEN);
+  SetProp(P_TRANSPARENT, 1);
+}
+
+int erlaubnis_liste()
+{
+  int i;
+  string *strs,str;
+  if( QueryHausbesitzer() != QueryTP() && !QueryProp("test") )
+  {
+    write( BS("Nur "+QueryHausbesitzer()+" darf Berechtigungen "
+      +name(WESSEN,1)+" abfragen!"));
+    return 1;
+  }
+  write("=============================================================================\n");
+  if(hauserlaubnis)
+  {
+    strs=SHVERWALTER->HausProp(LOWER(QueryHausbesitzer()), 2);
+    write(BS("Folgende Freunde Deines Hauses duerfen "+name(WEN,1)
+      +" oeffnen/schliessen:"));
+    str="";
+    if(sizeof(strs))
+    {
+      for(i=0;i<sizeof(strs);i++)
+      {
+        str+=strs[i];
+        if(i<sizeof(strs)-1)
+          str+=", ";
+      }
+    }
+    else
+      str="Du hast keiner Person Zugriff auf Dein Haus gewaehrt...\n";
+    write(BS(str));
+  }
+  else
+    write(BS("Die Freunde Deines Hauses duerfen "+name(WEN,1)
+      +" nicht oeffnen/schliessen."));
+  write("-----------------------------------------------------------------------------\n");
+  if(zweitieerlaubnis!="")
+  {
+  if( zweitieerlaubnis==geteuid(TP) )
+    write(BS( "Alle Deine Zweities duerfen "+name(WEN,1)+" oeffnen/schliessen."));
+  else
+    write(BS( "Alle Zweities von "+CAP(zweitieerlaubnis)+" duerfen "+name(WEN,1)
+      +" oeffnen/schliessen."));
+  write("-----------------------------------------------------------------------------\n");
+  }
+  strs=QueryProp("cnt_erlaubnis");
+  if(sizeof(strs))
+  {
+    write(BS("Folgende sonstige Personen duerfen "+name(WEN,1)
+      +" oeffnen/schliessen:"));
+    str="";
+    for(i=0;i<sizeof(strs);i++)
+    {
+      str+=strs[i];
+      if(i<sizeof(strs)-1)
+        str+=", ";
+    }
+    write(BS(str));
+  }
+  else
+    write(BS("Es gibt keine sonstigen Personen, die "+name(WEN,1)
+      +" oeffnen/schliessen duerfen."));
+  write("=============================================================================\n");
+  return 1;
+}
+
+int erlaubnis(string str)
+{
+  string *strs,wen,nf_str;
+  nf_str="Syntax: serlaube [Objekt-Id] [Spielername|\"hausfreunde\"|\"zweities\"]\n"
+        +"Bsp.:   serlaube "+QueryProp(P_IDS)[1]+" hausfreunde\n"
+        +"        serlaube "+QueryProp(P_IDS)[1]+" zweities\n"
+        +"        serlaube "+QueryProp(P_IDS)[1]+" geordi\n"
+        +"        serlaube "+QueryProp(P_IDS)[1]+"      (Listet Spieler mit Erlaubnis)\n";
+  notify_fail("Fehler: Ohne Parameter klappt das nicht.\n"+nf_str);
+  if(!str) return 0;
+  if(present(str)==TO)     // Falls Par==Obj. und kein 2./3. Par.
+  {
+    erlaubnis_liste();           //   Liste der Erlaubten ausgeben!
+    return 1;
+  }
+  notify_fail("Fehler: Du musst eine gueltige Objekt-Id angeben!\n"+nf_str);
+  strs=old_explode(str, " ");
+  if( sizeof(strs) < 2 )           // Falls nur 1 Par.
+    return 0;             // Anzahl erforderlicher Parameter unterschritten!
+  else if( sizeof(strs) == 2 )
+  {
+    str=strs[0];
+    wen=strs[1];
+    if( IST_ZAHL(wen) )
+      if(present(str+" "+wen)==TO)   // Falls 2 Par. und dies das Obj. ist ohne 3. Par.
+      {
+        erlaubnis_liste();           //   Liste der Erlaubten ausgeben!
+        return 1;
+      }
+      else
+        return 0;
+  }
+  else if( sizeof(strs) == 3 )
+  {
+    str=strs[0]+" "+strs[1];
+    wen=strs[2];
+  }
+  else        // Anzahl erforderlicher Parameter ueberschritten!
+    return 0;
+  if(present(str)!=TO)   // Ueberpruefe, ob auch dieses Objekt gemeint ist!
+    return 0;
+  if( !erlaubt() && !QueryProp("test") )
+  {
+    write( BS("Nur "+QueryHausbesitzer()+" darf Berechtigungen "
+      +name(WESSEN,1)+" aendern!"));
+    return 1;
+  }
+  if(wen=="hausfreunde")
+  {
+    if(hauserlaubnis)
+    {
+      hauserlaubnis=0;
+      SetProp("cnt_hausfreunde", ({}) );
+    }
+    else
+    {
+      hauserlaubnis=1;
+      SetProp("cnt_hausfreunde", SHVERWALTER->HausProp(LOWER(QueryHausbesitzer()), 2) );
+    }
+    write( BS("Die Freunde Deines Seherhauses duerfen "+name(WEN,1)+" jetzt "
+      +(!hauserlaubnis?"nicht mehr ":"")+"oeffnen/schliessen."));
+    return 1;
+  }
+  if(wen=="zweities")
+  {
+    if(zweitieerlaubnis!="")                        // Zweities erlaubt?
+      zweitieerlaubnis="";                          //   dann verbieten!
+    else                                            // ansonsten:
+    {
+      if( TP->QueryProp(P_SECOND) )                 // Selbst ein Zweitie?
+        zweitieerlaubnis=LOWER(TP->QueryProp(P_SECOND)); // Die Zweities vom Erstie erlauben!
+      else                                          // sonst:
+        zweitieerlaubnis=geteuid(TP);               //   Eigene Ersties erlauben!
+    }
+    SetProp("cnt_zweitieerlaubnis", zweitieerlaubnis );
+    if(zweitieerlaubnis!="")
+      write( BS(CAP(zweitieerlaubnis)+"'s Zweities duerfen "+name(WEN,1)+" jetzt "
+        +(zweitieerlaubnis==""?"nicht mehr ":"")+"oeffnen/schliessen."));
+    return 1;
+  }
+  wen=CAP(wen);
+  if( file_size("//save//"+LOWER(wen[0..0])+"//"+LOWER(wen)+".o") != -1 ) // Spieler gibt es auch!
+  {
+    if( member(erlaubnis, wen) != -1 )  // Spieler hat Erlaubnis -> verbieten!
+    {
+      erlaubnis-=({wen});
+      write( BS( wen+" darf "+name(WEN,1)+" jetzt nicht mehr oeffnen/schliessen."));
+    }
+    else
+    {
+      erlaubnis+=({wen});
+      write( BS( wen+" darf "+name(WEN,1)+" jetzt oeffnen/schliessen."));
+    }
+    SetProp("cnt_erlaubnis", erlaubnis);
+    return 1;
+  }
+  else
+    write("Es gibt keinen Spieler namens "+wen+"!\n");
+  return 1;
+}
+
+varargs int skommandos(string str)
+{
+  notify_fail( "Fehler: Dieser Befehl benoetigt eine gueltige Objekt-Id als Parameter.\n"
+    +"Beispiel: skommandos "+QueryProp(P_IDS)[1]+"\n");
+  if(!str) return 0;
+  if(present(str)!=TO ) // Bin ich gemeint?
+    return 0;
+  write("=============================================================================\n");
+  write("Aktuelle Version: "+QueryProp("cnt_version_std")+QueryProp("cnt_version_obj")+"\n");
+  write( BS(Name(WER,1)+" kann nur in diesem Seherhaus verwendet werden, "
+    +"da "+QueryPronoun(WER)+" speziell dafuer gekauft wurde. "+CAP(QueryPronoun(WER))
+    +" verfuegt ueber folgende Kommandos:")
+    +"-----------------------------------------------------------------------------\n"
+    +"oeffne [Objekt-Id]\n"
+    +"  oeffnet "+name(WEN,1)+"\n\n"
+    +"schliesse [Objekt-Id]\n"
+    +"  schliesst "+name(WEN,1)+"\n\n"
+    +"serlaube [Objekt-Id] [Spielername|\"hausfreunde\"|\"zweities\"]\n"
+    +"  Erlaubt Personen, "+name(WEN,1)+" mitzubenutzen.\n"
+    +"  serlaube + Objekt-Id (ohne Spielername/hausfreunde)\n"
+    +"  listet alle Personen mit Zugriff auf "+name(WEN,1)+"\n\n"
+    +"verschiebe [Objekt-Id] nach [Ausgang]\n"
+    +"  Damit kannst Du "+name(WEN,1)+" innerhalb Deines Seherhauses verschieben.\n\n"
+  //Seleven 07.12.2005
+    +"sverstecke [Objekt-Id]\n"
+    +"  Damit machst Du "+name(WEN,1)+" unsichtbar.\n"
+    +"shole [Objekt-Id] hervor\n"
+    +"  Damit machst Du "+name(WEN,1)+" wieder sichtbar.\n"
+  // Bis hier
+    +"zertruemmer [Objekt-Id]\n"
+    +"  Damit zerstoerst Du "+name(WEN,1)+".\n\n");
+
+
+  if( QueryProp("obj_cmd") )
+    write( QueryProp("obj_cmd")+"\n" );
+
+  write("[Objekt-Id] muss eine gueltige Id sein, in diesem Fall z.B. "
+      +QueryProp(P_IDS)[1]+"\n");
+  write("=============================================================================\n");
+
+
+  return 1;
+}
+
+int verschieben(string str)
+{
+  string was, wohin, zielraum,nf_str;
+  nf_str="Syntax: verschiebe [Objekt-Id] nach [Richtung]\n"
+        +"Bsp.:   verschiebe "+QueryProp(P_IDS)[1]+" nach osten\n";
+  notify_fail("Fehler: Ohne Parameter klappt das nicht.\n"+nf_str);
+  if(!str) return 0;
+  if(sscanf(str,"%s nach %s", was, wohin) != 2)
+    return 0;
+  notify_fail("Fehler: Du musst eine gueltige Objekt-Id angeben!\n"+nf_str);
+  if(present(was)!=TO)   // Ueberpruefe, ob auch dieses Objekt gemeint ist!
+    return 0;
+  if( QueryHausbesitzer() != QueryTP() && !QueryProp("test") )
+  {
+    write( BS("Nur "+QueryHausbesitzer()+" darf "+name(WEN,1)+" verschieben!"));
+    return 1;
+  }
+  if( member(m_indices(ETO->QueryProp(P_EXITS)), wohin) != -1 ) // Ausgang vorhanden?
+  {
+    zielraum=ETO->QueryProp(P_EXITS)[wohin];
+    if( strstr(zielraum, LOWER(QueryHausbesitzer())+"raum", 0) != -1  ||
+        QueryProp("test") )  // Gleiches Seherhaus? Oder Test?
+    {
+      TO->move(zielraum, M_PUT);
+      write("Du verschiebst "+name(WEN,1)+" nach "+CAP(wohin)+".\n");
+      TP->move(zielraum, M_GO, "nach "+CAP(wohin), "schiebt "+name(WEN),
+                              "schiebt "+name(WEN)+" herein");
+      if( present("Interactive", SCHRANKMASTER) )
+        tell_room(SCHRANKMASTER, TP->Name(WER)+" verschiebt "+name(WEN)+" nach "
+          +to_string(ETO)+".\n");
+    }
+    else
+      write( BS("Du kannst "+name(WEN,1)+" nicht in einen Raum ausserhalb "
+        +"Deines Hauses schieben!"));
+  }
+  else
+    write( BS("Es gibt keinen Ausgang namens \""+wohin+"\", wohin Du "
+      +name(WEN,1)+" verschieben koenntest.",78,"Fehler: ", BS_INDENT_ONCE));
+  return 1;
+}
+
+int zertruemmern(string str)
+{
+  string nf_str;
+  nf_str="Syntax: zertruemmer [Objekt-Id]\n"
+        +"Bsp.:   zertruemmer "+QueryProp(P_IDS)[1]+"\n";
+  notify_fail("Fehler: Ohne Parameter klappt das nicht.\n"+nf_str);
+  if(!str) return 0;
+  notify_fail("Fehler: Du musst eine gueltige Objekt-Id angeben!\n"+nf_str);
+  if(present(str)!=TO)   // Ueberpruefe, ob auch dieses Objekt gemeint ist!
+    return 0;
+  if( QueryHausbesitzer() != QueryTP() && !QueryProp("test") )
+  {
+    write( BS("Nur "+QueryHausbesitzer()+" darf "+name(WEN,1)+" zertruemmern!"));
+    return 1;
+  }
+  write( BS("Du zertruemmerst "+name(WEN)+" mit wuchtigen Schlaegen, bis "
+    +"nicht mal mehr Kruemel von "+QueryPronoun(WEM)+" uebrig sind."));
+  tell_room(ETO, BS( TP->Name(WER)+" zertruemmert "+name(WEN)+"."), ({TP}) );
+  call_other(SCHRANKMASTER,"???",0);
+  if( present("Interactive", SCHRANKMASTER) )
+    tell_room(SCHRANKMASTER, TP->Name(WER)+" zertruemmert "+name(WEN)+".\n");
+  SCHRANKMASTER->RemoveCnt(TO, geteuid(TP) );
+  remove(1);
+  if(TO) destruct(TO);
+  return 1;
+}
+
+int props2vars()  // Fuer die Update-Funktion des Schrankmasters
+{
+  zweitieerlaubnis=QueryProp("cnt_zweitieerlaubnis")||"";
+  erlaubnis=QueryProp("cnt_erlaubnis")||({});
+  if( sizeof(QueryProp("cnt_hausfreunde")) )
+    hauserlaubnis=1;
+  else
+    hauserlaubnis=0;
+  if( QueryProp(P_CNT_STATUS) == CNT_STATUS_OPEN)
+    SetProp(P_TRANSPARENT, 1);
+  else
+    SetProp(P_TRANSPARENT, 0);
+  return 1;
+}
+
+void reset()
+{
+  set_next_reset(3600); // 1 x pro Std. Reset!
+  ::reset();
+}
+
+public varargs int remove(int silent)
+{
+  // Beim Schrankmaster abmelden, dann zerstoeren.
+  string uid="";
+  if (objectp(environment()))
+  {
+    uid=environment()->QueryOwner();                
+  }
+  SCHRANKMASTER->RemoveCnt(TO, uid );
+  return ::remove(silent);
+}
+
+public int UpdateMe()
+{
+  if (!objectp(environment()))
+    return 0;
+  object cnt_neu=clone_object(load_name(ME));  // Neuen Schrank clonen
+  cnt_neu->move( environment(), M_NOCHECK );  // In selben Raum wie alten schieben...
+  cnt_neu->SetProp("cnt_status", QueryProp("cnt_status") );
+  cnt_neu->SetProp("cnt_hausfreunde", QueryProp("cnt_hausfreunde") );
+  cnt_neu->SetProp("cnt_erlaubnis", QueryProp("cnt_erlaubnis") );
+  cnt_neu->SetProp("cnt_zweitieerlaubnis", QueryProp("cnt_zweitieerlaubnis") );
+  cnt_neu->props2vars();  // Schrank liest gesetzte Props aus in eigene Vars
+  // Inventar bewegen
+  foreach(object inv: all_inventory(this_object()))
+  {
+    if( inv->IsUnit() )                          // Units
+      inv->move(cnt_neu, M_NOCHECK|M_MOVE_ALL);
+    else                                            // Normale Objekte
+      inv->move(cnt_neu, M_NOCHECK);
+  }
+  remove(1);
+  return 1;
+}
+
+// Eingebaut 07.12.2005 von Seleven
+// Die Kurzbeschreibung invis machen:
+static int verstecken (string str)
+{
+   string nf_str;
+   nf_str="Syntax: sverstecke [Objekt-Id]\n"
+         +"Bsp.:   sverstecke "+QueryProp(P_IDS)[1]+"\n";
+   notify_fail("Fehler: Ohne Parameter klappt das nicht.\n"+nf_str);
+   if(!str || sizeof(str) == 0 || !stringp(str)) return 0;
+
+   notify_fail("Fehler: Du musst eine gueltige Objekt-Id angeben!\n"+nf_str);
+   if(present(str)!=TO)   // Ueberpruefe, ob auch dieses Objekt gemeint ist!
+    return 0;
+
+  if( QueryHausbesitzer() != QueryTP() && !QueryProp("test") )
+  {
+    write( BS("Nur "+QueryHausbesitzer()+" darf "+name(WEN,1)+" verstecken!"));
+    return 1;
+  }
+  notify_fail("Du hast "+name(WEN,1)+" doch schon versteckt!\n");
+  if(QueryProp("versteckt") == 1) return 0;
+  write("Du versteckst "+name(WEN,1)+".\n");
+  SetProp("versteckt", 1);
+  return 1;
+}
+
+static int zeigen (string str)
+{
+   string nf_str;
+   nf_str="Syntax: shole [Objekt-Id] hervor\n"
+         +"Bsp.:   shole "+QueryProp(P_IDS)[1]+" hervor\n";
+   notify_fail("Fehler: Ohne Parameter klappt das nicht.\n"+nf_str);
+   if(!str || sizeof(str) == 0 || !stringp(str)) return 0;
+   if(strstr(str,"hervor") != -1)
+    sscanf(str,"%s hervor",str);
+   notify_fail("Fehler: Du musst eine gueltige Objekt-Id angeben!\n"+nf_str);
+   if(present(str)!=TO)   // Ueberpruefe, ob auch dieses Objekt gemeint ist!
+    return 0;
+
+   if( QueryHausbesitzer() != QueryTP() && !QueryProp("test") )
+   {
+     write( BS("Nur "+QueryHausbesitzer()+" darf "+name(WEN,1)+
+               " wieder hervorholen!"));
+     return 1;
+   }
+   notify_fail(Name(WER,1)+" ist doch gar nicht versteckt!\n");
+   if(QueryProp("versteckt") == 0) return 0;
+   write("Du holst "+name(WEN,1)+" aus dem Versteck.\n");
+   SetProp("versteckt", 0);
+   return 1;
+}
+
+
+mixed short()
+{
+  string sh;
+
+  // Unsichtbar? Dann gibts nichts zu sehen ...
+  if (QueryProp(P_INVIS)||!(sh=QueryProp(P_SHORT)))
+  return 0;
+
+  if(QueryProp(P_CNT_STATUS)==CNT_STATUS_OPEN)
+  {sh += " (geoeffnet)";}
+
+  if(QueryProp("versteckt") == 1) {sh = "";}
+  else sh += ".";
+
+  return process_string(sh)+"\n";
+}
+
+// hier nicht genutzt, zum Ueberschreiben gedacht.
+protected void SetBesitzer(string uid, string uuid) { }
+
+// nach dem move schauen, ob man in einem Seherhaus ist. Wenn ja, wird die
+// Funktion SetBesitzer() gerufen und ihr UID und UUID des Eigentuemers
+// uebergeben. Sollten UID und/oder UUID nicht bestimmbar sein, wird die
+// Funktion nicht gerufen.
+protected void NotifyMove(object dest, object oldenv, int method)
+{
+
+  ::NotifyMove(dest, oldenv, method);
+
+  if (dest
+      && strstr(object_name(dest),"/d/seher/haeuser/") == 0)
+  {
+    // (vermutlich) in einem Seherhaus
+    string uid = dest->QueryOwner();
+    // erstmal beim Schrankmaster anmelden.
+    SCHRANKMASTER->RegisterCnt(TO, QueryProp("cnt_version_std")
+        +":"+QueryProp("cnt_version_obj"), uid, dest);
+    // UUID rausfinden
+    mixed ret = (mixed)master()->get_userinfo(uid);
+    if ( pointerp(ret) && sizeof(ret) >= 5 )
+    {
+      // Username + "_" + CreationDate
+      SetBesitzer(uid, ret[0] + "_" + ret[5]);
+    }
+    // else: User unbekannt? -> jedenfalls keine initialisierung moeglich.
+  }
+}
+
diff --git a/d/seher/haeuser/moebel/tresor.c b/d/seher/haeuser/moebel/tresor.c
new file mode 100644
index 0000000..ecad6d7
--- /dev/null
+++ b/d/seher/haeuser/moebel/tresor.c
@@ -0,0 +1,78 @@
+//--------------------------------------------------------------------------------
+// Name des Objects:    Tresor
+// Letzte Aenderung:    17.03.2001
+// Magier:              Swift
+//--------------------------------------------------------------------------------
+#pragma strong_types,rtt_checks
+
+#include "schrankladen.h"
+inherit LADEN("swift_std_container");
+
+#define VERSION_OBJ "3"
+
+protected void create()
+{
+  if (!clonep(TO)) return;
+  swift_std_container::create();
+  SetProp(P_SHORT, "Ein Tresor");
+  SetProp(P_LONG, BS(
+     "Ein sehr stabiler und feuersicherer Tresor, an dem sich sicher schon so "
+    +"mancher Einbrecher eine Abfuhr geholt hat. Das magische Feld, das den "
+    +"Tresor umgibt, verhindert wohl auch Attacken magischer Art. So wuchtig "
+    +"und wichtig, wie dieser Klotz aussieht, vermutest Du wohl zu Recht, "
+    +"dass sich unsagbare Reichtuemer in seinem Inneren verbergen muessen.")
+    +"@@cnt_status@@");
+  AddId(({"tresor"}));
+  SetProp("cnt_version_obj", VERSION_OBJ);
+  SetProp(P_NAME, "Tresor");
+  SetProp(P_GENDER, MALE);
+  SetProp(P_WEIGHT, 5000);         // Gewicht 5 Kg
+  SetProp(P_MAX_WEIGHT, 1000000);  // Es passen fuer 1000 kg Sachen rein.
+  SetProp(P_WEIGHT_PERCENT, 100);  // Dafuer macht er auch nix leichter :)
+  SetProp(P_MAX_OBJECTS, 100);     // Mehr sollte nicht sein, lt. Tiamak.
+  SetProp(P_VALUE, 0);             // Kein materieller Wert. Ist eh nicht verkaufbar.
+  SetProp(P_NOBUY, 1);             // Wird im Laden zerstoert, falls er verkauft wird.
+  SetProp(P_NOGET, "Das geht nicht. "+Name(WER,1)+" haftet wie magisch am Boden.\n");
+  SetProp(P_MATERIAL, ({MAT_STEEL, MAT_MISC_MAGIC}) );
+  SetProp(P_INFO, "Versuchs mal mit: \"skommandos "+QueryProp(P_IDS)[1]+"\" !\n");
+
+  AD(({"feld"}), BS("Ein starkes magisches Feld umgibt "+name(WEN,1)+"."));
+  AD(({"klotz"}), BS(Name(WER,1)+" ist wahrlich ein Klotz, ausgesprochen wuchtig."));
+}
+
+varargs int PreventInsert(object ob)
+{
+  // Zuerst mal: Dinge, deren Wert >= 5000 Muenzen ist, duerfen rein, solange
+  // es keine Ruestungen oder Waffen sind!
+  if( ob->QueryProp(P_VALUE) >= 5000 && !ob->QueryProp(P_ARMOUR_TYPE) &&
+     !ob->QueryProp(P_WEAPON_TYPE) )
+        return ::PreventInsert(ob);
+  if( ob->id("\ngeld") ||                                     // Geld?
+      ob->QueryMaterialGroup(MATGROUP_PRECIOUS_METAL) ||      // Edelmetall?
+      ob->QueryMaterialGroup(MATGROUP_JEWEL) ||               // Edelstein?
+      ob->QueryMaterial(MAT_CRYSTAL) ||                       // Kristall?
+      ob->QueryMaterial(MAT_IVORY) )                          // Elfenbein?
+  {
+    if(!ob->QueryProp(P_WEAPON_TYPE) )    // Auf keinen Fall Waffen!
+    {
+      if( ob->QueryProp(P_ARMOUR_TYPE ) ) // Falls Ruestungsteil...
+      {
+        if( ob->QueryProp(P_ARMOUR_TYPE)==AT_RING ||
+            ob->QueryProp(P_ARMOUR_TYPE)==AT_AMULET ||
+            ob->QueryProp(P_ARMOUR_TYPE)==AT_MISC )
+          return ::PreventInsert(ob);
+        else
+          write(BS("Nur wertvolle Ringe und Amulette kannst Du in "+name(WEN,1)
+            +" stecken, evtl. noch andere wertvolle Sachen, aber auf keinen "
+            +"Fall Ruestungen oder Waffen!"));
+      }
+      else
+        return ::PreventInsert(ob);
+    }
+    else
+      write("Waffen kannst Du nicht in "+name(WEN,1)+" tun!\n");
+  }
+  write( BS("In "+name(WEN,1)+" kannst Du nur Geld und Edelsteine legen, evtl. auch "
+           +"wertvolle Objekte, z.B. aus Edelmetallen, Kristall oder Elfenbein!"));
+  return 1;
+}
diff --git a/d/seher/haeuser/moebel/verkaeufer.c b/d/seher/haeuser/moebel/verkaeufer.c
new file mode 100644
index 0000000..5143ab2
--- /dev/null
+++ b/d/seher/haeuser/moebel/verkaeufer.c
@@ -0,0 +1,311 @@
+//--------------------------------------------------------------------------------
+// Name des Objects:    Verkaeufer (August vom SCHRAENKER)
+// Letzte Aenderung:    24.08.2006
+// Magier:              Seleven
+//--------------------------------------------------------------------------------
+#pragma strong_types,rtt_checks
+
+#include <properties.h>
+#include <language.h>
+#include <moving.h>
+#include <wizlevels.h>
+#include <bank.h>
+
+#include "schrankladen.h"
+inherit "/std/npc";
+
+// Wenn im Laden bzw. im Environment von August die Prop "test" auf 1 gesetzt
+// wird, kostet der Kauf nichts. Jeder der ein Seherhaus besitzt, kann kaufen.
+
+// Fuer Prop im Spieler = individuellere Begruessung
+#define LASTVISIT "schrankladen_lastvisit"
+// 10% Rabatt fuer Leute, die intensiv testeten, Ideen fuer den Laden beisteuerten,
+// oder halfen, groessere Bugs zu beheben!
+#define RABATT ({"geordi","foobar","blood","lurchi", "eldaron"})
+
+// kaufe... andere im raum sollten vor der antwort sehen wer august nach was fragt
+
+protected void create()
+{
+  if(!clonep(TO)) return;
+  ::create();
+  SetProp(P_LOG_FILE,"seleven/schraenker"); // Seleven 06.04.2006
+  SP(P_SHORT, "August");
+  SP(P_LONG, BS(
+     "Das ist August, ein kleiner Zwerg und seines Zeichens Seher-Berater. "
+    +"Er versorgt Seher mit Eigenheim mit dem Mobiliar, das man braucht, "
+    +"will man sein Haus uebersichtlich halten und etwas Ordnung in die "
+    +"Sammlungen bringen, die sich in so einem Seherhaus zwangslaeufig "
+    +"anhaeufen. Im Gegensatz zu den meisten Zwergen sieht August nicht nur "
+    +"aus wie frisch geduscht, er steckt auch in einem feinen Anzug. So "
+    +"einen gepflegten Bart wie den von August hast Du vorher noch nie "
+    +"gesehen. Und dann duftet er auch noch nach irgendeinem exotischen "
+    +"Waesserchen. Waere nicht der gierige Blick in seinen Augen, koenntest "
+    +"Du wirklich zweifeln, dass es sich hier wirklich um einen Zwerg "
+    +"handelt.",78,0,1));
+  SP(P_NAME, "August");
+  SP(P_GENDER, MALE);
+  SP(P_ARTICLE, 0);
+  SP(P_RACE, "Zwerg");
+  // Arathorn, 2015-Okt-13, Zeile vor P_XP gezogen, damit auch sicher kein
+  // EK angezeigt wird.
+  create_default_npc(20);
+  SP(P_XP, 0);
+  AddId(({"august", "inhaber", "ladeninhaber", "besitzer",
+          "firmenbesitzer", "verkaeufer", "zwerg", "seher-berater"}));
+
+  SP(P_SIZE, 130);
+  SP(P_NO_ATTACK, BS("Die beruhigende Melodie scheint nicht nur zum "
+    +"Vergnuegen der Kunden zu erklingen. Du bringst es einfach "
+    +"nicht fertig, Deine Hand gegen August zu erheben!"));
+
+  AD(({"anzug"}), BS(Name(WER)+" steckt in einem feinen rotbraunen Anzug, "
+    +"in dem vermutlich auch ein Bettler koeniglich auf Dich wirken wuerde. "
+    +"Offensichtlich ist er nicht der Aermsten einer."));
+  AD(({"bettler"}), BS("Wie ein Bettler wirkt August nicht auf Dich."));
+  AD(({"waesserchen"}), BS("Es riecht koestlich. Schnupper doch mal!"));
+  AD(({"bart"}), BS("Der vermutlich weisse Bart wurde von Kuenstlerhand "
+    +"roetlich eingefaerbt und passt farblich vorzueglich zum Anzug."));
+  AD(({"kuenstlerhand"}), BS("Bestimmt hat August das nicht selbst gemacht."));
+  AD(({"mobiliar"}), BS("Das verkauft er hier."));
+  AD(({"augen"}), BS("Obwohl "+Name(WER)+" perfekte Manieren an den Tag "
+    +"legt, seine Augen verraten ihn. Die Dollarzeichen in seinem Blick "
+    +"sind nicht zu uebersehen."));
+  AD(({"dollarzeichen"}), BS("Eine Redensart. Keine Ahnung was das sein soll."));
+  AD(({"redensart"}), BS("Irgend ein Spruch, den Du irgendwo aufgeschnappt hast."));
+  AD(({"spruch"}), BS("Im Spruecheklopfen bist Du gut, oder?"));
+  AD(({"spruecheklopfen"}), BS("OK, ich geb auf. :)"));
+  AD(({"manieren"}), "Und das bei einem Zwerg!!!\n");
+
+  AddInfo(({"laden", "schraenker"}), "Der Schraenker ist mein Laden, "
+    +"und ich denke es ist ein guter Laden. Das Geschaeft laeuft, seit "
+    +"jeder Ordnung in seinem Seherhaus haben moechte. Und Seherhaeuser "
+    +"gibt es ja mehr als genug! :)", "sagt: ");
+  AddInfo(({"haeuser", "seherhaeuser"}), "Bei mir koennen Seher "
+    +"Mobiliar fuer ihr Seherhaus kaufen. Unsere Qualitaet ist weithin "
+    +"beruehmt. Ausserdem sind wir die einzigen auf dem Markt.", "grinst: ");
+  AddInfo(({"melodie"}), "lauscht vertraeumt.\n");
+  AddInfo(({"geld"}), "Sie haben doch welches?\n", "fragt besorgt: ");
+  // Seleven 01.04.2006: frage nach (schluessel)brett eingefuegt
+  AddInfo(({"mobiliar", "schrank", "schraenke", "truhe", "truhen", "kommode",
+     "kuehlschrank", "waffenschrank", "waffentruhe", "spind", "kleiderschrank","brett","schluesselbrett",
+     "muellcontainer", "zauberkiste", "tresor", "holztruhe","vitrine","pult","lesepult"}),
+     "Lesen Sie doch bitte die Preisliste an der Wand.", "sagt: ");
+  AddInfo(({"liefern", "lieferung"}), "Wir liefern sofort.", "sagt: ");
+  AddInfo(({"bart"}), "Es ist ein schoener Bart, nicht? :)", "fragt: ");
+  AddInfo(({"augen"}), "Was haben Sie an denen auszusetzen?", "fragt: ");
+  AddInfo(({"dusche"}), "Jeden Morgen. Das ist leider Pflicht. Und 364 mal "
+    +"zu oft :(", "sagt: ");
+  AddInfo(({"pflicht", "pflichten"}), "Als Ladeninhaber hat man deren "
+    +"viele!", "sagt: ");
+  AddInfo(({"anzug"}), "Ein echter Armgani!", "verkuendet stolz: ");
+  AddInfo(({"armgani"}), "Du kennst Armgani nicht?", "fragt naseruempfend: ");
+  AddInfo(({"geordi"}), "Von ihm stammt die urspruengliche Geschaeftsidee "
+    +"fuer den SCHRAENKER. Dafuer bekommt er bei uns auch Rabatt!", "erzaehlt: ");
+  AddInfo(({"august"}), "Wollen Sie sich ueber mich lustig machen?", "fragt drohend: ");
+  AddInfo(({"rabatt"}), "Nur Stammkunden, die uns schon brauchbare Ideen "
+    +"geliefert haben, oder die uns beim Aufbau des Geschaefts geholfen haben, "
+    +"gewaehren wir Rabatt.", "sagt: ");
+  AddInfo(({"ideen"}), "Es muessen brauchbare Ideen sein.", "sagt: ");
+  AddInfo(({"stammkunde", "stammkunden"}), "Einige kommen oefter vorbei.", "sagt: ");
+  AddInfo(({"aufbau"}), "Es kommt mir noch so vor, als waers gestern gewesen.", "sagt: ");
+  AddInfo(({"kunde", "kunden"}), "Ich hoffe mal, dass SIE der Kunde sind!?", "sagt: ");
+
+  AddCmd(({"kauf", "kaufe", "bestell", "bestelle"}), "container_kaufen");
+  AddCmd(({"schnupper", "schnuppere"}), "schnuppern");
+}
+
+int schnuppern()
+{
+  write(BS("Ein betoerender Duft umgibt August, und verdeckt jeglichen Geruch, "
+    +"den Du von sonstigen Zwergen gewohnt bist."));
+  return 1;
+}
+
+static string anrede()
+{
+  switch( TP->QueryProp(P_GENDER) )
+  {
+    case MALE   : return "mein Herr"; break;
+    case FEMALE : return "meine Dame"; break;
+  }
+  return "mein H... D... Wasauchimmer";
+}
+
+void begruessung(object pl, string txt)
+{
+  if( objectp(pl) && present(pl) )
+    tell_room(ETO, "\n"+txt);
+}
+
+void init()
+{
+  ::init();
+  if (!interactive(TP) || TP->QueryProp(P_INVIS))
+      return 0; // Keine Meldungen wenn invis oder kein Spieler!
+  if(TP->QueryProp(LASTVISIT) < time()-3600)  // laenger als 1 Std. nicht da gewesen
+  {
+    if( member(RABATT, geteuid(TP)) != -1 )
+      call_out("begruessung", 0, TP, BS("Herzlichst Willkommen in meinem "
+        +"bescheidenen Laden, "+TP->name(WER)+". Es ist jedesmal eine Freude, "
+        +"Sie zu sehen!",78, Name(WER)+" sagt: "));
+    else
+      call_out("begruessung", 0, TP, BS("Willkommen in meinem bescheidenen Laden, "
+        +anrede()+".",78, Name(WER)+" sagt: "));
+  }
+  else  // schonmal innerhalb 1 Std. da gewesen?
+  {
+    if( member(RABATT, geteuid(TP)) != -1 )
+      call_out("begruessung", 0, TP, BS("Hallo, "+TP->name(WER)+". "
+        +"Sie konnten es ja nicht lange ohne mich aushalten, aber Stammkunden "
+        +"sind mir die liebsten Kunden. Womit kann ich Ihnen diesmal "
+        +"dienen?",78, Name(WER)+" sagt: "));
+    else
+      call_out("begruessung", 0, TP, BS("Guten Tag, "+anrede()+". "
+        +"Ich freue mich, dass Sie meinen Laden so bald wieder besuchen kommen! "
+        +"Womit kann ich Ihnen diesmal dienen?",78, Name(WER)+" sagt: "));
+  }
+
+  TP->SetProp(LASTVISIT, time() );
+}
+
+int container_kaufen(string str)
+{
+  string cnt_file;
+  int preis;
+  object zielraum,cnt,ob;
+  tell_room(ETO, TP->Name(WER)+" wendet sich wegen eines Kaufs an "
+    +Name(WEN)+".\n", ({TP}) );
+  if( (query_wiz_level(TP) >= SEER_LVL && query_wiz_level(TP) < LEARNER_LVL) ||
+      ETO->QueryProp("test") ) // TP ist Seher, oder Testmodus.
+  {
+    catch(call_other("/d/seher/haeuser/"+geteuid(TP)+"raum0", "???", 0));
+    if( !zielraum=find_object("/d/seher/haeuser/"+geteuid(TP)+"raum0") )
+    {
+      tell_room(ETO, BS("Tut mir leid, "+anrede()+". Voraussetzung fuer eine "
+        +"Lieferung unserer Artikel ist ein begehbares "
+        +"Seherhaus.",78, Name(WER)+" sagt: "));
+      return 1;
+    }
+    notify_fail( BS("Tut mir leid, "+anrede()+". So einen Artikel fuehren wir nicht. "
+      +"Bitte lesen Sie die Preisliste an der Wand. Dort koennen Sie sich genau "
+      +"darueber informieren, ueber welche Artikel wir zur Zeit "
+      +"verfuegen.",78, Name(WER)+" sagt: "));
+    if(!str) return 0;
+    switch(str)
+    {
+      case "1" :
+      case "kommode" :       cnt_file="kommode";
+                             preis=3799;
+                             break;
+      case "2" :
+      case "kleiderschrank": cnt_file="kleiderschrank";
+                             preis=5899;
+                             break;
+      case "3" :
+      case "spind" :         cnt_file="spind";
+                             preis=5299;
+                             break;
+      case "4" :
+      case "kuehlschrank" :  cnt_file="kuehlschrank";
+                             preis=3499;
+                             break;
+      case "5" :
+      case "waffenschrank" : cnt_file="waffenschrank";
+                             preis=5899;
+                             break;
+      case "6" :
+      case "waffentruhe" :   cnt_file="waffentruhe";
+                             preis=5399;
+                             break;
+      case "7" :
+      case "tresor" :        cnt_file="tresor";
+                             preis=4499;
+                             break;
+      case "8" :
+      case "zauberkiste" :   cnt_file="zauberkiste";
+                             preis=7999;
+                             break;
+      case "9" :
+      case "muellcontainer": cnt_file="muellcontainer";
+                             preis=999;
+                             break;
+      // Seleven 01.04.2006
+      case "10" :
+      case "schluesselbrett": cnt_file="schluesselbrett";
+                             preis=499;
+                             break;
+      case "11" :
+      case "duschkabine": cnt_file="wasch";
+                             preis=3499;
+                             break;
+      case "12":
+      case "holztruhe":
+                             cnt_file="autoloadertruhe";
+                             preis=74999;
+                             break;
+      case "13":
+      case "vitrine":
+                             cnt_file="vitrine";
+                             preis=49999;
+                             break;
+      case "14":
+      case "lesepult":
+                            cnt_file="lesepult";
+                            preis=60000;
+                             break;
+      default:               return 0; break;
+    }
+    if( member(RABATT, geteuid(TP)) != -1 )  // 10% Rabatt fuer bestimmte Leute,
+      preis=preis/100*90;                    // die Ideen fuer den Laden beisteuerten.
+    if( !ETO->QueryProp("test") )
+    {
+      if( !TP->QueryMoney() )
+      {
+        tell_room(ETO, BS("Ohne Geld bekommen Sie bei uns nichts, "+anrede()
+          +". Wir sind kein Wohlfahrtsinstitut!",78, Name(WER)+" sagt: "));
+        return 1;
+      }
+      if( TP->QueryMoney() < preis )
+      {
+        tell_room(ETO, BS( CAP(anrede())+", Sie haben zuwenig Geld dabei. "
+          +"Der Preis fuer dieses Objekt ist "+preis
+          +" Muenzen.",78, Name(WER)+" sagt: "));
+        return 1;
+      }
+      TP->AddMoney(-preis);      // Spieler Geld abziehen
+      ZENTRALBANK->PayIn(preis); // Geld auf die Bank.
+    }
+    cnt=clone_object( LADEN(cnt_file) );
+    cnt->move(zielraum, M_PUT|M_SILENT);
+    tell_room(ETO, TP->Name(WER)+" kauft "+cnt->name(WEN)+".\n", ({TP}) );
+    tell_room(ETO, BS("Es ist ein Vergnuegen, mit Ihnen Geschaefte zu machen, "
+      +anrede()+"! Wenn Sie in Ihr Haus zurueckkehren, werden Sie die Ware bereits "
+      +"vorfinden, so schnell arbeiten wir.",78, Name(WER)+" sagt: "));
+    tell_room(zielraum, BS("Mit Knall und Schwefelduft erscheint ein kleines, "
+      +"verhutzeltes Maennchen. Es traegt einen gruenen Anzug und eine gruene "
+      +"Kappe, auf der in gelbem Schriftzug \"SCHRAENKER\" steht. Das Maennchen "
+      +"stellt "+cnt->name(WEN)+" ab und verschwindet auf dem gleichen Wege, wie "
+      +"es hereingekommen ist."));
+    if( present("Interactive", SCHRANKMASTER) )
+      tell_room(SCHRANKMASTER, TP->Name(WER)+" kauft "+name(WEN)+".\n");
+    SCHRANKMASTER->RegisterCnt(cnt, cnt->QueryProp("cnt_version_std")
+      +cnt->QueryProp("cnt_version_obj"), geteuid(TP),
+       "/d/seher/haeuser/"+geteuid(TP)+"raum0");
+    return 1;
+  }
+  else if(query_wiz_level(TP) >= LEARNER_LVL )  // TP ist Magier.
+  {
+    tell_room(ETO, BS("Tut mir leid, "+anrede()+". An Magier liefern wir nichts. "
+      +"Das ist ein Prinzip des Hauses, und Prinzipien sind dazu da, dass "
+      +"sie eingehalten werden. ",78, Name(WER)+" sagt: "));
+    return 1;
+  }
+  else  // TP ist Spieler, kein Seher oder Magier.
+  {
+    tell_room(ETO, BS("Tut mir leid, "+anrede()+". Wir liefern nur an Seher. "
+      +"Aber da ich Sie als strebsame und erfolgreiche Person ansehe, "
+      +"bin ich sicher, dass wir uns bald wiedersehen!",78, Name(WER)+" sagt: "));
+    return 1;
+  }
+}
diff --git a/d/seher/haeuser/moebel/vitrine.c b/d/seher/haeuser/moebel/vitrine.c
new file mode 100644
index 0000000..ae5bb96
--- /dev/null
+++ b/d/seher/haeuser/moebel/vitrine.c
@@ -0,0 +1,339 @@
+/************************************************************************************
+Vitrine fuer die Pokale
+Autor: Miril
+letzte Aenderung:
+05.09.2011
+************************************************************************************/
+
+#include <properties.h>
+#include <defines.h>
+#include <wizlevels.h>
+#include "/d/ebene/miril/fraternitas/fraternitas.h"
+#include "/d/ebene/miril/fraternitas/trophy.h"
+#pragma strong_types,rtt_checks
+#include "/d/seher/haeuser/moebel/moebel.h"
+#include "/d/seher/haeuser/haus.h"
+
+inherit LADEN("swift_std_container");
+
+string besitzer;
+int staub;
+string *trophynamen;
+
+static string my_long();
+static string staub_descr();
+void GetTrophyDetails();
+string *GetAllTrophyNames();
+void NeueDetails();
+
+protected void create()
+{
+  if (!clonep(this_object())){
+    set_next_reset(-1);
+    return;
+  }
+  set_next_reset(86400);
+  ::create();
+  besitzer="";
+  staub=0;
+  SetProp(P_NAME,"Vitrine");
+  SetProp(P_SHORT,"Eine Vitrine");
+  Set(P_LONG,#'my_long,F_QUERY_METHOD);
+  SetProp(P_GENDER,FEMALE);
+  SetProp(P_MATERIAL,([MAT_GLASS:50,MAT_EBONY:50]));
+  SetProp(P_VALUE,10000);
+  SetProp(P_WEIGHT,500000);
+  SetProp(P_MAX_OBJECTS,0);
+  SetProp(P_MAX_WEIGHT,0);
+  SetProp(H_FURNITURE,1);
+  SetProp(P_NOGET,"Die Vitrine ist viel zu schwer.\n");
+  SetProp("cnt_version_obj",2);
+  GetTrophyDetails();
+  AddId(({"\nmiril_pokal_vitrine","vitrine"}));
+
+  NeueDetails();
+
+  AddCmd(({"saeubere","saeuber","reinige","reinig","mach","mache"}),
+           "saeuber_cmd");
+
+  AddCmd(({"stelle","stell"}),"stell_cmd");
+  RemoveCmd(({"serlaube"}));
+
+}
+
+void reset(){
+  ++staub;
+  set_next_reset(86400);
+  ::reset();
+  return;
+}
+
+void SetBesitzer(string uid,string uuid){
+  besitzer=uuid;
+  GetTrophyDetails();
+  return;
+}
+
+string QueryBesitzer(){
+  return besitzer;
+}
+
+void NeueDetails(){
+  AddDetail(({"holz","ebenholz"}),BS("Die Vitrine besteht teilweise "
+    "aus Ebenholz. Tueren, Deckel und Einlegeboeden sind aus Glas."));
+  AddDetail(({"tueren","tuer","glastueren","glastuer","deckel"}),BS(
+            "Durch das Glas kannst Du ins Innere der Vitrine gucken."));
+  AddDetail(({"inneres","gegenstaende","gegenstand"}),
+            BS("Dort kann man Pokale hineinstellen, aber nicht wieder "
+            "herausnehmen."));
+  AddDetail(({"glas","scheibe","scheiben"}),
+     BS("Glas ist praktisch, solange es sauber ist: "
+        "Man kann dadurch ins Innere schauen."));
+  AddDetail(({"reihe","platz","einlegeboeden","einlegeboden","boeden",
+              "boden"}),
+           BS("Die vielen Boeden bieten Platz fuer viele Pokale!"));
+  return;
+}
+
+
+static string my_long(){
+  if(staub<21)
+  return BS(
+  "Die schlichte Vitrine aus dunklem Holz eignet sich hervorragend, um "
+  "wertvolle Gegenstaende darin auszustellen. Hinter den beiden Glastueren "
+  "siehst Du eine Reihe von Einlegeboeden, die ebenfalls aus Glas bestehen. "+
+  staub_descr());
+  else return BS(staub_descr());
+}
+
+
+static string staub_descr(){
+  string text;
+  text="";
+  switch(staub){
+    case 0..1:
+      text=
+        "Die Vitrine ist hervorragend gepflegt. Du siehst keinerlei Staub "+
+        "darin, und die Scheiben sind voellig klar.\n";
+        AddDetail(({"staub"}),BS("Keiner zu sehen."));
+    break;
+    case 2..4:
+      text=
+        "Die Vitrine ist gut gepflegt. Es liegt kaum Staub darin, und die "+
+        "Tueren sind klar.\n";
+        AddDetail(({"staub"}),BS("Man sieht nur wenig davon."));
+    break;
+    case 5..7:
+      text=
+        "Die Vitrine ist in einem ordentlichen Zustand, allerdings sammelt "+
+        "sich so langsam Staub auf den Einlegeboeden.\n";
+        AddDetail(({"staub"}),BS("So langsam koennte man die "
+        "Vitrine saeubern!"));
+        AddDetail(({"zustand"}),BS("Noch ist er ordentlich."));
+    break;
+    case 8..10:
+      text=
+        "Die Vitrine wirkt schon etwas staubig. Man erkennt auch, dass "+
+        "der ein oder andere Fingerabdruck die Tueren ziert.";
+        AddDetail(({"staub","fingerabdruck","tueren","glastueren",
+        "deckel","glastuer","tuer","zustand"}),
+        BS("Es lohnt sich jetzt schon, die Vitrine zu saeubern."));
+    break;
+    case 11..15:
+      text=
+        "Du hast den Eindruck, dass die Vitrine langsam einmal gesaeubert "+
+        "werden koennte. Die Einlegeboeden sind staubig und zahlreiche "+
+        "Fingerabdruecke sind auf den Glastueren zu sehen.";
+    break;
+    case 16..20:
+      text=
+        "Die Vitrine macht einen recht ungepflegten Eindruck. Innen ist "+
+        "sie schon sehr verstaubt und auch die Tueren sind schon recht "+
+        "dreckig geworden.";
+        AddDetail(({"staub"}),BS("Nun wird es aber wirklich Zeit, die "
+        "Vitrine zu saeubern. Sonst sieht man bald nichts mehr darin."));
+    break;
+    case 21..25:
+      text=
+        "Die Vitrine ist total zugestaubt. Ueber den Glastueren sind "+
+        "erste Spinnweben zu erkennen und die Scheiben sind schon fast "+
+        "blind von all den Fingerabdruecken unaufmerksamer Gaeste.";
+         RemoveDetail(m_indices(QueryProp(P_DETAILS)));
+         AddDetail(({"spinnweben","dreck","vitrine","glastueren","glastuer",
+         "tueren","tuer","scheibe","scheiben","deckel"}),
+         "Unter dem ganzen Dreck ist leider nichts mehr zu erkennen.\n");
+         AddDetail(({"gaeste","gast","fingerabdruck","fingerabdruecke"}),
+         "Die Gaeste sind sicher schuld an dem Dreck.\n");
+    break;
+    case 26..30:
+      text=
+        "Du kannst die Vitrine unter der dicken Staubschicht kaum noch "+
+        "erkennen und die Glastueren sind blind geworden.";
+         AddDetail(({"staubschicht","schicht"}),
+         BS("Die ist verdammt dick und undurchsichtig."));
+    break;
+    default:
+      text=
+        "Dass sich unter dieser Ansammlung von Spinnweben und Staub noch "+
+        "eine Vitrine mit Glastueren verbergen soll, kannst Du kaum glauben. "+
+        "Jedenfalls kann man durch die voellig blinden Scheiben nichts "+
+        "mehr erkennen.";
+      AddDetail(({"dreck","spinnweben","staub","ansammlung"}),"Pfui Deibel!\n");
+  }
+  return text;
+}
+
+static int saeuber_cmd(string str){
+  string text;
+  if(!str) return 0;
+  if(strstr(str,"vitrine")<0) return 0;
+  switch(staub){
+    case 0:
+      write("Das ist noch nicht noetig!\n");
+      return 1;
+    break;
+    case 1..20:
+      text="Du reinigst die Vitrine gruendlich. Das wurde auch langsam "
+      "Zeit!";
+      if(getuuid(TP)!=besitzer)
+        text+="Du fragst Dich, wieso Du fremde Moebel reinigst.";
+
+      write(BS(text));
+      say(BS(TPN+" reinigt die Vitrine gruendlich. Das wurde auch langsam "
+      "Zeit!\n"),TP);
+      staub=0; //Hier darf noch jemand helfen!
+    break;
+    case 21..30:
+      text="Du beginnst die Vitrine zu reinigen. ";
+      if(getuuid(TP)!=besitzer){
+        text+="Nach einiger Zeit fragst Du Dich, ob Du eigentlich spinnst, "+
+        "denn das ist ueberhaupt nicht Deine Vitrine. Du laesst von dem "+
+        "Vorhaben wieder ab.";
+        say(BS(TPN+" faengt kurz an, die Vitrine zu reinigen, laesst es aber "
+        "schnell wieder sein."),TP);
+      }
+      else{
+        text+="Das dauert eine ganze Weile, aber dann strahlt die Vitrine "
+        "wieder.";
+        say(BS(TPN+" beginnt die Vitrine zu reinigen. Das dauert eine ganze "
+        "Weile, aber dann strahlt sie wieder."),TP);
+        staub=0;
+      }
+      write(BS(text));
+    break;
+    default:
+      if(getuuid(TP)!=besitzer)
+        write("Das dreckige Teil fasst Du nicht an!\n");
+      else{
+        write(BS(
+          "Du schrubbst und schrubbst und es scheint kein Ende zu nehmen. "
+          "Als Du schon langsam aufgeben willst, ist so langsam ein kleiner "
+          "Erfolg zu sehen. Du nimmst Dir vor, die Vitrine in Zukunft "
+          "haeufiger zu reinigen!"));
+        say(BS(
+          TPN+" schrubbt stundenlang an der Vitrine rum, bis sie endlich "
+          "wieder richtig sauber ist."),TP);
+        staub=0;
+      }
+  }
+  if(staub==0){
+    RemoveDetail(m_indices(QueryProp(P_DETAILS)));
+    GetTrophyDetails();
+    NeueDetails();
+   }
+  return 1;
+}
+
+void GetTrophyDetails(){
+  string *trophyliste,*shorts;
+  mapping trophydetails;
+
+  shorts=({});
+
+  trophyliste=MIRIL_TROPHYMASTER->GetPlacedTrophies(besitzer);
+
+  foreach( string tr : trophyliste )
+    shorts+=({ MIRIL_TROPHYMASTER->GetTrophyShort(tr) });
+
+  shorts = sort_array(shorts, #'>);
+  if(!sizeof(shorts))
+    AddDetail(({"pokale","pokal","in vitrine"}),
+                "Bislang ist die Vitrine noch leer.\n");
+  else
+  AddDetail(({"pokale","pokal","in vitrine"}),
+    "Du siehst folgende Pokale in der Vitrine:\n"
+    +implode(shorts,".\n")+".\n");
+
+  foreach( string tr : trophyliste )
+  {
+    AddDetail( MIRIL_TROPHYMASTER->GetTrophyIds(tr),
+               BS(MIRIL_TROPHYMASTER->GetTrophyLong(tr)));
+
+    trophydetails = MIRIL_TROPHYMASTER->GetTrophyDetails(tr);
+    if ( !sizeof(trophydetails) )
+      continue;
+    foreach ( mixed det, string det_desc : trophydetails )
+      AddDetail( det, BS(det_desc) );
+  }
+  return;
+}
+
+string *GetAllTrophyNames(){
+  int i,anzahl;
+  string *trophynamen;
+
+  trophynamen=({});
+
+  foreach(string bla:MIRIL_TROPHYMASTER->GetTrophyListe())
+    trophynamen+=MIRIL_TROPHYMASTER->GetTrophyIds(bla);
+
+  return trophynamen;
+}
+
+static int stell_cmd(string str){
+  string was,identifier;
+  int resultat;
+  object ob;
+  if(!str) return 0;
+  if(strstr(str,"vitrine")<0) return 0;
+  notify_fail("Das ist nicht Deine Vitrine!\n");
+  if(getuuid(TP)!=besitzer)
+    return 0;
+  notify_fail("Die Syntax ist: stelle <gegenstand> in vitrine!\n");
+  if(sscanf(str,"%s in vitrine",was)!=1)
+    return 0;
+
+  notify_fail("Die Vitrine sollte schon offen sein.\n");
+  if(QueryProp(P_CNT_STATUS)!=CNT_STATUS_OPEN && !IS_LEARNER(TP))
+    return 0;
+  notify_fail("Du solltest die Vitrine vorher erstmal saeubern!\n");
+  if(staub>20)
+    return 0;
+  notify_fail("Das kannst Du leider nicht in die Vitrine stellen!\n");
+  if(member(GetAllTrophyNames(),lower_case(was))<0
+     && lower_case(was)!="pokal")
+    return 0;
+  notify_fail("Das hast Du nicht!\n");
+  if(!ob=present(was,TP))
+    return 0;
+  notify_fail("Das kannst Du leider nicht in die Vitrine stellen!\n");
+  if(!ob->id("\nmiril_pokal"))
+    return 0;
+
+  identifier=ob->QueryIdentifier();
+  resultat=MIRIL_TROPHYMASTER->PlaceTrophy(getuuid(TP),identifier);
+
+  notify_fail("Hier stimmt etwas nicht, sag bitte einem Erzmagier Bescheid! "
+  "Resultat="+resultat+"\n");
+  if(resultat!=1)
+    return 0;
+  write(BS("Du stellst den Pokal in die Vitrine und bewunderst ihn noch ein "
+  "wenig.\n"));
+  say(TPN+" stellt einen Pokal in die Vitrine.\n",TP);
+  GetTrophyDetails();
+  ob->remove();
+  if(ob)
+    destruct(ob);
+  return 1;
+}
+
diff --git a/d/seher/haeuser/moebel/waffenschrank.c b/d/seher/haeuser/moebel/waffenschrank.c
new file mode 100644
index 0000000..e36abc9
--- /dev/null
+++ b/d/seher/haeuser/moebel/waffenschrank.c
@@ -0,0 +1,220 @@
+//--------------------------------------------------------------------------------
+// Name des Objects:    Waffenschrank
+// Letzte Aenderung:    22.03.2001
+// Magier:              Swift
+//--------------------------------------------------------------------------------
+/* Changelog
+   * 21.05.2007, Zesstra
+     Kampfstaebe auf Hinweis von tassram ergaenzt.
+*/
+#pragma strong_types,rtt_checks
+
+#include "schrankladen.h"
+#include <ansi.h>
+#include <class.h>
+inherit LADEN("swift_std_container");
+
+#define VERSION_OBJ "6"
+
+string strall;
+
+protected void create()
+{
+  if (!clonep(TO)) return;
+  swift_std_container::create();
+  SetProp(P_SHORT, "Ein Waffenschrank");
+  SetProp(P_LONG, BS(
+     "Mit den Waffen, die in diesen massiven Holzschrank passen, koenntest "
+    +"Du ein ganzes Soeldnerheer ausruesten. Fuer jede Waffengattung gibt "
+    +"es einen eigenen Platz, damit man auch alles gleich findet, sollte "
+    +"man es brauchen.")+"@@cnt_status@@");
+  AddId(({"waffenschrank", "holzschrank", "schrank"}));
+  SetProp("cnt_version_obj", VERSION_OBJ);
+  SetProp(P_NAME, "Waffenschrank");
+  SetProp(P_GENDER, MALE);
+  SetProp(P_WEIGHT, 5000);         // Gewicht 5 Kg
+  SetProp(P_MAX_WEIGHT, 1000000);  // Es passen fuer 1000 kg Sachen rein.
+  SetProp(P_WEIGHT_PERCENT, 100);  // Dafuer macht er auch nix leichter :)
+  SetProp(P_MAX_OBJECTS, 100);     // Mehr sollte nicht sein, lt. Tiamak.
+  SetProp(P_VALUE, 0);             // Kein materieller Wert. Ist eh nicht verkaufbar.
+  SetProp(P_NOBUY, 1);             // Wird im Laden zerstoert, falls er verkauft wird.
+  SetProp(P_NOGET, "Das geht nicht. "+Name(WER,1)+" haftet wie magisch am Boden.\n");
+  SetProp(P_MATERIAL, ({MAT_MISC_WOOD, MAT_MISC_MAGIC}) );
+  SetProp(P_INFO, "Versuchs mal mit: \"skommandos "+QueryProp(P_IDS)[1]+"\" !\n");
+  SetProp("obj_cmd", "sliste [Objekt-Id] [Waffentyp|\"alles\"]\n"
+    +"  Waffentypen: Schwerter, Speere, Aexte, Keulen, Kampfstaebe, Messer, Peitschen,\n"
+    +"               Fernwaffen, Munition, Sonstiges, Unzuordbar\n");
+
+  AD(({"platz"}), BS("Der Schrank bietet Platz fuer jede erdenkliche "
+    +"Waffengattung."));
+
+  AddCmd(({"sliste"}), "auflistung");
+}
+
+varargs int PreventInsert(object ob)
+{
+  // Keine Waffe? Hat in diesem Container nix verloren!
+  if( !ob->QueryProp(P_WEAPON_TYPE) && !ob->QueryProp(P_WC) &&
+      !ob->id("\nBumerang") && !ob->is_class_member(CL_AMMUNITION) &&
+      !ob->id("\ngorseilpfeil") )
+  {
+    write( BS("In "+name(WEN,1)+" kannst Du nur Waffen + Munition legen!"));
+    return 1;
+  }
+  else
+    return ::PreventInsert(ob);
+}
+
+int auflistung2(string was, string nf_str1, string nf_str2, int alles)
+{
+  string obshort, suche, *strs;
+  object *obs;
+  int i;
+  mapping suchobs;
+  switch(was)
+  {
+    case "munition"   : suche=WT_AMMU; break;
+    case "aexte"      : suche=WT_AXE; break;
+    case "keulen"     : suche=WT_CLUB; break;
+    case "messer"     : suche=WT_KNIFE; break;
+    case "fernwaffen" : suche=WT_RANGED_WEAPON; break;
+    case "speere"     : suche=WT_SPEAR; break;
+    case "schwerter"  : suche=WT_SWORD; break;
+    case "peitschen"  : suche=WT_WHIP; break;
+    case "sonstiges"  : suche=WT_MISC; break;
+    case "kampfstaebe": suche=WT_STAFF; break;
+    case "unzuordbar" : suche="unzuordbar"; break;
+    default           : write("Fehler: Ungueltiger Waffentyp. "
+                             +"Folgende Typen gibt es:\n"+nf_str1+nf_str2);
+                        return 1; break;
+  }
+  obs=all_inventory();
+  suchobs=([]);
+  for(i=0;i<sizeof(obs);i++)
+  {
+    obshort=to_string(obs[i]->QueryProp(P_SHORT));
+    if(obshort=="Ein Bumerang@@fliegt@@")
+      obshort="Ein Bumerang";
+    else if(obshort=="Nichts besonderes" || obshort=="0") // keine P_SHORT ?
+      obshort=obs[i]->Name(WER);     //   Hoffen wir mal dass das Obj. nen Namen hat.
+    if(obs[i]->QueryProp(P_WEAPON_TYPE)==suche ||  // Gesuchter WeaponType gefunden...
+       (!obs[i]->QueryProp(P_WEAPON_TYPE) && suche=="unzuordbar") )
+    {
+      if(suchobs[obshort])                         // P_SHORT des Obj. schon im mapping?
+      {
+        if( obs[i]->QueryProp(P_AMOUNT) )
+          suchobs[obshort]+=obs[i]->QueryProp(P_AMOUNT); //   Dann den Zaehler um Amount hoch!
+        else
+          suchobs[obshort]+=1;                     //   Dann den Zaehler um 1 hoch!
+      }
+      else
+      {
+        if( obs[i]->QueryProp(P_AMOUNT) )
+          suchobs+=([obshort: obs[i]->QueryProp(P_AMOUNT)]);
+        else
+          suchobs+=([obshort: 1]);
+      }
+    }
+  }
+  strs=m_indices(suchobs);
+  if(sizeof(strs))
+  {
+    if(!alles)
+    {
+      if(suche=="unzuordbar")
+        strall+=Name(WER,1)+" enthaelt folgende nicht zuordbare Waffen:\n";
+      else
+        strall+=Name(WER,1)+" enthaelt folgende "+CAP(was)+":\n";
+      strall+="------------------------------------------------------------\n";
+    }
+    else
+    {
+      if(suche=="unzuordbar")
+        strall+=ANSI_BOLD+"=== Nicht zuordbare Waffen:\n"+ANSI_NORMAL;
+      else
+        strall+=ANSI_BOLD+"=== "+CAP(was)+":\n"+ANSI_NORMAL;
+    }
+    for(i=0;i<sizeof(strs);i++)
+    {
+      if(suchobs[strs[i]] > 1)
+        strall+=strs[i]+". ("+suchobs[strs[i]]+")\n";
+      else
+        strall+=strs[i]+".\n";
+    }
+  }
+  else
+    if(!alles)
+      strall+=Name(WER,1)+" enthaelt keine "+CAP(was)+"!\n";
+  return 1;
+}
+
+int auflistung(string str)
+{
+  string *strs, ob_id, was, nf_str1,nf_str2;
+  strall="";
+  nf_str1="   (Schwerter, Speere, Aexte, Keulen, Kampfstaebe, Messer, Peitschen,\n"
+         +"    Fernwaffen, Munition, Sonstiges, Unzuordbar)\n";
+  nf_str2="Syntax: sliste [Objekt-Id] [Waffentyp]\n"
+         +"Bsp.:   sliste "+QueryProp(P_IDS)[1]+" "+"schwerter\n"
+         +"        sliste "+QueryProp(P_IDS)[1]+" alles\n";
+  notify_fail("Fehler: Ohne Parameter klappt das nicht.\n"+nf_str2);
+  if(!str) return 0;
+  if(present(str)==TO)   // Ueberpruefe, ob dieses Objekt gemeint ist!
+  {
+    write("Fehler: Es fehlt ein Waffentyp. Folgende Typen gibt es:\n"
+         +nf_str1+nf_str2);
+    return 1;
+  }
+  strs=old_explode(str, " ");
+  notify_fail("Fehler: Du musst eine gueltige Objekt-Id angeben!\n"
+             +nf_str2);
+  if( sizeof(strs) < 2 ) return 0;   // Nur 1 Par. und der ist nicht die Objekt-Id
+  if( sizeof(strs) == 2 )   // Anzahl Par. = 2
+  {
+    ob_id=strs[0];
+    was=strs[1];
+    if( IST_ZAHL(was) )     // Objekt-Id z.B. mit "schrank 2" angesprochen?
+      if(present(ob_id+" "+was)==TO)   // Falls dieses Objekt gemeint ist und kein 3. Par!
+      {
+        write("Fehler: Es fehlt ein Waffentyp. Folgende Typen gibt es:\n"
+              +nf_str1+nf_str2);
+        return 1;
+      }
+      else
+        return 0;
+  }
+  else if( sizeof(strs) == 3 )
+  {
+    ob_id=strs[0]+" "+strs[1];
+    was=strs[2];
+  }
+  else        // Anzahl erforderlicher Parameter ueberschritten!
+    return 0;
+  if(present(ob_id)!=TO)   // Ueberpruefe, ob auch dieses Objekt gemeint ist!
+    return 0;
+  if(QueryProp(P_CNT_STATUS)!=CNT_STATUS_OPEN)
+  {
+    write("Dazu muesste "+name(WER,1)+" geoeffnet sein.\n");
+    return 1;
+  }
+//--- Hier ist Parameterpruefung zu Ende.
+  was=LOWER(was);
+  if(was!="alles")
+    auflistung2(was, nf_str1, nf_str2, 0);
+  else
+  {
+    auflistung2("aexte", nf_str1, nf_str2, 1);
+    auflistung2("keulen", nf_str1, nf_str2, 1);
+    auflistung2("kampfstaebe", nf_str1, nf_str2, 1);
+    auflistung2("messer", nf_str1, nf_str2, 1);
+    auflistung2("speere", nf_str1, nf_str2, 1);
+    auflistung2("schwerter", nf_str1, nf_str2, 1);
+    auflistung2("peitschen", nf_str1, nf_str2, 1);
+    auflistung2("fernwaffen", nf_str1, nf_str2, 1);
+    auflistung2("munition", nf_str1, nf_str2, 1);
+    auflistung2("sonstiges", nf_str1, nf_str2, 1);
+    auflistung2("unzuordbar", nf_str1, nf_str2, 1);
+  }
+  TP->More(strall);
+  return 1;
+}
diff --git a/d/seher/haeuser/moebel/waffentruhe.c b/d/seher/haeuser/moebel/waffentruhe.c
new file mode 100644
index 0000000..098aaa7
--- /dev/null
+++ b/d/seher/haeuser/moebel/waffentruhe.c
@@ -0,0 +1,43 @@
+//--------------------------------------------------------------------------------
+// Name des Objects:    Waffentruhe
+// Letzte Aenderung:    22.03.2001
+// Magier:              Swift
+//--------------------------------------------------------------------------------
+/* Changelog
+   * 21.05.2007, Zesstra
+     Da Waffenschrank und Waffentruhe sich praktisch nicht unterscheiden, bis
+     auf 10 Zeilen im Create, erbt nun die Waffentruhe den Waffenschrank und
+     ueberschreibt einfach die passenden Props.
+*/
+#pragma strong_types,rtt_checks
+
+#include "schrankladen.h"
+#include <ansi.h>
+#include <class.h>
+//inherit LADEN("swift_std_container");
+inherit LADEN("waffenschrank");
+
+#define VERSION_OBJ "7"
+
+protected void create() {
+  if (!clonep(TO)) return;
+  ::create();
+  SetProp(P_SHORT, "Eine Waffentruhe");
+  SetProp(P_LONG, BS(
+     "Diese Stahltruhe ist speziell zur Aufnahme von grossen Waffenmengen "
+     "gefertigt. Verschiedene Faecher fuer die einzelnen Waffentypen erleichtern "
+     "die Suche nach Deinem bevorzugten Waffentyp.")+"@@cnt_status@@");
+  RemoveId(({"waffenschrank", "holzschrank", "schrank"}));
+  AddId(({"waffentruhe", "stahltruhe", "truhe"}));
+  SetProp("cnt_version_obj", VERSION_OBJ);
+  SetProp(P_NAME, "Waffentruhe");
+  SetProp(P_GENDER, FEMALE);  
+  SetProp(P_MATERIAL, ({MAT_MISC_METAL, MAT_MISC_MAGIC}) );
+  SetProp(P_INFO, "Versuchs mal mit: \"skommandos "+QueryProp(P_IDS)[1]+
+    "\" !\n");
+  AD(({"faecher"}), BS("Fuer jeden Waffentyp gibt es ein eigenes Fach, so dass "
+    "Du eine bessere Uebersicht hast."));
+  AD(({"platz"}), BS("Die Waffentruhe bietet Platz fuer jede erdenkliche "
+	"Waffengattung."));
+}
+
diff --git a/d/seher/haeuser/moebel/wasch.c b/d/seher/haeuser/moebel/wasch.c
new file mode 100644
index 0000000..7789350
--- /dev/null
+++ b/d/seher/haeuser/moebel/wasch.c
@@ -0,0 +1,220 @@
+// Name des Objects:    Waschobjekt
+// Letzte Aenderung:    01.04.2005
+// Magier:              Seleven
+// Dieses File gibt dem Spieler die Moeglichkeit, eine Waschgelegenheit in
+// seinem Seherhaus aufzustellen. Das beim Kommando wasch(e), dusch(e) laesst
+// sich die Medung ueberschreiben (Test per raum->QueryProp("h_commands"))
+// 01.07.2007 (Zesstra): GetOwner() definiert.
+//----------------------------------------------------------------------------
+#pragma strong_types,rtt_checks
+
+#include "schrankladen.h"
+inherit LADEN("swift_std_container");
+
+string *wcmd;
+string *objekte =
+  (({"\nstinkobj","\nzesstra_asche","seleve\nscheisse","\npopc",
+     "\nsspbollen","seleve\nstinkobj","\nq2p_gestank","ber\tram_skot",
+     "bambi\nschmutzigehaende"}));
+/* Wurzel(Klo/Imbiss), Zesstra(Vulkan/Illuminatos), Seleven(Klo/Nebelelfen),
+ * Seleven(Popcorn/Nebelelfen), Boing(Schleimschmeisser,SSP), STANDART
+ */
+
+static void wasch_fun();
+
+protected void create()
+{
+  if (!clonep(this_object())) return;
+  ::create();
+
+  wcmd = (({"wasche","wasch","dusche","dusch"}));
+  AddId(({"duschkabine","kabine","dusche","waschgelegenheit"}));
+  SetProp(P_NAME,"Duschkabine");
+  
+  SetProp("cnt_version_obj",1);
+
+  SetProp("obj_cmd",
+  "wasch(e), dusch(e)\n"+
+  "   Damit laesst sich das Stinken aus dem Imbissklo beseitigen.\n"+
+  "   Wenn kein Befehl 'wasch(e)' im Raum beschrieben ist, erfolgt eine\n"+
+  "   Standartmeldung, selbiges gilt fuer 'dusch(e)'.\n"+
+  "ssetz(e) waschbefehl\n"+
+  "   Damit kann man die Befehlsliste erweitern, die das Waschen \n"+
+  "   ausloesen\n"+
+  "sloesch(e) waschbefehl\n"+
+  "   Damit kann man einen Befehl aus der Liste loeschen\n"+
+  "waschbefehlslite, wbl"+
+  "   Zeigt eine Liste der Befehle an, die das Waschen ausloesen.\n");
+
+  SetProp(P_SHORT,"Eine Duschkabine");
+  SetProp(P_LONG,BS("Die Duschkabine hat einen Rahmen aus hellem Holz. "
+   "Dazwischen wurden matte Scheiben eingelassen, damit man niemanden beim "
+   "Duschen beobachten kann."));
+  AddDetail("rahmen","Der Rahmen ist aus hellem Holz.\n");
+  AddDetail(({"scheiben","scheibe"}),"Die Scheiben der Duschkabine sind "+
+   "matt und absolut undurchsichtig!\n");
+  AddDetail(({"duschen","beim duschen"}),
+   "Man kann niemanden beim Duschen beobachten.\n");
+
+  SetProp(P_GENDER, FEMALE);
+  SetProp(P_WEIGHT, 5000);         // Gewicht 5 Kg
+  SetProp(P_MAX_WEIGHT, 0);        // Soll nur n pseudo-Container
+  SetProp(P_WEIGHT_PERCENT, 100);  // Dafuer macht er auch nix leichter :)
+  SetProp(P_MAX_OBJECTS, 0);       // Kein Container :)
+  SetProp(P_VALUE, 0);             // Ist eh nicht verkaufbar.
+  SetProp(P_NOBUY, 1);             // Fals doch: zerstoeren!
+  SetProp(P_NOGET,
+    "Das geht nicht. "+Name(WER,1)+" haftet wie magisch am Boden.\n");
+  SetProp(P_MATERIAL, ({MAT_MISC_WOOD, MAT_MISC_MAGIC}) );
+  SetProp(P_INFO, "Versuchs mal mit: \"skommandos "+QueryProp(P_IDS)[1]+"\" !\n");
+
+  AddCmd(wcmd,"cmd_waschen");
+  RemoveCmd(({"oeffne","oeffn","schliesse","schliess"}));
+  AddCmd(({"ssetze","ssetz"}),"cmd_setzen");
+  AddCmd(({"sloesche","sloesche"}),"cmd_loeschen");
+  AddCmd(({"wbl","waschbefehlsliste"}),"liste");
+}
+
+// Zesstra, 1.7.07, fuers Hoerrohr
+string GetOwner() {return "seleven";}
+
+varargs int PreventInsert(object ob) {return 1;} //Das ist kein Container :)
+
+static void wasch_fun()
+{
+  int i;
+  object ob;
+  i = sizeof(objekte);
+  i--;
+  while(i > -1)
+  {
+
+    if(!TP) return;
+    ob = present(objekte[i],TP);
+    while(ob)
+    {
+      if(query_once_interactive(ob))
+	  {
+	    tell_object(TP,BS("Du scheinst jemanden in Deinem Inv zu haben!\n"
+	     "Das sollte sich vielleicht ein Magier anschauen."));
+	    i--;
+	    return;
+      }
+      ob->remove(1);
+      if(present(objekte[i],TP));
+       ob = present(objekte[i],TP);
+    }
+    i--;
+
+  }
+}
+
+int cmd_waschen(string str)
+{
+  string verb;
+  verb = query_verb();
+  if(!environment()) return 0;
+  if( !erlaubt() )
+  {
+      write("Du solltest den Besitzer vielleicht um Erlaubnis bitten.\n");
+      return 1;
+  }
+  if(member(environment()->QueryProp("h_commands"),verb) == 0)
+  {
+    write(
+     "Du springst schnell unter die Dusche und waeschst Dich gruendlich.\n");
+    say(this_player()->Name(WER)+" springt schnell unter die Dusche.\n");
+    wasch_fun();
+    return 1;
+  }
+  wasch_fun();
+  return 1;
+}
+
+
+static int cmd_setzen(string str)
+{
+  string bef;
+  notify_fail("Moechtest Du einen Waschbefehl setzen?\n"+
+    "Syntax: ssetz(e) waschbefehl [befehl]\n");
+  if(!str || !stringp(str) || sizeof(str) == 0) return 0;
+  sscanf(str,"waschbefehl %s",bef);
+  if(!bef) return 0;
+  if(bef[sizeof(bef) .. sizeof(bef)-1] == "e")
+   bef = bef[sizeof(bef) .. sizeof(bef)-2];
+  notify_fail("Der Befehl steht schon auf der Liste.\n");
+  if(member(wcmd,bef) != -1) return 0;
+  wcmd += (({bef,bef+"e"}));
+  AddCmd(wcmd,"cmd_waschen");
+  write(BS("Du hast die Befehle "+bef+" und "+bef+"e an die Liste "
+   "angefuegt."));
+  return 1;
+}
+
+static int cmd_loeschen(string str)
+{
+  string bef;
+  notify_fail("Moechtest Du einen Waschbefehl loeschen?\n"+
+    "Syntax: sloesch(e) waschbefehl [befehl]\n");
+  if(!str || !stringp(str) || sizeof(str) == 0) return 0;
+  sscanf(str,"waschbefehl %s",bef);
+  if(!bef) return 0;
+  notify_fail("Der Befehl steht gar nicht auf der Liste.\n");
+  if(member(wcmd,bef) == -1) return 0;
+  wcmd -= (({bef}));
+  RemoveCmd(bef);
+  write(BS("Du hast die Befehle "+bef+" und "+bef+"e von der Liste "
+   "entfernt."));
+  return 1;
+}
+
+static int liste(string str)
+{
+  write("Du hast folgende Befehle auf der Waschliste stehen:\n"+
+   break_string(implode(wcmd,", "),78,3));
+  return 1;
+}
+
+
+
+// oeffnen und schliessen ausbauen.
+varargs int skommandos(string str)
+{
+  notify_fail( "Fehler: Dieser Befehl benoetigt eine gueltige Objekt-Id als Parameter.\n"
+    +"Beispiel: skommandos "+QueryProp(P_IDS)[1]+"\n");
+  if(!str) return 0;
+  if(present(str)!=TO ) // Bin ich gemeint?
+    return 0;
+  write("=============================================================================\n");
+  write("Aktuelle Version: "+QueryProp("cnt_version_std")+QueryProp("cnt_version_obj")+"\n");
+  write( BS(Name(WER,1)+" kann nur in diesem Seherhaus verwendet werden, "
+    +"da "+QueryPronoun(WER)+" speziell dafuer gekauft wurde. "+CAP(QueryPronoun(WER))
+    +" verfuegt ueber folgende Kommandos:")
+    +"-----------------------------------------------------------------------------\n"
+    +"serlaube [Objekt-Id] [Spielername|\"hausfreunde\"|\"zweities\"]\n"
+    +"  Erlaubt Personen, "+name(WEN,1)+" mitzubenutzen.\n"
+    +"  serlaube + Objekt-Id (ohne Spielername/hausfreunde)\n"
+    +"  listet alle Personen mit Zugriff auf "+name(WEN,1)+"\n\n"
+    +"verschiebe [Objekt-Id] nach [Ausgang]\n"
+    +"  Damit kannst Du "+name(WEN,1)+" innerhalb Deines Seherhauses verschieben.\n\n"
+  //Seleven 07.12.2005
+    +"sverstecke [Objekt-Id]\n"
+    +"  Damit machst Du "+name(WEN,1)+" unsichtbar.\n"
+    +"shole [Objekt-Id] hervor\n"
+    +"  Damit machst Du "+name(WEN,1)+" wieder sichtbar.\n"
+  // Bis hier
+    +"zertruemmer [Objekt-Id]\n"
+    +"  Damit zerstoerst Du "+name(WEN,1)+".\n\n");
+
+
+  if( QueryProp("obj_cmd") )
+    write( QueryProp("obj_cmd")+"\n" );
+
+  write("[Objekt-Id] muss eine gueltige Id sein, in diesem Fall z.B. "
+      +QueryProp(P_IDS)[1]+"\n");
+  write("=============================================================================\n");
+
+
+  return 1;
+}
+
diff --git a/d/seher/haeuser/moebel/zauberkiste.c b/d/seher/haeuser/moebel/zauberkiste.c
new file mode 100644
index 0000000..ecf6f74
--- /dev/null
+++ b/d/seher/haeuser/moebel/zauberkiste.c
@@ -0,0 +1,56 @@
+//--------------------------------------------------------------------------------
+// Name des Objects:    Zauberkiste
+// Letzte Aenderung:    10.05.2002
+// Magier:              Vanion
+// Was:                 Die ID fuer die Kompos der Zauberer umgestellt.
+//--------------------------------------------------------------------------------
+#pragma strong_types,rtt_checks
+
+#include "schrankladen.h"
+
+// Fuer die IDs
+#include "/p/zauberer/zauberer.h"
+
+inherit LADEN("swift_std_container");
+
+#define VERSION_OBJ "3"
+
+protected void create()
+{
+  if (!clonep(TO)) return;
+  swift_std_container::create();
+  SetProp(P_SHORT, "Eine Zauberkiste");
+  SetProp(P_LONG, BS(
+     "Eine kleine Kiste aus Birnbaumholz. Da diesem seltenen Holz selbst "
+    +"magische Faehigkeiten nachgesagt werden, ist es wohl das ideale Material, "
+    +"um die teilweise gefaehrlichen Komponenten eines Zauberers darin "
+    +"unterzubringen.")+"@@cnt_status@@");
+  AddId(({"zauberkiste", "kiste"}));
+  SetProp("cnt_version_obj", VERSION_OBJ);
+  SetProp(P_NAME, "Zauberkiste");
+  SetProp(P_GENDER, FEMALE);
+  SetProp(P_WEIGHT, 5000);         // Gewicht 5 Kg
+  SetProp(P_MAX_WEIGHT, 1000000);  // Es passen fuer 1000 kg Sachen rein.
+  SetProp(P_WEIGHT_PERCENT, 100);  // Dafuer macht er auch nix leichter :)
+  SetProp(P_MAX_OBJECTS, 100);     // Mehr sollte nicht sein, lt. Tiamak.
+  SetProp(P_VALUE, 0);             // Kein materieller Wert. Ist eh nicht verkaufbar.
+  SetProp(P_NOBUY, 1);             // Wird im Laden zerstoert, falls er verkauft wird.
+  SetProp(P_NOGET, "Das geht nicht. "+Name(WER,1)+" haftet wie magisch am Boden.\n");
+  SetProp(P_MATERIAL, ({MAT_PEAR_WOOD, MAT_MISC_MAGIC}) );
+  SetProp(P_INFO, "Versuchs mal mit: \"skommandos "+QueryProp(P_IDS)[1]+"\" !\n");
+
+  AD(({"holz", "birnbaumholz"}), BS("Fast koenntest Du meinen, dass "+name(WER,1)
+    +" lebt!"));
+}
+
+varargs int PreventInsert(object ob)
+{
+  // Keine Zauberkompo? Hat in diesem Container nix verloren!
+  if( !ob->id(Z_ID_ZUTAT) )
+  {
+    write( BS("In "+name(WEN,1)+" kannst Du nur Zauberer-Komponenten legen!"));
+    return 1;
+  }
+  else
+    return ::PreventInsert(ob);
+}