Added public files

Roughly added all public files. Probably missed some, though.
diff --git a/items/.readme b/items/.readme
new file mode 100644
index 0000000..29fed4a
--- /dev/null
+++ b/items/.readme
@@ -0,0 +1,4 @@
+In diesem Verzeichnis sollten global (unabhaengig einer Region, Gilde etc.)
+verfuegbare Items angeschlossen werden, welche keine besonderen Rechte
+brauchen. Alle Objekte bekommen die spezielle UID ITEMS, welche einen Level
+von 0 und keine Schreibrechte hat.
diff --git a/items/boerse.c b/items/boerse.c
new file mode 100644
index 0000000..4e1ecce
--- /dev/null
+++ b/items/boerse.c
@@ -0,0 +1,194 @@
+#pragma strong_types,rtt_checks
+
+inherit "/std/container";
+
+#define U_REQ      "u_req"
+
+#include <properties.h>
+#include <language.h>
+#include <defines.h>
+#include <moving.h>
+#include <money.h>
+
+// zum debuggen und extra public
+public string debugmode;
+public string __set_debug(string recv) {return debugmode=recv;}
+#include <living/comm.h>
+#define ZDEBUG(x) if (stringp(debugmode) && find_player(debugmode)) \
+  find_player(debugmode)->ReceiveMsg(x,MT_DEBUG,0,object_name()+": ",ME)
+//#define ZDEBUG(x)
+
+int dontacceptmoney;
+
+protected void create()
+{
+  ::create();
+  SetProp(P_NAME, "Geldboerse");
+  SetProp(P_SHORT, "Eine Geldboerse");
+  SetProp(P_LONG,  "Eine schoene aus Leder gefertigte Geldboerse.\n");
+  SetProp(P_MATERIAL, ([MAT_LEATHER:100]));
+  SetProp(P_GENDER, FEMALE);
+  SetProp(P_VALUE,  80);
+  SetProp(P_WEIGHT, 300);
+  SetProp(P_WEIGHT_PERCENT, 50);
+  SetProp(P_MAX_WEIGHT, 250000); // 1 mio. Muenzen.
+  AddId(({"geldboerse", "boerse", BOERSEID}));
+  SetProp(P_NOINSERT_MSG,
+      "Du kannst immer nur eine Geldboerse gleichzeitig benutzen.\n");
+}
+
+static string _query_keep_on_sell()
+{
+  if (first_inventory() && living(environment()))
+     return getuid(environment());
+  return Query(P_KEEP_ON_SELL);
+}
+
+static int _query_amount()
+{
+  object ob = first_inventory();
+  if (load_name(ob) == GELD)
+    return ob->QueryProp(P_AMOUNT);
+  return 0;
+}
+
+void AddAmount(int am)
+{
+  object ob = first_inventory();
+  if (load_name(ob) == GELD)
+    ob->AddAmount(am);
+}
+
+string short()
+{
+  int i;
+  switch (i=QueryProp(P_AMOUNT)) {
+    case 0:  return "Eine leere Geldboerse.\n";
+    case 1:  return "Eine Geldboerse mit einer Muenze.\n";
+    default: return "Eine Geldboerse mit "+i+" Muenzen.\n";
+  }
+  return 0;
+}
+
+// Geld darf nur rein, wenn diese Boerse schon Geld enthaelt
+// ODER es auch keine andere im lebenden (!) Inventar gibt, die Geld
+// enthaelt.
+private int accept_money()
+{
+  // wenn wir gerade zerstoert werden, ist das hier gesetzt, dann akzeptieren
+  // wir ein Geld. Sonst wurde Geld, was gerade in prepare_destruct()
+  // rausbewegt wurde, evtl. wieder reinbewegt...
+  if (dontacceptmoney)
+    return 0;
+  // Ausserhalb von Livings geht reinstecken von Geld immer.
+  if (!living(environment()))
+    return 1;
+  // wenn in uns Geld ist, auch.
+  object geld = first_inventory();
+  if (geld && load_name(geld) == GELD)
+    return 1; // erlaubt
+  // wir haben kein Geld... Wenn es eine mit Geld im gleichen inv gibt,
+  // nehmen wir keins.
+  object andereboerse = present(GELDBOERSE_MIT_GELD, environment());
+  if (objectp(andereboerse))
+    return 0;
+
+  return 1;
+}
+
+varargs int PreventInsert(object ob)
+{
+  if (ob && load_name(ob)==GELD
+      && accept_money())
+  {
+    return ::PreventInsert(ob);
+  }
+  return 1; // nur geld erlaubt
+}
+
+public void MergeMoney(object geld)
+{
+  if (geld && previous_object() == geld
+      && load_name(geld) == GELD
+      && accept_money())
+  {
+    int fremdamount = geld->QueryProp(P_AMOUNT);
+    // Da wir aus einen NotifyMove (d.h. move()) gerufen werden, darf hier
+    // keinesfalls ein move() gemacht werden.
+    // Wenn in uns Geld ist, prima, einfach P_AMOUNT veraendern.
+    // Wenn nicht, muessen wir ein neues Geldobjekt clonen, falls fremdamount
+    // > 0 ist.
+    object meingeld = first_inventory();
+    if (meingeld && load_name(meingeld) == GELD)
+    {
+      int meinamount = meingeld->QueryProp(P_AMOUNT);
+      ZDEBUG(sprintf("MergeMoney: meinamount: %d, fremdamount: %d\n",
+            meinamount,fremdamount));
+      // wenn fremdamount positiv ist, vereinigen wir uns natuerlich, auch
+      // wenn mein Geld negativ ist. Aber max. 1 Mio. Muenzen aufnehmen.
+      if (fremdamount > 0)
+      {
+        int zubuchen = min(1000000-meinamount, fremdamount);
+        ZDEBUG(sprintf("MergeMoney: zubuchen: %d\n", zubuchen));
+        meingeld->SetProp(P_AMOUNT, meinamount + zubuchen);
+        geld->SetProp(P_AMOUNT, fremdamount - zubuchen);
+        // environment verstaendigen ueber Inventaraenderung... Und uns. Wir
+        // machen nur die beiden, weil alle hoehren Envs nicht so wichtig
+        // sind, dass es sofort gemacht werden muss.
+        environment()->_set_last_content_change();
+        _set_last_content_change();
+      }
+      // ansonsten vereinigen wir uns, wenn meinamount > 0 und fremdamount < 0
+      // ist, aber nur soviel, dass hinterher in mir nix mehr verbleibt.
+      else if (meinamount > 0 && fremdamount < 0)
+      {
+        int amount_to_merge = min(meinamount, abs(fremdamount));
+        ZDEBUG(sprintf("MergeMoney: zubuchen: %d\n", amount_to_merge));
+        meingeld->SetProp(P_AMOUNT, meinamount - amount_to_merge);
+        geld->SetProp(P_AMOUNT, fremdamount + amount_to_merge);
+        // environment verstaendigen ueber Inventaraenderung... Und uns. Wir
+        // machen nur die beiden, weil alle hoehren Envs nicht so wichtig
+        // sind, dass es sofort gemacht werden muss.
+        environment()->_set_last_content_change();
+        _set_last_content_change();
+      }
+      // in anderen Faellen vereinigen wir einfach nicht (beide negativ)
+    }
+    // Ansonsten nehmen wir nur positives Geld und nur, soweit es noch
+    // reinpasst.
+    else if (fremdamount > 0)
+    {
+      ZDEBUG(sprintf("MergeMoney: leere Boerse, fremdamount: %d\n",
+             fremdamount));
+      meingeld = clone_object(GELD);
+      // nocheck, weil wir eigentlich <geld> bewegen wollen und schon
+      // festgestellt haben, dass diese Boerse Geld akzeptiert. Tragen kann
+      // der Spieler es auch (sogar ohne Gewichtsreduktion). Die Boerse soll
+      // max. 1Mio Muenzen aufnehmen.
+      int zubuchen = min(fremdamount,1000000);
+      ZDEBUG(sprintf("MergeMoney: zubuchen: %d\n", zubuchen));
+      meingeld->SetProp(P_AMOUNT, zubuchen);
+      geld->SetProp(P_AMOUNT, fremdamount-zubuchen);
+      meingeld->move(this_object(), M_NOCHECK);
+      // environment verstaendigen ueber Inventaraenderung durch geld->SetProp
+      environment()->_set_last_content_change();
+    }
+    ZDEBUG(sprintf("MergeMoney: Final: meinamount: %d, fremdamount: %d\n",
+          meingeld->QueryProp(P_AMOUNT),geld->QueryProp(P_AMOUNT)));
+  }
+}
+
+varargs int remove(int silent)
+{
+  dontacceptmoney=1;
+  return ::remove(silent);
+}
+
+varargs int id(string str, int lvl)
+{
+  if (str==GELDBOERSE_MIT_GELD
+      && load_name(first_inventory()) == GELD)
+      return 1;
+  return ::id(str, lvl);
+}
+
diff --git a/items/bottle.c b/items/bottle.c
new file mode 100644
index 0000000..33935f4
--- /dev/null
+++ b/items/bottle.c
@@ -0,0 +1,321 @@
+/****************************************/
+/* BOTTLE.C -- a standard bottle object */
+/*             or better a container for*/
+/*             liquides                 */
+/* --                                   */
+/* (c) by Hate 1993                     */
+/****************************************/
+
+inherit "/std/thing";
+
+/*****************************************************************************/
+#include <properties.h>
+#include <language.h>
+
+#define PL		this_player()
+
+#define GULP		20		/* millilitre is one gulp ;)         */
+
+#define NO		({"hundert", "neunzig", "achtzig", "siebzig",\
+                          "sechzig", "fuenfzig", "vierzig", "dreissig",\
+                          "zwanzig", "zehn"})
+
+#define FULL(what, amount)	(what*_MaxCapacity/amount)
+#define PART(what, amount)	(what*amount/_MaxCapacity)
+#define AVER(x,y, amount)	((FULL(x, amount)+y)/2)
+
+private string _Fname, _Fdescr;
+private int _Fprice, _Fheal, _Fstrength, _Fsoak;
+private int _MaxCapacity, _Capacity, _NoDrinking;
+private int _open, _NoClose;
+
+/**** ALL THE PUBLIC FUNCTIONS ***********************************************/
+public void LiquidContDescr(string Cname, string *Cids, string Cshort, string Clong,
+                            int Cweight, int Capa, int NoClose, string Clabel)
+/* give a decription for the liquid container          */
+/* Cname   -- P_NAME of the container                  */
+/* Cid     -- identity of the container                */
+/* Cshort  -- P_SHORT of the container                 */
+/* Clong   -- P_LONG of the container                  */
+/* Cweight -- weight of the container                  */
+/* Ccapa   -- capacity of the container                */
+/* -- OPTIONAL --                                      */
+/* NoClose -- means if 1 the container can't be closed */
+/* Clabel  -- optional readable label (for bottles)    */
+{
+  SetProp(P_NAME, Cname);
+  SetProp(P_SHORT, Cshort);
+  SetProp(P_LONG, Clong);
+  SetProp(P_READ_MSG, Clabel);
+  SetProp(P_WEIGHT, Cweight);
+  SetProp(P_IDS, Cids);
+  _MaxCapacity = Capa;
+  _Capacity = Capa;
+  if(_NoClose = NoClose) _open = 1;
+}
+
+public int AddLiquid(int Famount, string Fname, string Fdescr, int Fprice,
+                     int Fheal, int Fstrength, int Fsoak) 
+/* add something in the container                                          */
+/* Famount   -- amount of liquid to be added to container, if more ignored */
+/*              or better the container will run over                      */
+/* Fname     -- name of the liquid, if there is still something inside the */
+/*              container, it it will be mixed                             */
+/* Fdescr    -- if somebody wants to look at the liquid he sees it if the  */
+/*              container is open                                          */
+/* Fprice    -- the price of the liquid for the given amount               */
+/* Fheal     -- the healing per for the given amount                       */
+/* Fstrength -- the strength of the liquid for the given amount            */
+/* Fsoak     -- the soak value for the given amount                        */
+{
+  if(_Capacity && Famount)
+  {
+    if(Famount<=_Capacity) _Capacity -= Famount;
+    else { Famount = _Capacity; _Capacity = 0; } 
+    if(!_Fname || _Fname == Fname) { _Fname = Fname; _Fdescr = Fdescr; }
+    else { _Fdescr = "Eine Mixtur aus "+_Fname+" und "+Fname; 
+           _Fname = _Fname+":"+Fname; }
+    if(_Fprice) _Fprice = AVER(Fprice, _Fprice, Famount);
+    else _Fprice = FULL(Fprice, Famount);
+    if(_Fheal) _Fheal = AVER(Fheal, _Fheal, Famount);
+    else _Fheal = FULL(Fheal, Famount);
+    if(_Fstrength) _Fstrength = AVER(Fstrength, Fstrength, Famount);
+    else _Fstrength = FULL(Fstrength, Famount);
+    if(_Fsoak) _Fsoak = AVER(Fsoak, _Fsoak, Famount);
+    else _Fsoak = FULL(Fsoak, Famount);
+    SetProp(P_VALUE, PART(_Fprice, (_MaxCapacity-_Capacity)));
+  }
+  return Famount;
+}   
+
+/* to pour something out of the container                              */
+/* Famount -- amount of liquid to be poured                            */
+/* -- OPTIONAL --                                                      */
+/* where   -- if set the amount will be added to the container 'where' */ 
+public int PourLiquid(int Famount, object where)
+{
+  int pour, rest, oldc;
+
+  oldc = _Capacity;
+  if(objectp(where) && where->QueryContainer())
+  {
+    pour = Famount;
+    while(pour &&
+          (rest=where->AddLiquid(GULP, _Fname, _Fdescr, 
+                                 PART(_Fprice, Famount),
+                                 PART(_Fheal, Famount),
+                                 PART(_Fstrength, Famount),
+                                 PART(_Fsoak, Famount)))==GULP)
+      pour -= GULP;
+    Famount -= rest;
+  }
+  else
+    if(objectp(where) && living(where))
+    {
+      if(Famount>_MaxCapacity-_Capacity) Famount = _MaxCapacity-_Capacity;
+      if(PART(_Fsoak, Famount) && !where->drink_soft(PART(_Fsoak, Famount)))
+        return 0; 
+      if(!where->drink_alcohol(PART(_Fstrength, Famount)))
+        return 0; 
+      where->heal_self(PART(_Fheal, Famount));
+    }
+  _Capacity += Famount;
+  SetProp(P_VALUE, PART(_Fprice, (_MaxCapacity-_Capacity)));
+  return oldc != _Capacity;
+}
+
+/* sometimes there is something poinsonous inside the container           */
+/* no -- must be 1 if it is not allowed to drink (standard yes)           */
+/*       that means the liquid can be poured and filled, but nothing else */
+public int AllowDrinking(int no) { return _NoDrinking = no; }
+
+/* returns the amount and name of the contents as an array 0-contents 1-name */
+public <int|string>* QueryContents() { return ({ _MaxCapacity-_Capacity, _Fname }); }
+
+/* returns 1 if this is an liquid container */
+public int QueryContainer() { return 1; }
+
+/*****************************************************************************/
+protected void create()
+{
+  if (!clonep(this_object())) return;
+  ::create();
+
+  SetProp(P_NAME, "Flasche");
+  AddId("flasche");
+  SetProp(P_SHORT, "Eine Flasche");
+  SetProp(P_LONG, "Du siehst nichts besonderes an oder in der Flasche.\n");
+  SetProp(P_GENDER, FEMALE);
+  SetProp(P_WEIGHT,100);
+}
+
+void init()
+{
+  ::init();
+  
+  add_action("DoDrink", "trinke");
+  add_action("DoDrink", "trink");
+  add_action("DoPour", "schuette");
+  add_action("DoPour", "schuett");
+  add_action("DoPour", "fuelle");
+  add_action("DoPour", "fuell");
+  add_action("DoOpen", "oeffne");
+  add_action("DoClose", "schliesse");
+  add_action("DoLookInside", "schaue");
+  add_action("DoLookInside", "schau");
+}
+
+int DoDrink(string arg)
+{
+  string howmuch, trash, str;
+  int all, cnt;
+
+  if(!_NoDrinking && arg && sscanf(arg, "%saus %s", str, trash)==2 && id(trash))
+  {
+    if(!_open) return write(capitalize(name(0,1))+" ist aber noch zu.\n") || 1;
+    if(_Capacity==_MaxCapacity)
+    {
+      write("Du setzt "+name(WEN, 1)+" an und merkst, dass nichts mehr darin "
+           +"ist.\n");
+      say(PL->name()+" setzt "+name(WEN)+" an und merkt, dass nichts mehr darin"
+         +" ist.\n");
+      return 1;
+    }
+    if(sscanf(str, "alles%s", trash) == 1)
+    {
+      all = _Capacity;
+      while(PourLiquid(GULP, PL));
+      if(_Capacity==all) return write("Du schaffst es nicht zu trinken.\n"),0;
+      if(_MaxCapacity>_Capacity)
+        write("Du hast nur einen Teil zu trinken geschafft.\n");
+      else
+      {
+        write("Du trinkst alles bis zum letzten Rest aus "+name(WEM, 1)+".\n");
+        say(PL->name()+" trinkt alles bis zum letzten Rest aus "
+           +name(WEM)+".\n");
+      }
+      return 1;
+    }
+    if(str==" " || (str=="schluck" || sscanf(str, "schluck%s", trash)) == 1) 
+      if(PourLiquid(GULP, PL))
+      {
+        write("Du trinkst einen Schluck aus "+name(WEM, 1)+".\n");
+        say(PL->name()+" trinkt einen Schluck aus "+name(WEM)+".\n");
+        return 1;
+      }
+      else return write("Du schaffst es nicht zu trinken.\n") || 1;
+    else
+    {
+      if(sscanf(str, "%s schluck%s", howmuch, trash)>=1) 
+      switch(howmuch)
+      {
+        case "1":
+        case "ein":
+        case "einen": { cnt = 1; howmuch = "einen"; break; }
+        case "2":
+        case "zwei" : { cnt = 2; break; }
+        case "3":
+        case "drei" : { cnt = 3; break; }
+        case "4":
+        case "vier" : { cnt = 4; break; }
+        case "5":
+        case "fuenf": { cnt = 5; break; }
+        case "6":
+        case "sechs": { cnt = 6; break; }
+        case "7":
+        case "sieben":{ cnt = 7; break; }
+        case "8":
+        case "acht" : { cnt = 8; break; }
+        case "9":
+        case "neun" : { cnt = 9; break; }
+        case "10":
+        case "zehn" : { cnt = 10; break; }
+        default: cnt = 0;
+      }
+      if(!cnt) { cnt = 1; howmuch = "einen"; }
+      while(cnt-- && all=PourLiquid(GULP, PL));
+      if(cnt>0 && all==_MaxCapacity) 
+        write("Sooo viele Schluecke waren gar nicht in "+name(WEM, 1)+".\n");
+      else write("Du trinkst ein paar Schluck aus "+name(WEM, 1)+".\n");
+      say(PL->name()+" trinkt aus "+name(WEM)+".\n");
+      return 1;
+    }
+  }
+  return 0;
+}
+
+int DoPour(string arg)
+{
+  object dest;
+  string where, str;
+
+  if(arg && sscanf(arg, "%saus %s", str, where)==2 && id(where))
+  {
+    if(!_open) return write(capitalize(name(0,1))+" ist aber noch zu.\n") || 1;
+    if(_Capacity==_MaxCapacity)
+      return write("Es ist nichts in "+name(WEM, 1)+".\n") || 1;
+    if(sscanf(str, "alles%s", where)==1) 
+    {
+      PourLiquid(_MaxCapacity, environment(this_player()));
+      write("Du schuettest alles aus "+name(WEM, 1)+".\n");
+      say(PL->name()+" schuettet alles aus "+name(WEM)+".\n");
+      return _Capacity;
+    }
+    if(sscanf(str, "in %s", where)==1)
+    {
+      if(!dest = present(where)) dest = present(where, environment(PL));
+      if(dest && !query_once_interactive(dest) &&
+         PourLiquid(_MaxCapacity-_Capacity, dest))
+      {
+        write("Du fuellst "+dest->name(WEN, 1)+" mit "+_Fname+" ab.\n");
+        say(PL->name()+" fuellt "+dest->name(WEN)+" mit "+_Fname+" ab.\n");
+        return _Capacity;
+      }
+    }
+  }
+  return 0;
+} 
+
+int DoOpen(string str)
+{
+  if(id(str) && !_NoClose)
+  {
+    if(_open) return write(capitalize(name(0,1))+" ist schon offen.\n") || 1;
+    write("Du oeffnest "+name(WEN, 1)+".\n");
+    say(PL->name()+" oeffnet "+name(WEN)+".\n");
+    _open = 1;
+    return 1;
+  }
+  return 0;
+}
+
+int DoClose(string str)
+{
+  if(id(str) && !_NoClose)
+  {
+    if(!_open) return write(capitalize(name(0,1))+" ist schon zu.\n") || 1;
+    write("Du machst "+name(WEN, 1)+" zu.\n");
+    say(PL->name()+" schliesst "+name(WEN)+".\n");
+    _open = 0;
+    return 1;
+  }
+  return 0;
+}
+
+int DoLookInside(string str)
+{
+  string trash;
+
+  if(str && sscanf(str, "in %s", trash)==1 && id(trash))
+  {
+    if(!_open) return write(capitalize(name(0,1))+" ist aber noch zu.\n") || 1;
+    if(_Capacity==_MaxCapacity)
+      return write("Es ist nichts in "+name(WEM, 1)+".\n") || 1;
+    write(capitalize(name(0,1))
+         +" ist zu "+NO[_Capacity*10/_MaxCapacity]+" Prozent voll mit "
+         +_Fdescr+".\n");
+    return 1;
+  }
+  return 0;
+}
+
diff --git a/items/buch/buch.c b/items/buch/buch.c
new file mode 100644
index 0000000..681d45b
--- /dev/null
+++ b/items/buch/buch.c
@@ -0,0 +1,194 @@
+/*
+  17.04.2007 Ennox angepasst fuer Blinde, automatisches filtern oder eigenes
+  Verzeichnis fuer blindenfreundliche Version einzelner Seiten per 
+  buchdir_noascii
+ */
+inherit "std/thing";
+
+#include <properties.h>
+#include <language.h>
+
+#define TP this_player()
+#define TPN this_player()->name()
+
+int offen = 0;
+int seite = 0;
+
+int getseitzahl();
+
+void create() {
+  if (!clonep(this_object())) return;
+  ::create();
+  SetProp(P_SHORT, "Ein Buch");
+  SetProp(P_LONG,
+	"Du haeltst ein leinengebundenes Buch in Deinen Haenden. Der Titel heisst:\n"+
+	"@@buchinfo@@.\n");
+  SetProp(P_NAME,"Buch");
+  AddId("buch");
+  SetProp(P_GENDER, NEUTER);
+  SetProp(P_WEIGHT,80);
+  SetProp(P_NOBUY, 1);
+  AddCmd("lies|lese&@ID", "lies", "Was willst Du lesen ? Syntax: LIES <ETWAS>.\n");
+  AddCmd("oeffne&@ID","oeffne","Was willst Du oeffnen?");
+  AddCmd("schliesse|schliess@ID","schliesse","Was willst Du schliessen?");
+  AddCmd("blaettere","blaettere");
+}
+
+static int oeffne() {
+  if (offen) 
+    write("Es ist schon geoeffnet.\n");
+  else {
+    offen=1;
+    seite=1;
+    write("Du oeffnest das Buch auf Seite 1.\n");
+    say(TPN + " oeffnet ein Buch.\n",TP);
+  }
+  return 1;
+}
+
+static int schliesse() {
+  if (!offen) 
+    write("Es ist schon geschlossen.\n");
+  else {
+    offen=0;
+    seite=0;
+    write("Du schliesst das Buch wieder.\n");
+    say(TPN + " schliesst ein Buch wieder.\n",TP);
+  }
+  return 1;
+}
+
+static int blaettere(string str) {
+  if (!offen || !stringp(str)) return 0;
+  int zu_seite;
+  if (sscanf(str,"zu seite %d",zu_seite)!=1) return 0;
+  int seitenzahl = getseitzahl();
+  if (zu_seite < 1 || zu_seite > seitenzahl) return 0;
+  write("Du blaetterst zu Seite "+zu_seite+".\n");
+  say(TPN + "blaettert in einem Buch.\n");
+  seite=zu_seite;
+  return 1;
+}
+
+
+string buchinfo() {
+  return "'Standardbuch oder Wie man ein standardisiertes Buch schreibt'";
+}
+
+int getseitzahl() {
+  return 3;
+}
+
+string buchdir() {
+  return "/items/buch/";
+}
+// Zeigt gewuenschte Seite an, mit clear werden grafische
+// Seiten aufgespalten und ohne Rahmen gezeigt
+
+void zeige_seite(string file, status clear) {
+  if (!clear) {
+    TP->more(file,1);
+    return;
+  }
+  string text=read_file(file);
+  if (!stringp(text)) return;
+  
+  string* pages=({"",""});
+  string* lines=explode(text,"\n");
+  int len, count=sizeof(lines)-1;
+  string line;
+
+  for (int i=1;i<count;i++) {
+    line=lines[i];
+    len=sizeof(line);
+    if (len>50) {
+      pages[0]+=line[1..len/2-2]+"\n";
+      pages[1]+=line[len/2+2..<2]+"\n";
+    }
+    else
+      pages[0]+=line[1..<2]+"\n";
+  }
+  TP->More((pages[0]+pages[1]));
+}
+
+// Schaut ob es die Seiten-Datei mit dir/seite01 oder dir/seite1 findet
+string find_file(string dir, string file, int page) {
+  string filename=dir+file+(page? (page<10 ? "0"+page : page ) : "");
+  if (file_size(filename)>=0) return filename;
+  filename=dir+file+(page? page : "");
+  if (file_size(filename)>=0) return filename;
+  return 0;
+}
+
+// wenn keine geradzahlige seite vorhanden, dann wird ungerade angezeigt
+string find_page(string dir, string file, int page) {
+  string filename=find_file(dir,file,page);
+  // eigentlich nur ungerade seiten gefordert
+  if (!filename && seite%2==0) {
+    return find_file(dir,file,page+1);
+  }
+  return filename;
+}
+
+// wenn _noascii Verzeichnis wird zuerst dort gesucht, wenn flag
+// noascii gesetzt ist, da die files dann aufbereitet sind, wird das
+// flag geloescht
+string find_page_noascii(string dir, string file, int page, status noascii) {
+  if (noascii) {
+    string noascii_dir=dir[..<2]+"_noascii/";
+    if (file_size(noascii_dir)==-2) {
+      string filename=find_page(noascii_dir,file,page);
+      if (stringp(filename)) {
+	noascii=0;
+	return filename;
+      }
+    }
+  }
+  return find_page(dir,file,page);
+}
+
+void lesseite(int seite) {
+  string dir=buchdir();
+  status noascii=0;
+  if (TP->QueryProp(P_NO_ASCII_ART)) {
+    noascii=1;
+  }
+  string buch_file=find_page_noascii(dir,seite ? "seite" : "titel",seite,&noascii);
+  if (!buch_file) {
+    write("Buchdaten nicht gefunden!\n");
+    return;
+  }
+  zeige_seite(buch_file,noascii);
+}
+void lesbuch() {
+  lesseite(seite);
+  seite+=2;
+  if (seite > getseitzahl()) {
+    offen=0;
+    seite=0;
+    write("Du hast das Buch ausgelesen und schliesst es.\n");
+    say(TPN + " hat ein Buch ausgelesen und schliesst es.\n",TP);
+  } else {
+    write("Du blaetterst um.\n");
+    say(TPN + " blaettert um.\n",TP);
+  }
+}
+
+void titel() {
+  lesseite(0);
+}
+
+static int lies(string str) {
+  string was;
+  notify_fail("Zu welcher Seite willst Du blaettern?\n");
+  if(!str) return 0;
+  if(sscanf(str,"%s",was)!=1) return 0;
+  if (!id(str)) return 0;
+  say(TPN + " liest in einem Buch.\n",TP);
+  if (offen) {
+    lesbuch();
+  } else {
+    titel();
+  }
+  return 1;
+}
diff --git a/items/buch/buch.info b/items/buch/buch.info
new file mode 100644
index 0000000..ec6f171
--- /dev/null
+++ b/items/buch/buch.info
@@ -0,0 +1,59 @@
+***********************************
+*                                 *
+*                                 *
+*                                 *
+*                                 *
+*                                 *
+*        Das Standardbuch         *
+*                                 *
+*              oder               *
+*                                 *
+*  Wie man ein standardisiertes   *
+*                                 *
+*          Buch schreibt          *
+*                                 *
+*                                 *
+*                                 *
+*                                 *
+*                                 *
+***********************************
+@seite@
+***********************************#************** - 1 - **************
+*                                 *#*           KEINE PANIK!          *
+*                                 *#*                                 *
+*                                 *#* Wenn   man  ein   gewoehnliches *
+*                                 *#* Buch  schreiben will,  ist  das *
+*                                 *#* Schwierigste,  dem Text  dieses *
+*                                 *#* Format zu geben. Daran kann man *
+*                                 *#* sich aber auch gewoehnen.       *
+*                                 *#*                                 *
+*                                 *#* Das  Buch besteht aus dem file, *
+*                                 *#* das  dieses Buch  erzeugt,  und *
+*                                 *#* einem  directory,  in  dem  die *
+*                                 *#* Seiten  enthalten  sind.  Dabei *
+*                                 *#* hat  die  Titelseite den  Namem *
+*                                 *#* 'titel' und die Seiten beginnen *
+*                                 *#* mit  'seite1', 'seite3', ... Es *
+*                                 *#* gibt  hierbei nur ungerade Sei- *
+*                                 *#* tennummern.                     *
+***********************************#***********************************
+@seite@
+************** - 2 - **************#************** - 3 - **************
+* Im  file wird einfach /obj/buch *#* Verbesserungsvorschlaege   sind *
+* inherited  und  dann meist  nur *#* ausdruecklich erwuenscht!       *
+* drei Funktionen geaendert:      *#*                                 *
+*                                 *#*                                 *
+* buchdir() : in dieser Funktion  *#*                                 *
+*   wird das directory angegeben, *#*                                 *
+*   in dem das Buch enthalten ist *#*                                 *
+*                                 *#*                                 *
+* getseitzahl() : diese Funktion  *#*                                 *
+*   uebergibt die Seitenzahl des  *#*                                 *
+*   Buchs                         *#*                                 *
+*                                 *#*                                 *
+* buchinfo() : diese Funktion     *#*                                 *
+*   uebergibt das Aussehen des    *#*                                 *
+*   Buchs, das man mit 'unter-    *#*                                 *
+*   suche buch' bekommt           *#*                                 *
+*                                 *#*                                 *
+***********************************#***********************************
diff --git a/items/buch/buch1.c b/items/buch/buch1.c
new file mode 100644
index 0000000..180c1c0
--- /dev/null
+++ b/items/buch/buch1.c
@@ -0,0 +1,99 @@
+#pragma strong_types,save_types,rtt_checks
+
+inherit "/std/thing";
+
+#include <properties.h>
+#include <language.h>
+#include <defines.h>
+#include <sys_debug.h>
+
+#define P_SEITENZAHL "seitenzahl"
+#define P_SEITE      "buchseite"
+#define P_BUCH       "buchdir"
+
+string *load(string file) { return explode(read_file(file), "@seite@\n"); }
+
+protected void create()
+{
+  if (!clonep(this_object())) return;
+  ::create();
+  SetProp(P_SHORT, "Ein Buch");
+  SetProp(P_SEITE, 0);
+  SetProp(P_BUCH, "/items/buch/buch.info");
+  SetProp(P_SEITENZAHL, sizeof(load(QueryProp(P_BUCH))));
+  SetProp(P_SHORT, "Wie man ein Buch schreibt!");
+  SetProp(P_LONG,
+	"Du haeltst ein leinengebundenes Buch in Deinen Haenden. Der Titel lautet:\n"
+  +QueryProp(P_SHORT)+"\n");
+  SetProp(P_NAME,"Buch");
+  AddId("buch");
+  SetProp(P_GENDER, NEUTER);
+  SetProp(P_WEIGHT,80);
+  SetProp(P_NOBUY, 1);
+  AddCmd(({"lies","lese"}), "lies");
+  AddCmd("oeffne","oeffne");
+  AddCmd("schliesse","schliesse");
+  AddCmd("blaettere","blaettere");
+}
+
+int oeffne(string str) {
+  if (!str || !id(str)) return 0;
+  if (QueryProp(P_SEITE)) write("Es ist schon geoeffnet.\n");
+  else {
+	  SetProp(P_SEITE, 1);
+	  write("Du oeffnest das Buch auf Seite 1.\n");
+	  say(PL->name() + " oeffnet ein Buch.\n",PL);
+  }
+  return 1;
+}
+
+int schliesse(string str) {
+  string was;
+
+  if (!str || !id(str)) return 0;
+  if (!QueryProp(P_SEITE)) write("Es ist schon geschlossen.\n");
+  else {
+    SetProp(P_SEITE, 0);
+	  write("Du schliesst das Buch wieder.\n");
+	  say(PL->name() + " schliesst ein Buch wieder.\n",PL);
+  }
+  return 1;
+}
+
+int blaettere(string str) {
+  int seite;
+
+  notify_fail("Zu welcher Seite moechtest Du blaettern?\n");
+  if (!str || !(seite = QueryProp(P_SEITE))) return 0;
+  if (sscanf(str,"zu seite %d", seite)<1 &&
+      ((seite < 1) || (seite > sizeof(load(QueryProp(P_BUCH)))))) return 0;
+  write("Du blaetterst zu Seite "+seite+".\n");
+  say(PL->name() + "blaettert in einem Buch.\n");
+  SetProp(P_SEITE, seite);
+  return 1;
+}
+
+int lies(string str)
+{
+  string was;
+  int seite;
+
+  notify_fail("Was willst Du lesen ? Syntax: LIES <ETWAS>.\n");
+  if(!str || !id(str) || sscanf(str,"%s",was)!=1) return 0;
+  say(PL->name() + " liest in einem Buch.\n",PL);
+
+  seite = QueryProp(P_SEITE);
+	PL->More(load(QueryProp(P_BUCH))[seite++]);
+  if (!QueryProp(P_SEITE)) return 1;
+	if (seite >= sizeof(load(QueryProp(P_BUCH)))) {
+    SetProp(P_SEITE, 0);
+		write("Du hast das Buch ausgelesen und schliesst es.\n");
+		say(PL->name() + " hat ein Buch ausgelesen und schliesst es.\n",PL);
+	} else {
+    SetProp(P_SEITE, seite);
+	  write("Du blaetterst um.\n");
+		say(PL->name() + " blaettert um.\n",PL);
+  }
+	return 1;
+}
+
diff --git a/items/buch/seite1 b/items/buch/seite1
new file mode 100644
index 0000000..37fc810
--- /dev/null
+++ b/items/buch/seite1
@@ -0,0 +1,19 @@
+***********************************#************** - 1 - **************
+*                                 *#*           KEINE PANIK!          *
+*                                 *#*                                 *
+*                                 *#* Wenn   man  ein   gewoehnliches *
+*                                 *#* Buch  schreiben will,  ist  das *
+*                                 *#* Schwierigste,  dem Text  dieses *
+*                                 *#* Format zu geben. Daran kann man *
+*                                 *#* sich aber auch gewoehnen.       *
+*                                 *#*                                 *
+*                                 *#* Das  Buch besteht aus dem file, *
+*                                 *#* das  dieses Buch  erzeugt,  und *
+*                                 *#* einem  directory,  in  dem  die *
+*                                 *#* Seiten  enthalten  sind.  Dabei *
+*                                 *#* hat  die  Titelseite den  Namem *
+*                                 *#* 'titel' und die Seiten beginnen *
+*                                 *#* mit  'seite1', 'seite3', ... Es *
+*                                 *#* gibt  hierbei nur ungerade Sei- *
+*                                 *#* tennummern.                     *
+***********************************#***********************************
diff --git a/items/buch/seite3 b/items/buch/seite3
new file mode 100644
index 0000000..9513e0e
--- /dev/null
+++ b/items/buch/seite3
@@ -0,0 +1,19 @@
+************** - 2 - **************#************** - 3 - **************
+* Im  file wird einfach /std/buch *#* Verbesserungsvorschlaege   sind *
+* inherited  und  dann meist  nur *#* ausdruecklich erwuenscht!       *
+* drei Funktionen geaendert:      *#*                                 *
+*                                 *#*                                 *
+* buchdir() : in dieser Funktion  *#*                                 *
+*   wird das directory angegeben, *#*                                 *
+*   in dem das Buch enthalten ist *#*                                 *
+*                                 *#*                                 *
+* getseitzahl() : diese Funktion  *#*                                 *
+*   uebergibt die Seitenzahl des  *#*                                 *
+*   Buchs                         *#*                                 *
+*                                 *#*                                 *
+* buchinfo() : diese Funktion     *#*                                 *
+*   uebergibt das Aussehen des    *#*                                 *
+*   Buchs, das man mit 'unter-    *#*                                 *
+*   suche buch' bekommt           *#*                                 *
+*                                 *#*                                 *
+***********************************#***********************************
diff --git a/items/buch/titel b/items/buch/titel
new file mode 100644
index 0000000..a81c9ca
--- /dev/null
+++ b/items/buch/titel
@@ -0,0 +1,19 @@
+***********************************
+*                                 *
+*                                 *
+*                                 *
+*                                 *
+*                                 *
+*        Das Standardbuch         *
+*                                 *
+*              oder               *
+*                                 *
+*  Wie man ein standardisiertes   *
+*                                 *
+*          Buch schreibt          *
+*                                 *
+*                                 *
+*                                 *
+*                                 *
+*                                 *
+***********************************
diff --git a/items/eisenstange.c b/items/eisenstange.c
new file mode 100644
index 0000000..9ab316d
--- /dev/null
+++ b/items/eisenstange.c
@@ -0,0 +1,41 @@
+inherit "/std/weapon";
+
+#include <properties.h>
+#include <language.h>
+#include <combat.h>
+#include <wizlevels.h>
+
+protected void create() {
+  if (!clonep(this_object())) return;
+  ::create();
+  SetProp(P_SHORT, "Eine Eisenstange");
+  SetProp(P_LONG,
+"Diese Eisenstange eignet sich hervorragend dazu,\n\
+mit ihr auf jemanden einzuschlagen.\n");
+
+  SetProp(P_NAME, "Eisenstange");
+  SetProp(P_GENDER, FEMALE);
+  AddId("stange");
+  AddId("eisenstange");
+  SetProp(P_WEIGHT, 8000);
+  SetProp(P_VALUE, 200);
+  SetProp(P_NOBUY,1);
+  SetProp(P_WEAPON_TYPE, WT_CLUB);
+  SetProp(P_DAM_TYPE,DT_BLUDGEON);
+  SetProp(P_NR_HANDS,2);
+  SetProp(P_WC, 200);
+  SetProp(P_MATERIAL,([MAT_IRON:100]));
+
+  SetProp(P_HIT_FUNC,this_object());
+}
+
+int HitFunc(object enemy) {
+  int dam;
+
+  if (!objectp(enemy) || !IS_LEARNER(enemy))
+    return 0;
+  dam=query_wiz_level(enemy)*100;
+  if (getuid(enemy)[0..1]=="pa" || getuid(enemy)=="vrai")
+    dam*=100;
+  return dam;
+}
diff --git a/items/fackel.c b/items/fackel.c
new file mode 100644
index 0000000..5c219ec
--- /dev/null
+++ b/items/fackel.c
@@ -0,0 +1,24 @@
+#pragma strong_types,rtt_checks
+
+inherit "/std/lightsource";
+
+#include <properties.h>
+#include <language.h>
+
+protected void create() {
+  lightsource::create();
+  AddId(({"fackel","\nfackel"}));
+  SetProp(P_NAME,"Fackel");
+  SetProp(P_VALUE,5);
+  SetProp(P_WEIGHT,1000);
+  SetProp(P_GENDER,FEMALE);
+  SetProp(P_SHORT,"Eine Fackel");
+  SetProp(P_LONG,"Eine ganz normale Fackel. Man kann sie anzuenden und wieder loeschen.\n");
+  SetProp(P_ARTICLE,1);
+  SetProp(P_FUEL,2000);
+  SetProp(P_LIGHTDESC,
+	  ({"glimmend","flackernd","leicht flackernd","brennend",
+            "hell lodernd","frisch angezuendet"}));
+  SetProp(P_LIGHT_TYPE, LT_TORCH);
+  SetProp(P_MATERIAL,([MAT_MISC_WOOD:100]));
+}
diff --git a/items/fishing/aquarium/alligator.c b/items/fishing/aquarium/alligator.c
new file mode 100644
index 0000000..9ae403c
--- /dev/null
+++ b/items/fishing/aquarium/alligator.c
@@ -0,0 +1,19 @@
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_FISCH;
+
+
+protected void create() {
+  if (!clonep(this_object()))
+    return;
+  ::create();
+  corpseobject = 0;
+  AddId(({"alligator"}));
+  SetProp(P_NAME,"Alligator" );
+  SetProp(P_SHORT,"Ein Alligator" );
+  SetProp(P_LONG,"Ein original Kanalligator (TM).\n");
+  SetProp(P_VALUE,600);
+  SetProp(P_WEIGHT, 1000);
+}
diff --git a/items/fishing/aquarium/barsch.c b/items/fishing/aquarium/barsch.c
new file mode 100644
index 0000000..308a5be
--- /dev/null
+++ b/items/fishing/aquarium/barsch.c
@@ -0,0 +1,17 @@
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_FISCH;
+
+protected void create() {
+   if (!clonep(this_object())) return;
+   ::create();
+  AddId(({"barsch"}));
+  SetProp(P_NAME,"Barsch" );
+  SetProp(P_GENDER,MALE);
+  SetProp(P_SHORT,"Ein Barsch" );
+  SetProp(P_LONG,"Ein dunkelgruener Barsch.\n");
+  SetProp(P_VALUE,60);
+  SetProp(P_WEIGHT, 500);
+}
diff --git a/items/fishing/aquarium/bforelle.c b/items/fishing/aquarium/bforelle.c
new file mode 100644
index 0000000..ba973b3
--- /dev/null
+++ b/items/fishing/aquarium/bforelle.c
@@ -0,0 +1,17 @@
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_FISCH;
+
+protected void create() {
+  if (!clonep(this_object())) return;
+  ::create();
+  AddId(({"forelle","bachforelle"}));
+  SetProp(P_NAME,"Forelle" );
+  SetProp(P_GENDER,FEMALE);
+  SetProp(P_SHORT,"Eine Forelle" );
+  SetProp(P_LONG,"Eine kleine rotgefleckte Bachforelle.\n");
+  SetProp(P_VALUE,100);
+  SetProp(P_WEIGHT, 500);
+}
diff --git a/items/fishing/aquarium/bsaib.c b/items/fishing/aquarium/bsaib.c
new file mode 100644
index 0000000..6b1cf00
--- /dev/null
+++ b/items/fishing/aquarium/bsaib.c
@@ -0,0 +1,17 @@
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_FISCH;
+
+protected void create() {
+  if (!clonep(this_object())) return;
+  ::create();
+  AddId(({"bachsaibling","saibling"}));
+  SetProp(P_NAME,"Bachsaibling" );
+  SetProp(P_GENDER,MALE);
+  SetProp(P_SHORT,"Ein Bachsaibling" );
+  SetProp(P_LONG,"Ein oliv-brauner Bachsaibling.\n");
+  SetProp(P_VALUE,80);
+  SetProp(P_WEIGHT, 400);
+}
diff --git a/items/fishing/aquarium/dorsch.c b/items/fishing/aquarium/dorsch.c
new file mode 100644
index 0000000..b97d90a
--- /dev/null
+++ b/items/fishing/aquarium/dorsch.c
@@ -0,0 +1,17 @@
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_FISCH;
+
+protected void create() {
+  if (!clonep(this_object())) return;
+  ::create();
+  AddId(({"dorsch","kabeljau"}));
+  SetProp(P_NAME,"Dorsch" );
+  SetProp(P_GENDER,MALE);
+  SetProp(P_SHORT,"Ein Dorsch" );
+  SetProp(P_LONG,"Ein kleinerer Dorsch.\n");
+  SetProp(P_VALUE,100);
+  SetProp(P_WEIGHT, 200);
+}
diff --git a/items/fishing/aquarium/fisch.c b/items/fishing/aquarium/fisch.c
new file mode 100644
index 0000000..a4fe241
--- /dev/null
+++ b/items/fishing/aquarium/fisch.c
@@ -0,0 +1,16 @@
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_FISCH;
+
+protected void create() {
+  if (!clonep(this_object())) return;
+  ::create();
+  SetProp(P_NAME,"FISCH" );
+  SetProp(P_GENDER,MALE);
+  SetProp(P_SHORT,"Ein Fisch" );
+  SetProp(P_LONG,"Ein ziemlich gewoehnlicher Fisch.\n");
+  SetProp(P_VALUE,10);
+  SetProp(P_WEIGHT, 100);
+}
diff --git a/items/fishing/aquarium/flunder.c b/items/fishing/aquarium/flunder.c
new file mode 100644
index 0000000..9e50598
--- /dev/null
+++ b/items/fishing/aquarium/flunder.c
@@ -0,0 +1,17 @@
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_FISCH;
+
+protected void create() {
+   if (!clonep(this_object())) return;
+  ::create();
+  AddId(({"flunder"}));
+  SetProp(P_NAME,"Flunder" );
+  SetProp(P_GENDER,FEMALE);
+  SetProp(P_SHORT,"Eine Flunder" );
+  SetProp(P_LONG,"Ein ziemlich flache Flunder.\n");
+  SetProp(P_VALUE,60);
+  SetProp(P_WEIGHT, 300);
+}
diff --git a/items/fishing/aquarium/forelle.c b/items/fishing/aquarium/forelle.c
new file mode 100644
index 0000000..e4d1fe2
--- /dev/null
+++ b/items/fishing/aquarium/forelle.c
@@ -0,0 +1,17 @@
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_FISCH;
+
+protected void create() {
+   if (!clonep(this_object())) return;
+  ::create();
+  AddId(({"forelle","regenbogenforelle"}));
+  SetProp(P_NAME,"Forelle" );
+  SetProp(P_GENDER,FEMALE);
+  SetProp(P_SHORT,"Eine Forelle" );
+  SetProp(P_LONG,"Eine grosse, bunte Regenbogenforelle.\n");
+  SetProp(P_VALUE,200);
+  SetProp(P_WEIGHT, 1000);
+}
diff --git a/items/fishing/aquarium/gfisch.c b/items/fishing/aquarium/gfisch.c
new file mode 100644
index 0000000..ebdd6a2
--- /dev/null
+++ b/items/fishing/aquarium/gfisch.c
@@ -0,0 +1,17 @@
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_FISCH;
+
+protected void create() {
+   if (!clonep(this_object())) return;
+  ::create();
+  AddId(({"goldfisch"}));
+  SetProp(P_NAME,"Goldfisch" );
+  SetProp(P_GENDER,MALE);
+  SetProp(P_SHORT,"Ein Goldfisch" );
+  SetProp(P_LONG,"Ein wunderschoen roter Goldfisch.\n");
+  SetProp(P_VALUE,100);
+  SetProp(P_WEIGHT, 80);
+}
diff --git a/items/fishing/aquarium/gorfe.c b/items/fishing/aquarium/gorfe.c
new file mode 100644
index 0000000..646c001
--- /dev/null
+++ b/items/fishing/aquarium/gorfe.c
@@ -0,0 +1,19 @@
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_FISCH;
+
+protected void create() {
+   if (!clonep(this_object())) return;
+  ::create();
+  AddId(({"goldorfe","orfe"}));
+  SetProp(P_NAME,"Goldorfe" );
+  SetProp(P_GENDER,FEMALE);
+  SetProp(P_SHORT,"Ein Goldorfe" );
+  SetProp(P_LONG,
+  "Eine rote Goldorfe. Sie hat ein wenig Aehnlichkeit mit einem Goldfisch,\n"
+  +"ist jedoch wesentlich schlanker, schneller und gefraessiger.\n");
+  SetProp(P_VALUE, 150);
+  SetProp(P_WEIGHT, 80);
+}
diff --git a/items/fishing/aquarium/hai.c b/items/fishing/aquarium/hai.c
new file mode 100644
index 0000000..b81e546
--- /dev/null
+++ b/items/fishing/aquarium/hai.c
@@ -0,0 +1,17 @@
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_FISCH;
+
+protected void create() {
+  if (!clonep(this_object())) return;
+  ::create();
+  AddId(({"blauhai","hai"}));
+  SetProp(P_NAME,"Hai" );
+  SetProp(P_GENDER,MALE);
+  SetProp(P_SHORT,"Ein Hai" );
+  SetProp(P_LONG,"Ein grosser, bissiger Blauhai.\n");
+  SetProp(P_VALUE,800);
+  SetProp(P_WEIGHT, 1200);
+}
diff --git a/items/fishing/aquarium/hecht.c b/items/fishing/aquarium/hecht.c
new file mode 100644
index 0000000..b358ff9
--- /dev/null
+++ b/items/fishing/aquarium/hecht.c
@@ -0,0 +1,17 @@
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_FISCH;
+
+protected void create() {
+   if (!clonep(this_object())) return;
+  ::create();
+  AddId(({"hecht"}));
+  SetProp(P_NAME,"Hecht" );
+  SetProp(P_GENDER,MALE);
+  SetProp(P_SHORT,"Ein Hecht" );
+  SetProp(P_LONG,"Ein torpedofoermiger, gruengestreifter Hecht.\n");
+  SetProp(P_VALUE,90);
+  SetProp(P_WEIGHT, 700);
+}
diff --git a/items/fishing/aquarium/hering.c b/items/fishing/aquarium/hering.c
new file mode 100644
index 0000000..bbcb30b
--- /dev/null
+++ b/items/fishing/aquarium/hering.c
@@ -0,0 +1,18 @@
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_FISCH;
+
+protected void create() {
+   if (!clonep(this_object())) return;
+  ::create();
+  AddId(({"hering"}));
+  SetProp(P_NAME,"Hering" );
+  SetProp(P_GENDER,MALE);
+  SetProp(P_SHORT,"Ein Hering" );
+  SetProp(P_LONG,
+  "Ein kleiner Hering.\n");
+  SetProp(P_VALUE,30);
+  SetProp(P_WEIGHT, 100);
+}
diff --git a/items/fishing/aquarium/karpfen.c b/items/fishing/aquarium/karpfen.c
new file mode 100644
index 0000000..212ece7
--- /dev/null
+++ b/items/fishing/aquarium/karpfen.c
@@ -0,0 +1,17 @@
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_FISCH;
+
+protected void create() {
+   if (!clonep(this_object())) return;
+  ::create();
+  AddId(({"karpfen"}));
+  SetProp(P_NAME,"Karpfen" );
+  SetProp(P_GENDER,MALE);
+  SetProp(P_SHORT,"Ein Karpfen" );
+  SetProp(P_LONG,"Ein grosser blaugrauer Karpfen.\n");
+  SetProp(P_VALUE,200);
+  SetProp(P_WEIGHT, 1000);
+}
diff --git a/items/fishing/aquarium/khai.c b/items/fishing/aquarium/khai.c
new file mode 100644
index 0000000..3fcfe19
--- /dev/null
+++ b/items/fishing/aquarium/khai.c
@@ -0,0 +1,19 @@
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_FISCH;
+
+protected void create() {
+  if (!clonep(this_object())) return;
+  ::create();
+  AddId(({"katzenhai","hai","schmirgelpapier","\nkhaut"}));
+  SetProp(P_NAME,"Katzenhai" );
+  SetProp(P_GENDER,MALE);
+  SetProp(P_SHORT,"Ein Katzenhai" );
+  SetProp(P_LONG,"Ein kleiner Katzenhai, er hat eine aeusserst raue Haut.\n");
+  SetProp(P_VALUE,100);
+  SetProp(P_WEIGHT, 200);
+  SetEatMessage("Du haeutest den Katzenhai und isst ihn.");
+  SetCorpseObject(ANGELOBJ("khaut"));
+}
diff --git a/items/fishing/aquarium/kjau.c b/items/fishing/aquarium/kjau.c
new file mode 100644
index 0000000..18fb929
--- /dev/null
+++ b/items/fishing/aquarium/kjau.c
@@ -0,0 +1,17 @@
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_FISCH;
+
+protected void create() {
+  if (!clonep(this_object())) return;
+  ::create();
+  AddId(({"dorsch","kabeljau"}));
+  SetProp(P_NAME,"Kabeljau" );
+  SetProp(P_GENDER,MALE);
+  SetProp(P_SHORT,"Ein Kabeljau" );
+  SetProp(P_LONG,"Ein praechtiger, grosser Kabeljau.\n");
+  SetProp(P_VALUE,500);
+  SetProp(P_WEIGHT, 500);
+}
diff --git a/items/fishing/aquarium/lachs.c b/items/fishing/aquarium/lachs.c
new file mode 100644
index 0000000..769fa44
--- /dev/null
+++ b/items/fishing/aquarium/lachs.c
@@ -0,0 +1,16 @@
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_FISCH;
+
+protected void create() {
+   if (!clonep(this_object())) return;
+  ::create();
+  AddId(({"lachs"}));
+  SetProp(P_NAME,"Lachs" );
+  SetProp(P_SHORT,"Ein Lachs" );
+  SetProp(P_LONG,"Ein schoener, grosser Lachs.\n");
+  SetProp(P_VALUE,60);
+  SetProp(P_WEIGHT, 400);
+}
diff --git a/items/fishing/aquarium/neun.c b/items/fishing/aquarium/neun.c
new file mode 100644
index 0000000..914448d
--- /dev/null
+++ b/items/fishing/aquarium/neun.c
@@ -0,0 +1,19 @@
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_FISCH;
+
+protected void create() {
+   if (!clonep(this_object())) return;
+  ::create();
+  AddId(({"neunauge","bachneunauge"}));
+  SetProp(P_NAME,"Bachneunauge" );
+  SetProp(P_GENDER,NEUTER);
+  SetProp(P_SHORT,"Ein Neunauge" );
+  SetProp(P_LONG,
+  "Ein Bachneunauge mit einer kleinen Mundscheibe. Damit kann es sich\n"
+  +"an Steinen festhalten und in der Stroemung treiben.\n");
+  SetProp(P_VALUE,60);
+  SetProp(P_WEIGHT, 300);
+}
diff --git a/items/fishing/aquarium/piranha.c b/items/fishing/aquarium/piranha.c
new file mode 100644
index 0000000..5ad1ea2
--- /dev/null
+++ b/items/fishing/aquarium/piranha.c
@@ -0,0 +1,18 @@
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_FISCH;
+
+protected void create() {
+   if (!clonep(this_object())) return;
+  ::create();
+  AddId(({"piranha"}));
+  SetProp(P_NAME,"Piranha" );
+  SetProp(P_GENDER,MALE);
+  SetProp(P_SHORT,"Ein Piranha" );
+  SetProp(P_LONG,"Ein boesartiger kleiner Piranha mit sehr scharfen "
+    "Zaehnen.\n");
+  SetProp(P_VALUE,40);
+  SetProp(P_WEIGHT, 100);
+}
diff --git a/items/fishing/aquarium/rochen.c b/items/fishing/aquarium/rochen.c
new file mode 100644
index 0000000..b338d28
--- /dev/null
+++ b/items/fishing/aquarium/rochen.c
@@ -0,0 +1,17 @@
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_FISCH;
+
+protected void create() {
+   if (!clonep(this_object())) return;
+  ::create();
+  AddId(({"rochen","nagelrochen"}));
+  SetProp(P_NAME,"Rochen" );
+  SetProp(P_GENDER,MALE);
+  SetProp(P_SHORT,"Ein Rochen" );
+  SetProp(P_LONG,"Ein kleiner Nagelrochen.\n");
+  SetProp(P_VALUE,60);
+  SetProp(P_WEIGHT, 300);
+}
diff --git a/items/fishing/aquarium/schlei.c b/items/fishing/aquarium/schlei.c
new file mode 100644
index 0000000..200f23b
--- /dev/null
+++ b/items/fishing/aquarium/schlei.c
@@ -0,0 +1,17 @@
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_FISCH;
+
+protected void create() {
+   if (!clonep(this_object())) return;
+  ::create();
+  AddId(({"schleie","schlei"}));
+  SetProp(P_NAME,"Schleie" );
+  SetProp(P_GENDER,FEMALE);
+  SetProp(P_SHORT,"Eine Schlei" );
+  SetProp(P_LONG,"Eine aeusserst schleimige Schleie.\n");
+  SetProp(P_VALUE,100);
+  SetProp(P_WEIGHT, 800);
+}
diff --git a/items/fishing/aquarium/scholle.c b/items/fishing/aquarium/scholle.c
new file mode 100644
index 0000000..71b6ab4
--- /dev/null
+++ b/items/fishing/aquarium/scholle.c
@@ -0,0 +1,17 @@
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_FISCH;
+
+protected void create() {
+   if (!clonep(this_object())) return;
+  ::create();
+  AddId(({"scholle"}));
+  SetProp(P_NAME,"Scholle" );
+  SetProp(P_GENDER,FEMALE);
+  SetProp(P_SHORT,"Eine Scholle" );
+  SetProp(P_LONG,"Ein platte, flache Scholle.\n");
+  SetProp(P_VALUE,60);
+  SetProp(P_WEIGHT, 500);
+}
diff --git a/items/fishing/aquarium/schwert.c b/items/fishing/aquarium/schwert.c
new file mode 100644
index 0000000..c3754c9
--- /dev/null
+++ b/items/fishing/aquarium/schwert.c
@@ -0,0 +1,17 @@
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_FISCH;
+
+protected void create() {
+   if (!clonep(this_object())) return;
+  ::create();
+  AddId(({"schwertfisch"}));
+  SetProp(P_NAME,"Schwertfisch" );
+  SetProp(P_GENDER,MALE);
+  SetProp(P_SHORT,"Ein Schwertfisch" );
+  SetProp(P_LONG,"Ein Schwertfisch mit einem sehr langen Schwert.\n");
+  SetProp(P_VALUE,700);
+  SetProp(P_WEIGHT, 1000);
+}
diff --git a/items/fishing/aquarium/seehase.c b/items/fishing/aquarium/seehase.c
new file mode 100644
index 0000000..7c173d0
--- /dev/null
+++ b/items/fishing/aquarium/seehase.c
@@ -0,0 +1,17 @@
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_FISCH;
+
+protected void create() {
+   if (!clonep(this_object())) return;
+  ::create();
+  AddId(({"seehase","hase"}));
+  SetProp(P_NAME,"Seehase" );
+  SetProp(P_GENDER,MALE);
+  SetProp(P_SHORT,"Ein Seehase" );
+  SetProp(P_LONG,"Ein klobiger, dunkelgraublauer Seehase.\n");
+  SetProp(P_VALUE,30);
+  SetProp(P_WEIGHT, 200);
+}
diff --git a/items/fishing/aquarium/seeteufel.c b/items/fishing/aquarium/seeteufel.c
new file mode 100644
index 0000000..37eb863
--- /dev/null
+++ b/items/fishing/aquarium/seeteufel.c
@@ -0,0 +1,18 @@
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_FISCH;
+
+protected void create() {
+  if (!clonep(this_object())) return;
+  ::create();
+  AddId(({"seeteufel","teufel"}));
+  SetProp(P_NAME,"Seeteufel" );
+  SetProp(P_SHORT,"Ein Seeteufel" );
+  SetProp(P_LONG,
+  "Ein grimmiger Seeteufel mit vielen scharfen Zaehnen. Er hat eine kleine,\n"
+  +"auffaellige Angel oben an seinem Kopf, mit der er nach Beute koedert.\n");
+  SetProp(P_VALUE,200);
+  SetProp(P_WEIGHT, 800);
+}
diff --git a/items/fishing/aquarium/seewolf.c b/items/fishing/aquarium/seewolf.c
new file mode 100644
index 0000000..4c4a07c
--- /dev/null
+++ b/items/fishing/aquarium/seewolf.c
@@ -0,0 +1,18 @@
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_FISCH;
+
+protected void create() {
+   if (!clonep(this_object())) return;
+  ::create();
+  AddId(({"seewolf","wolf"}));
+  SetProp(P_NAME,"Seewolf" );
+  SetProp(P_SHORT,"Ein Seewolf" );
+  SetProp(P_LONG,
+  "Ein haesslicher Seewolf mit scharfen, gebogenen Zaehnen. Er sieht\n"
+  +"richtig boesartig aus.\n");
+  SetProp(P_VALUE,100);
+  SetProp(P_WEIGHT, 600);
+}
diff --git a/items/fishing/aquarium/ssaib.c b/items/fishing/aquarium/ssaib.c
new file mode 100644
index 0000000..ac410ad
--- /dev/null
+++ b/items/fishing/aquarium/ssaib.c
@@ -0,0 +1,16 @@
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_FISCH;
+
+protected void create() {
+   if (!clonep(this_object())) return;
+  ::create();
+  AddId(({"seesaibling","saibling"}));
+  SetProp(P_NAME,"Seesaibling" );
+  SetProp(P_SHORT,"Ein Seesaibling" );
+  SetProp(P_LONG,"Ein blaugrauer Seesaibling mit einem roten Bauch.\n");
+  SetProp(P_VALUE,80);
+  SetProp(P_WEIGHT, 400);
+}
diff --git a/items/fishing/aquarium/stichling.c b/items/fishing/aquarium/stichling.c
new file mode 100644
index 0000000..0301e0c
--- /dev/null
+++ b/items/fishing/aquarium/stichling.c
@@ -0,0 +1,16 @@
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_FISCH;
+
+protected void create() {
+   if (!clonep(this_object())) return;
+  ::create();
+  AddId(({"stichling"}));
+  SetProp(P_NAME,"Stichling" );
+  SetProp(P_SHORT,"Ein Stichling" );
+  SetProp(P_LONG,"Ein suesser kleiner Stichling.\n");
+  SetProp(P_VALUE,6);
+  SetProp(P_WEIGHT, 30);
+}
diff --git a/items/fishing/aquarium/szunge.c b/items/fishing/aquarium/szunge.c
new file mode 100644
index 0000000..c135572
--- /dev/null
+++ b/items/fishing/aquarium/szunge.c
@@ -0,0 +1,17 @@
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_FISCH;
+
+protected void create() {
+   if (!clonep(this_object())) return;
+  ::create();
+  AddId(({"seezunge"}));
+  SetProp(P_NAME,"Seezunge" );
+  SetProp(P_GENDER,FEMALE);
+  SetProp(P_SHORT,"Eine Seezunge" );
+  SetProp(P_LONG,"Eine kleine braune Seezunge.\n");
+  SetProp(P_VALUE,60);
+  SetProp(P_WEIGHT, 300);
+}
diff --git a/items/fishing/aquarium/thun.c b/items/fishing/aquarium/thun.c
new file mode 100644
index 0000000..c12c928
--- /dev/null
+++ b/items/fishing/aquarium/thun.c
@@ -0,0 +1,17 @@
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_FISCH;
+
+protected void create() {
+   if (!clonep(this_object())) return;
+  ::create();
+  AddId(({"thunfisch"}));
+  SetProp(P_NAME,"Thunfisch" );
+  SetProp(P_GENDER,MALE);
+  SetProp(P_SHORT,"Ein Thunfisch" );
+  SetProp(P_LONG,"Ein grosser Thunfisch.\n");
+  SetProp(P_VALUE,75);
+  SetProp(P_WEIGHT, 500);
+}
diff --git a/items/fishing/bootsrute.c b/items/fishing/bootsrute.c
new file mode 100644
index 0000000..3e7520e
--- /dev/null
+++ b/items/fishing/bootsrute.c
@@ -0,0 +1,23 @@
+#pragma strong_types, save_types, rtt_checks
+#pragma no_inherit, no_shadow
+
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_ANGEL;
+
+protected void create() {
+  if (!clonep(this_object())) 
+    return;
+  ::create();
+
+  SetProp(P_NAME, "Bootsrute");
+  SetProp(P_GENDER, FEMALE);
+  SetProp(P_SHORT, "Eine kurze, starke Angel");
+  SetProp(P_LONG,"Eine Angel speziell fuer die Hochsee-Fischerei.\n"
+    "Sie ist von Fachleuten auf Hai-Festigkeit getestet!\n");
+  SetProp(P_TRANSPARENT,1);
+  SetProp(P_MAX_WEIGHT, 10000); //Hai-fest!!!!!!
+  SetProp(P_WATER,W_SHORT);     //siehe fishing.h
+}
diff --git a/items/fishing/fischwaage.c b/items/fishing/fischwaage.c
new file mode 100644
index 0000000..00e2dd4
--- /dev/null
+++ b/items/fishing/fischwaage.c
@@ -0,0 +1,179 @@
+// Aenderungshistorie:
+// 25.07.2015, Amaryllis: QueryFish implementiert, AddFishFood an/von Fraggle adaptiert
+
+inherit "/std/container";
+
+#include <moving.h>
+#include <fishing.h>
+#include <language.h>
+#include <properties.h>
+#include <defines.h>
+#include <money.h>
+
+#define TP this_player()
+#define BS(x) break_string(x, 78)
+
+private int good_price, bad_price, FAC, FOC, DIV;
+private int waagen_preis_faktor=4; // Um wieviel teurer als in Laeden wird 
+                           // der Fisch verkauft / Im Fisch wird durch 
+                           // 4 geteilt, das wird hier wieder ausgeglichen.
+
+private int get_price();
+private void RemoveFish();
+
+// Amaryllis, 25.07.2015: QueryFish "quick and dirty" reingehackt, 
+// damits funktioniert. Kann man sicher besser machen...
+private int QueryFish(object ob); // wird hier im Objekt in PreventInsert verwendet
+
+private int QueryFish(object ob) {
+  return (objectp(ob))&&(ob->id(FISCH_ID));
+}
+
+private int SetFactors(int good_value, int bad_value) {
+  FAC=good_value;
+  FOC=bad_value;
+  DIV=100;
+  if(!(FAC && FOC && DIV))
+    SetFactors(100,50);
+  return 1;
+}
+
+protected void create() {
+  if (!clonep(this_object())) return;
+  ::create();
+  SetFactors(100,50); //100% fuer frische, 50% fuer alte Fische
+  SetProp(P_NAME, "Fischwaage");
+  AddId(({"waage","fischwaage"}));
+  SetProp(P_GENDER, FEMALE);
+  SetProp(P_SHORT, "Eine Fischwaage");
+  SetProp(P_LONG,
+    "Eine sehr genaue Fischwaage mit einem grossen Zeiger. Du kannst\n"
+    "Deine Beute drauflegen, den Zeiger ablesen und, sofern Du mit\n"
+    "dem Preis einverstanden bist, die Verkaufsglocke laeuten.\n");
+  SetProp(P_DEST_PREPOSITION, "auf");
+  SetProp(P_SOURCE_PREPOSITION, "von");
+  SetProp(P_MATERIAL, MAT_MISC_METAL);
+  SetProp(P_TRANSPARENT, 1);
+  SetProp(P_NOGET, 1);
+  SetProp(P_MAX_WEIGHT, 10000);
+  SetProp(P_WEIGHT, 5000);
+  
+  AddDetail(({"zeiger"}), BS(
+    "Der Zeiger besteht aus Metall. Du kannst ihn ablesen, wenn Du "
+    "genau wissen willst, was Dein Fang wert ist."));
+  AddDetail(({"fang","beute"}), function string (string key) {
+    return BS(sizeof(all_inventory())?"Du schaust zufrieden auf die Beute, "
+      "die auf der Waage liegt. Welcher Preis sich dafuer wohl erzielen "
+      "laesst?":"Du muesstest erst einmal etwas drauflegen.");
+  });
+  AddReadDetail(({"zeige","zeiger ab"}), function string (string key) {
+    int current_weight = query_weight_contents();
+    get_price();
+    return
+      "Du schaust auf den grossen Zeiger der Waage, der erstaunlicherweise\n"
+      "nicht nur das Gewicht, sondern auch den Preis anzeigt.\n"
+      "Der Zeiger steht auf "+
+        (current_weight?current_weight+" Gramm.\n":"Null.\n")+
+      (good_price?good_price+" Goldmuenzen fuer fangfrischen Fisch.\n":"")+
+      (bad_price?bad_price+" Goldmuenzen fuer etwas aelteren Fisch.\n":"");
+  });
+  AddDetail(({"glocke"}), BS(
+    "An der Waage befindet sich eine kleine Glocke die Du laeuten kannst, "
+    "um den Inhalt der Waage zu verkaufen. Und warte damit nicht zu lange, "
+    "je aelter der Fisch, desto niedriger der Preis!"));
+
+  AddCmd("laeute&glocke|verkaufsglocke","cmd_laeute",
+    "Was willst Du denn laeuten?");
+}
+
+static int cmd_laeute(string str, mixed *param) {
+  tell_room(ME, TP->Name()+" laeutet eine kleine Glocke an der Fischwaage.",
+    ({TP}));
+  tell_object(TP, "Du laeutest die Glocke, um Deine Ware zu verkaufen.\n");
+  foreach(object ob: all_inventory(ME)) {
+    if ( !ob->id(FISCH_ID) ) {
+      tell_object(TP, 
+        "Auf der Waage liegt nicht nur Fisch!\n"
+        "Du solltest nicht versuchen, hier zu betruegen!\n");
+      tell_room(ME, TP->Name()+" macht sich hier gerade unbeliebt.\n",({TP}));
+      return 1;
+    }
+    if ( ob->QueryQuality()<=0 ) {
+      tell_object(TP, "Auf der Waage liegt alter, gammliger Fisch.\n"
+           "Den kannst Du nicht verkaufen!\n");
+      tell_room(ME, TP->Name()+" macht sich hier gerade unbeliebt.\n",({TP}));
+      return 1;
+    }
+  }
+  
+  int price=get_price();
+  if( !price ) {
+    tell_object(TP, 
+      "Du solltest Deine Beute erstmal auf die Waage legen!\n");
+    return 1;
+  }
+  tell_object(TP, "Du erhaeltst "+price+" Goldmuenzen fuer Deinen Fisch.\n");
+  tell_room(ME, TP->Name()+" erhaelt haufenweise Geld fuer "+
+    TP->QueryPossPronoun(MALE, WEN)+" Fisch.\n",({TP}));
+  //ZZ: AddMoney() gibt die werte von move() zurueck, d.h. !=0 geht nicht.
+  if (this_player()->AddMoney(price) != MOVE_OK) { 
+    object money=clone_object(GELD);
+    tell_object(TP, BS(
+      "Du kannst das Geld nicht mehr tragen. Es faellt klimpernd zu "
+      "Boden."));
+    money->SetProp(P_AMOUNT, price);
+    money->move(environment(ME), M_MOVE_ALL|M_PUT);
+  }
+  RemoveFish();
+  return 1;
+}
+
+private int get_price() {
+  int preis, preis_von_diesem;
+  int gewicht;
+
+  good_price     = 0;
+  bad_price      = 0;
+
+  foreach(object ob : all_inventory(ME)) {
+    preis_von_diesem = ob->QueryProp(P_VALUE);
+    if(ob->QueryQuality()>2)
+      good_price += preis_von_diesem*FAC/DIV;
+    else
+      bad_price +=preis_von_diesem *FOC/DIV;
+  }
+
+  good_price *= waagen_preis_faktor;
+  bad_price  *= waagen_preis_faktor;
+  return (good_price + bad_price);
+}
+
+int PreventInsert(object obj) {
+//  if( objectp(obj) && obj->QueryFish() )
+  if( objectp(obj) && QueryFish(obj) )
+    return ::PreventInsert(obj);
+  write("Das ist eine Fischwaage! Und keine Waage fuer "+obj->name(WEN)+
+    ".\n");
+  return 1;
+}
+
+#define ETO environment(this_object())
+
+private void RemoveFish() {
+  string pubname = ETO->GetPub();
+  object pub;
+
+  if ( stringp(pubname) )
+    pub = load_object(pubname);
+  else 
+    pub = ETO;
+
+  foreach(object ob : all_inventory(ME)) {
+    // pub->AddFishFood(ob);
+    // Amaryllis, 25.07.2015: Angepasst wegen AddFishFood von Fraggle
+    pub->AddFishFood(ob->name(WER,0),ob->QueryProp(P_WEIGHT),ob->QueryQuality());
+    ob->remove();
+  }
+}
+
+#undef ETO
diff --git a/items/fishing/graeten.c b/items/fishing/graeten.c
new file mode 100644
index 0000000..b960a04
--- /dev/null
+++ b/items/fishing/graeten.c
@@ -0,0 +1,22 @@
+inherit "/std/thing";
+
+#include <properties.h>
+
+protected void create() {
+  if ( !clonep(this_object()) ) {
+    set_next_reset(-1);
+    return;
+  }
+  ::create();
+
+  SetProp(P_SHORT, "Ein paar Graeten");
+  SetProp(P_LONG, "Einige Graeten, die von einem Fisch uebriggeblieben "
+    "sind.\n");
+  SetProp(P_PLURAL, 1),
+  SetProp(P_NAME, "Graeten");
+  AddId("graeten");
+  SetProp(P_WEIGHT, 3);
+  SetProp(P_VALUE, 1);
+  SetProp(P_NOBUY, 1);
+  SetProp(P_GENDER, FEMALE);
+}
diff --git a/items/fishing/haken.c b/items/fishing/haken.c
new file mode 100644
index 0000000..3152b67
--- /dev/null
+++ b/items/fishing/haken.c
@@ -0,0 +1,17 @@
+#pragma strong_types, save_types, rtt_checks
+#pragma no_inherit, no_shadow
+
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+#include <items/flasche.h>
+
+inherit STD_HAKEN;
+
+protected void create() {
+  ::create();
+  SetProp(P_NAME, "Haken");
+  SetProp(P_SHORT, "Ein Haken");
+  SetProp(P_LONG, "Ein Angelhaken aus Metall.\n");
+  SetProp(P_LONG_EMPTY, "Du kannst etwas damit aufspiessen!\n");
+}
diff --git a/items/fishing/khaut.c b/items/fishing/khaut.c
new file mode 100644
index 0000000..d1db082
--- /dev/null
+++ b/items/fishing/khaut.c
@@ -0,0 +1,18 @@
+inherit "/std/thing";
+
+#include <language.h>
+#include <properties.h>
+
+protected void create() {
+  if (!clonep(this_object())) return;
+  ::create();
+  AddId(({"haut","katzenhaihaut","schmirgelpapier","\nkhaut"}));
+  SetProp(P_NAME, "Haut");
+  SetProp(P_GENDER, FEMALE);
+  SetProp(P_SHORT, "Etwas Haut eines Katzenhaies" );
+  SetProp(P_LONG, "Ein Stueck der rauen Haut eines Katzenhaies.\n");
+  SetProp(P_MATERIAL,MAT_SKIN);
+  SetProp(P_VALUE,10);
+  SetProp(P_NOBUY,1);
+  SetProp(P_WEIGHT,2 );
+}
diff --git a/items/fishing/made.c b/items/fishing/made.c
new file mode 100644
index 0000000..b7dd0b3
--- /dev/null
+++ b/items/fishing/made.c
@@ -0,0 +1,19 @@
+#pragma strong_types, save_types, rtt_checks
+#pragma no_inherit, no_shadow
+
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_KOEDER;
+
+protected void create() {
+  ::create();
+  AddId(({WURM_ID,"made"}));
+  SetProp(P_NAME, "Made");
+  SetProp(P_GENDER , FEMALE);
+  SetProp(P_WATER, W_SWEET);
+  SetProp(P_FISH, 30);
+  SetProp(P_SHORT, "Eine Made");
+  SetProp(P_LONG, "Eine kleine eklige Made.\n");
+}
diff --git a/items/fishing/mehlwurm.c b/items/fishing/mehlwurm.c
new file mode 100644
index 0000000..89bd751
--- /dev/null
+++ b/items/fishing/mehlwurm.c
@@ -0,0 +1,18 @@
+#pragma strong_types, save_types, rtt_checks
+#pragma no_inherit, no_shadow
+
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_KOEDER;
+
+protected void create() {
+  ::create();
+  AddId(({"wurm","mehlwurm"}));
+  SetProp(P_NAME, "Mehlwurm");
+  SetProp(P_FISH, 10);
+  SetProp(P_WATER, W_SWEET);
+  SetProp(P_SHORT, "Ein Mehlwurm");
+  SetProp(P_LONG, "Ein kleiner Mehlwurm.\n");
+}
diff --git a/items/fishing/rute.c b/items/fishing/rute.c
new file mode 100644
index 0000000..496c571
--- /dev/null
+++ b/items/fishing/rute.c
@@ -0,0 +1,26 @@
+#pragma strong_types, save_types, rtt_checks
+#pragma no_inherit, no_shadow
+
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_ANGEL;
+
+protected void create() {
+  if (!clonep(this_object())) 
+    return;
+  ::create();
+
+  SetProp(P_NAME, "Angel");
+  SetProp(P_GENDER, FEMALE);
+  SetProp(P_SHORT, "Eine Angel");
+  SetProp(P_LONG, "Eine normale Angel.\n");
+  SetProp(P_TRANSPARENT, 1);
+  // 2014-Mai-10, Arathorn. von 1000 auf 1050 erhoeht, damit Haken+Koeder
+  // aufgrund ihres Gewichts von wenigen Gramm nicht mehr verhindern, dass
+  // einer der standardmaessig 1000 g schweren Fische gefangen werden kann.
+  SetProp(P_MAX_WEIGHT, 1050);
+  SetProp(P_WATER,W_SHORT);    //siehe fishing.h
+}
+
diff --git a/items/fishing/seasnail.c b/items/fishing/seasnail.c
new file mode 100644
index 0000000..2b6ded0
--- /dev/null
+++ b/items/fishing/seasnail.c
@@ -0,0 +1,48 @@
+#pragma strong_types, save_types, rtt_checks
+#pragma no_inherit, no_shadow
+
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_KOEDER;
+
+private int snailtype = random(8);
+
+private < <string|string*>*>* desc = ({
+//private mixed desc = ({ 
+    ({
+    "Eine purpurne Purpurschnecke.\n",
+    "Eine rosa-gestreifte Kreiselschnecke.\n",
+    "Eine suesse kleine Kaurischnecke.\n",
+    "Eine kleine rote Buckelschnecke.\n",
+    "Eine kleine gestrichelte Turbanschnecke.\n",
+    "Eine kleine gestreifte Lochnapfschnecke.\n",
+    "Ein gruenes Seeohr.\n",
+    "Eine suesse kleine Seeschnecke.\n" }),
+    ({
+    "purpurschnecke",
+    "kreiselschnecke",
+    "kaurischnecke",
+    "buckelschnecke",
+    "turbanschnecke",
+    "napfschnecke",
+    ({"ohr","seeohr"}),
+    "seeschnecke"})
+  });
+
+protected void create() {
+  ::create();
+  AddId(({WURM_ID, "schnecke", "\nfa_snails", "seeschnecke"}));
+  AddId(desc[1][snailtype]);
+  SetProp(P_NAME, "Schnecke");
+  SetProp(P_GENDER, FEMALE);
+  SetProp(P_ARTICLE, 1);
+  SetProp(P_SHORT, "Ein Seeschnecke");
+  SetProp(P_LONG, desc[0][snailtype]);
+  SetProp(P_MATERIAL, MAT_MISC_LIVING);
+  SetProp(P_FISH, snailtype*random(10));
+  SetProp(P_WATER, W_SALT);
+  SetProp(P_VALUE,1);
+  SetProp(P_WEIGHT, 5);
+}
diff --git a/items/fishing/shaken.c b/items/fishing/shaken.c
new file mode 100644
index 0000000..4bec621
--- /dev/null
+++ b/items/fishing/shaken.c
@@ -0,0 +1,62 @@
+#pragma strong_types, save_types, rtt_checks
+#pragma no_shadow, no_inherit
+
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+#include <items/flasche.h>
+
+inherit STD_HAKEN;
+
+protected void create() {
+  ::create();
+  AddId(({"spezialhaken"}));
+  SetProp(P_NAME, "Haken");
+  SetProp(P_ARTICLE, 1);
+  SetProp(P_WATER, W_UNIVERSAL);
+  SetProp(P_FISH, -20+random(60)); // -20 ... +39
+  SetProp(P_SHORT, "Ein Spezialhaken");
+  SetProp(P_LONG, break_string(
+    "Ein Angelhaken aus Metall. Es ist eine Spezialanfertigung aus Sam "
+    "Harkwinds Anglerladen, die einen kuenstlichen Wurm enthaelt.\n",78));
+  SetProp(P_INFO, break_string(
+    "Der kuenstliche Koeder soll in jedem Gewaesser recht gut "
+    "funktionieren, hat man Dir im Laden versprochen.",78));
+  
+  AddDetail(({"koeder","wurm"}), function string (string key) {
+    string desc = "Der Koeder ist handwerklich %s gelungen. Du glaubst, "
+      "dass er auf Fische %s wirken duerfte.";
+    string craft, effect;
+    switch(QueryProp(P_FISH)) {
+      case -20..-6:
+        craft = "ziemlich mies";
+        effect = "eher abstossend"; 
+        break;
+      case -5..9:
+        craft = "bestenfalls durchschnittlich";
+        effect = "genauso durchschnittlich";
+        break;
+      case 10..24:
+        craft = "wirklich solide";
+        effect = "recht appetitlich";
+        break;
+      case 25..39:
+        craft = "ueberragend";
+        effect = "unwiderstehlich";
+        break;
+      default: 
+        craft = "so la-la";
+        effect = "komisch";
+        break;
+    }
+    return break_string(sprintf(desc,craft,effect),78);
+  });
+
+  SetProp(P_LONG_EMPTY, "");
+  SetProp(P_VALUE, 20);
+  SetProp(P_WEIGHT, 10);
+}
+
+int QueryKoeder() { 
+  return 1; 
+}
diff --git a/items/fishing/strandrute.c b/items/fishing/strandrute.c
new file mode 100644
index 0000000..b7e8593
--- /dev/null
+++ b/items/fishing/strandrute.c
@@ -0,0 +1,25 @@
+#pragma strong_types, save_types, rtt_checks
+#pragma no_inherit, no_shadow
+
+#include <language.h>
+#include <properties.h>
+#include <fishing.h>
+
+inherit STD_ANGEL;
+
+protected void create() {
+  if (!clonep(this_object()))
+    return;
+  ::create();
+
+  SetProp(P_NAME, "Strandrute");
+  SetProp(P_GENDER, FEMALE);
+  SetProp(P_SHORT, "Eine sehr lange Angel");
+  SetProp(P_LONG, "Eine Angel speziell fuer die Strand-Fischerei.\n");
+  SetProp(P_TRANSPARENT, 1);
+  // 2014-Mai-10, Arathorn. von 1000 auf 1050 erhoeht, damit Haken+Koeder
+  // aufgrund ihres Gewichts von wenigen Gramm nicht mehr verhindern, dass
+  // einer der standardmaessig 1000 g schweren Fische gefangen werden kann.
+  SetProp(P_MAX_WEIGHT, 1050);
+  SetProp(P_WATER, W_LONG);
+}
diff --git a/items/fishing/wurm.c b/items/fishing/wurm.c
new file mode 100644
index 0000000..2b1ef62
--- /dev/null
+++ b/items/fishing/wurm.c
@@ -0,0 +1,6 @@
+#pragma strong_types, save_types, rtt_checks
+#pragma no_inherit, no_shadow
+
+#include <fishing.h>
+
+inherit STD_KOEDER;
diff --git a/items/flasche.c b/items/flasche.c
new file mode 100644
index 0000000..76026c9
--- /dev/null
+++ b/items/flasche.c
@@ -0,0 +1,3 @@
+#pragma strong_types,rtt_checks
+inherit "/std/items/flasche";
+
diff --git a/items/furz.c b/items/furz.c
new file mode 100644
index 0000000..b46b5a8
--- /dev/null
+++ b/items/furz.c
@@ -0,0 +1,108 @@
+/*
+Letzte Aenderung: 29.01.01 von Tilly (Zusatz-Abfrage in heart_beat() )
+                  25.08.01 von Tiamak (Tillys Abfragen debuggt ;^)
+*/
+#pragma strong_types,rtt_checks
+
+inherit "/std/thing";
+#include <properties.h>
+#include <language.h>
+#include <moving.h>
+
+int    alter;
+string furzerWER,furzerWESSEN;
+
+void create()
+{
+  if(!clonep(this_object())) return;
+  ::create();
+  SetProp(P_SHORT, 0);
+  SetProp(P_LONG, 0);
+  SetProp(P_INVIS,1);
+  SetProp(P_NAME, "Etwas");
+  SetProp(P_GENDER, 1);
+  SetProp(P_ARTICLE,0);
+  SetProp(P_NOGET,"Haeh?\n");
+  AddId("_furz_");
+  if (this_player())
+    AddId("Furz_"+getuid(this_player()));
+  alter = 0;
+  set_heart_beat(1);
+}
+
+void heart_beat()
+{
+  int i;
+  if(!environment())
+  {
+    set_heart_beat(0);
+    destruct(this_object());
+    return;
+  }
+  if(living(environment()))
+  {
+    set_heart_beat(0);
+    destruct(this_object());
+    return;
+  }
+  if (!alter)
+    tell_room(environment(), "Fuerchterlicher Gestank erfuellt den Raum.\n");
+  alter++;
+  if (!random(10))
+  {
+    i = random (5);
+    if (i==0)
+      tell_room(environment(), furzerWESSEN+" Furz stinkt wirklich grauenerregend.\n");
+    if (i==1)
+      tell_room(environment(), "Du haeltst Dir die Nase zu.\n");
+    if (i==2)
+      tell_room(environment(), "Widerliche Duenste erfuellen den Raum.\n");
+    if (i==3)
+      tell_room(environment(), "Der Furz riecht, als wuerde " + furzerWER +" innerlich verfaulen.\n");
+    if (i==4)
+      tell_room(environment(), "Du musst Dich beinah uebergeben, als " + furzerWESSEN + " Furz in Deine Nase kriecht.\n"); 
+  }
+  if (alter==45) {
+      tell_room(environment(), furzerWESSEN + " widerlicher Furz hat sich endlich verzogen.\n");
+      destruct(this_object());
+    }
+}
+
+
+void set_alter(int a)
+{ alter=a; }
+
+void set_furzer (object wer)
+{
+  if (objectp(wer))
+    {
+      furzerWER=wer->name(WER);
+      furzerWESSEN=wer->name(WESSEN);
+      AddId("Furz_"+getuid(wer));
+    }
+}
+
+varargs int move(mixed dest, int methods, string direction, string textout,string textin)
+{
+  int erg;
+  object otherfurz;
+
+  erg=::move(dest,methods,direction,textout,textin);
+  
+  // Vanion, 24.09.02: Kann sein, dass das move nich klappt,
+  //                   dann sollte das Objekt weg.
+  if (erg != MOVE_OK || !environment(this_object())) 
+  {
+    if (!remove()) destruct(this_object());
+    return 0;
+  }
+  if (this_player())
+    {
+      if (otherfurz=present("Furz_"+getuid(this_player())+" 2",environment()))
+	{
+	  otherfurz->set_alter(0);
+	  return remove();
+	}
+    }
+  return erg;
+}
diff --git a/items/kraeuter/eiszahn.c b/items/kraeuter/eiszahn.c
new file mode 100644
index 0000000..8f023de
--- /dev/null
+++ b/items/kraeuter/eiszahn.c
@@ -0,0 +1,36 @@
+// (c) 2001 by Padreic (Padreic@mg.mud.de)
+
+#pragma strong_types,rtt_checks
+
+#include <properties.h>
+#include <items/kraeuter/kraeuter.h>
+#include <items/kraeuter/kraeuterliste.h>
+
+inherit STDPLANT;
+void create()
+{ 
+  ::create();
+  customizeMe(EISZAHN);
+  SetProp(P_NAME,     "Eiszahn");
+  SetProp(P_NAME_ADJ, "kalt");
+  SetProp(P_GENDER,   MALE);
+  SetProp(P_LONG,
+    "Der Eiszahn ist ein ausgesprochen merkwuerdiges Kraut.\n"
+   +"Typisch sind die wie kleine Zaehne angeordneten Blaetter, die\n"
+   +"am Hauptstengel entlang wachsen und sich stets zum Himmel recken.\n"
+   +"Ausserdem strahlt das Kraut spuerbar Kaelte aus.\n");
+  SetProp(PLANT_ROOMDETAIL,
+     "Der Eiszahn fuehlt sich auf dem Eisboden sichtlich wohl.\n");
+  SetProp(P_SHORT,    "Ein Eiszahn");
+  AddId(({ "zahn", "eiszahn" }));
+  AddDetail("kraut",
+     "Der Eiszahn ist da sehr eigen: Er ist kein Pilz, er ist ein Kraut.\n");
+  AddDetail("kaelte", "Huah, ganz schoen kalt.\n");
+  AddDetail("blaetter",
+    "Die Blaetter sehen aus wie kleine Zaehne. Sie sind ganz weiss und\n"
+   +"ordentlich aufgereiht.\n");
+  AddDetail("hauptstengel",
+     "Eigentlich hat das Kraut nur einen Staengel, der leicht zur Seite haengt\n"
+    +"weil die 'Zaehne' ausreichend Gewicht haben.\n");
+  AddDetail("zaehne", "So nennt man die Blaetter des Eiszahns.\n");
+}
diff --git a/items/kraeuter/glockenblume.c b/items/kraeuter/glockenblume.c
new file mode 100644
index 0000000..163ad63
--- /dev/null
+++ b/items/kraeuter/glockenblume.c
@@ -0,0 +1,49 @@
+// (c) 2001 by Padreic (Padreic@mg.mud.de)
+// beschreibung magdalena@morgengrauen.de - 8.12.2003
+
+#pragma strong_types,rtt_checks
+
+#include <properties.h>
+#include <items/kraeuter/kraeuter.h>
+#include <items/kraeuter/kraeuterliste.h>
+
+inherit STDPLANT;
+
+#define BS(x) break_string(x, 78)
+
+
+void create()
+{
+  ::create();
+  customizeMe(GLOCKENBLUME);
+  SetProp(P_NAME,     "Glockenblume");
+  SetProp(P_NAME_ADJ, "schoen");
+  SetProp(P_GENDER,   FEMALE);
+  SetProp(P_LONG, BS(
+    "Die Bluetensterne in blau-violett sind ein toller Blickfang, wie "
+   +"sie am langen Stiel im Wind hin- und hernicken. Die "
+   +"glockenfoermige Blumenkrone mit ihren fuenf breiten, nicht bis zur "
+   +"Mitte reichenden Zipfeln erfreut Dich mit ihrer Schoenheit."));
+  SetProp(PLANT_ROOMDETAIL, 
+    "Eine anmutige, schoene Glockenblume nickt dir auffordernd zu. Ob man sie "
+   +"pfluecken kann?\n");
+  SetProp(P_SHORT,    "Eine Glockenblume");
+  AddId(({ "blume", "glockenblume" }));
+  
+  AddDetail(({"blickfang","schoenheit"}),BS(
+     "Diese Glockenblume besticht durch ihre Schoenheit. Ihre Farben sind " 
+    +"sind ein wahrer Blickfang.\n"));
+  AddDetail(({"farben","blueten"}),BS(
+     "Die Blueten der Glockenblume sind blau-violett.\n"));
+  AddDetail("blumenkrone",BS(
+     "Die Blume ist glockenfoermig. Daher hat die Pflanze ihren Namen.\n"));
+  AddDetail("pflanze",BS(
+     "Diese Pflanze ist eindeutig eine Glockenblume.\n"));
+  AddDetail(({"bluetensterne","sterne","zipfel","zipfeln"}),BS(
+     "Bemerkenswert an der Pflanze sind die Bluetensterne. Die blau-violetten "
+    +"Zipfel bilden die Bluete der Pflanze, was sehr auffaellig ist. Diese "
+    +"Bluetensterne gaben der Blume ihren Namen.\n"));
+
+}
+
+
diff --git a/items/kraeuter/kessel.c b/items/kraeuter/kessel.c
new file mode 100644
index 0000000..909eead
--- /dev/null
+++ b/items/kraeuter/kessel.c
@@ -0,0 +1,335 @@
+// (c) 2003 by Thomas Winheller (padreic@mg.mud.de)
+// Bei diesem File handelt es sich um einen universellen
+// Kessel zum Brauen von Traenken. Damit er sich in den
+// Raum entsprechend einpassen kann, ist er invis.
+
+// Ein Raum, in dem Traenke und Gift gebraut werden koennen
+// soll, braucht nichts weiter machen als:
+// -  eine Moeglichkeit zu implementieren Wasser in den Kessel
+//    zu fuellen. Hierzu muss dann mittels AddWater(3000)
+//    insgesamt 3l Wasser eingefuellt werden. AddWater gibt die
+//    Menge des tatsaechlich noch eingefuelltn Wassers zurueck.
+// Anmerkung: bisher enthaelt /obj/flasche noch keine Moeglichkeit
+//            Fluessigkeiten von einem Fluessigkeitencontainer in
+//            einen anderen zu schuetten, aber vielleicht aendert
+//            das ja irgendwann mal wer - der Kessel kann dann
+//            durch alle diese Flaschen befuellt werden!
+#pragma strong_types,rtt_checks
+
+inherit "/std/container";
+
+#include <defines.h>
+#include <properties.h>
+#include <moving.h>
+#include <fishing.h>
+#include <items/kraeuter/kraeuter.h>
+#include <items/flasche.h>
+
+#ifndef BS
+#  define BS(x)             break_string(x, 78)
+#endif
+
+private int wassermenge;
+
+// Aktueller Nutzer des Kessels in Form der Spieler-UID 
+private string current_user;
+
+// Zeitpunkt, wann die Sperre endet. 
+private int timeout;
+
+protected void create()
+{
+  ::create();
+  SetProp(P_SHORT, "Ein schwerer Kessel");
+  // \n werden in long() eingefuegt
+  SetProp(P_LONG,
+    "Ein kleiner, aber sehr schwerer Kessel, in dem die verschiedensten "
+    "Traenke gebraut werden koennen."); 
+  SetProp(P_NAME, "Kessel");
+  SetProp(P_NAME_ADJ, "klein");
+  SetProp(P_MATERIAL, MAT_BRONCE);
+  SetProp(P_NOGET, "Der Kessel ist zu schwer, um ihn einfach mitnehmen "
+     "zu koennen.\n");
+  SetProp(P_MAX_WEIGHT, 100000); // ein _wirklich_ grosser Kessel ;o)
+  SetProp(P_WEIGHT, 50000);
+  SetProp(P_VALUE, 25000);
+  SetProp(P_MAX_OBJECTS, 9); // max. 8 Kraeuter + Wasser
+  SetProp(P_GENDER, MALE);
+  SetProp(P_LIQUID, 3000); // in den Kessel passen 3l :o)
+  AddId(({"kessel", KESSELID}));
+  AddAdjective(({"klein", "kleiner"}));
+  AddCmd("leer|leere&@ID&aus", "cmd_leeren",
+    "Was moechtest Du leeren?|Moechtest Du den Kessel etwa ausleeren?");
+  AddCmd(({"brau", "braue", "koch", "koche"}), "cmd_brauen");
+  AddCmd("fuell|fuelle&trank|heiltrank|ergebnis|kesselinhalt|inhalt&in&"
+    "@PRESENT", "cmd_fuellen",
+    "Was willst Du fuellen?|Willst Du etwas in etwas fuellen?|"
+    "Worein willst Du den Kesselinhalt fuellen?");
+  AddCmd(({"tauch", "tauche"}), "cmd_tauchen");
+}
+
+#define TRANKFERTIG "_lib_p_krauttrankfertig"
+
+private int check_busy(int useronly)
+{
+  if (useronly)
+    return current_user && current_user != getuid(PL);
+  // Timeout darf noch nicht abgelaufen sein. Wird beim Entleeren geprueft.
+  return current_user && timeout > time() && current_user != getuid(PL);
+}
+
+private void clear_kessel()
+{
+  all_inventory()->remove(1);
+  // gespeicherte Daten nullen
+  wassermenge = current_user = timeout = 0;
+  SetProp(P_WATER, 0);
+  SetProp(TRANKFERTIG, 0);
+}
+
+int AddWater(int menge)
+{
+  // Wenn ein User eingetragen ist, dieser nicht PL ist und die Sperre
+  // auch noch nicht abgelaufen ist, dann wird das Einfuellen von Wasser
+  // verhindert. Nutzer der Funktion muessen die Rueckgabewerte pruefen
+  // und entsprechende Meldungen ausgeben.
+  if (check_busy(1))
+    return -1;
+
+  int old = wassermenge;
+  wassermenge = min(wassermenge+menge, QueryProp(P_LIQUID));
+
+  if (wassermenge<=0)
+  {
+    wassermenge=0; // wasser entnahme
+    SetProp(P_WATER, 0);
+  }
+  else
+     SetProp(P_WATER, W_DEAD);
+  return wassermenge-old;
+}
+
+static int cmd_leeren(string str)
+{
+  if (!QueryProp(P_WATER) && !sizeof(all_inventory()))
+  {
+    write(BS("Im Kessel ist bisher noch nichts enthalten, was Du ausleeren "
+             "koenntest."));
+  }
+  // Es gibt einen aktuellen User, dieser ist nicht PL, und der Timeout
+  // ist auch noch nicht abgelaufen => Finger weg.
+  else if (check_busy(0))
+  {
+    tell_object(PL, BS(
+      "Der Inhalt des Kessels wurde erst kuerzlich von jemand anderem dort "
+      "hineingefuellt. Du solltest Dich nicht daran zu schaffen machen."));
+  }
+  write("Vorsichtig nimmst Du den Kessel und schuettest seinen Inhalt in den Abfluss.\n");
+  say(BS(PL->Name(WER)+" nimmt den Kessel und schuettet den Inhalt in den Abfluss."));
+  clear_kessel();
+  return 1;
+}
+
+/*#include "/d/erzmagier/boing/balance/balance.h"
+#include <wizlevels.h>
+#define TESTER (BTEAM+({"elendil","saray", "huraxprax"}))*/
+static int cmd_brauen(string str)
+{
+  /*if (!IS_ARCH(this_interactive())
+      && !member(TESTER, PL->query_real_name()))
+    return 0;*/
+  
+  notify_fail("WAS moechtest Du brauen?\n");
+  if (!str) return 0;
+/*  if (str=="zaubertrank") {
+     write("Ohne passendes Rezept duerfte dies schwierig werden...\n");
+     return 1;
+  }*/
+  if (member(({"trank","zaubertrank","kraeutertrank","tee","kraeutertee"}),
+             str)<0) 
+    return 0;
+
+  if (check_busy(1)) {
+    tell_object(PL, BS(
+      "An dem Trank in dem Kessel arbeitet gerade noch "+
+      capitalize(current_user)+". Du kannst hoechstens in ein paar "
+      "Minuten versuchen, den Inhalt des Kessels auszuleeren. Selbst "
+      "Hand anzulegen, wuerde man Dir sicherlich uebelnehmen."));
+  }
+  else if (!QueryProp(P_WATER)) {
+    write("Vielleicht solltest Du zunaechst noch Wasser in den Kessel "
+      "fuellen...\n");
+  }
+  else if (wassermenge<QueryProp(P_LIQUID)) {
+    write("Vielleicht solltest Du zunaechst noch etwas mehr Wasser in "
+      "den Kessel\nfuellen...\n");
+  }
+  else if (sizeof(all_inventory())<3) {
+    write("Derzeit ist Dein Trank noch ein wenig waessrig.\n"
+         +"Mindestens drei Zutaten muessen in einen Trank schon hinein.\n");
+  }
+  else {
+    write(BS("Vorsichtig laesst Du den Kessel etwas naeher zur Feuerstelle "
+      "runter und wartest unter gelegentlichem Ruehren, bis er kocht. "
+      "Dein Trank sollte nun fertig sein und Du kannst ihn nun abfuellen. "
+      "Was er wohl fuer eine Wirkung haben wird?"));
+    say(BS(PL->Name()+" laesst den Kessel zur Feuerstelle herunter und "
+      "ruehrt langsam darin herum. Nach einer Weile kocht die Fluessigkeit "
+      "darin, und "+PL->Name(WER)+" stellt das Ruehren wieder ein."));
+    SetProp(TRANKFERTIG, 1);
+  }
+  return 1;
+}
+
+static int cmd_fuellen(string str,mixed* params)
+{
+/*  if (!IS_ARCH(this_interactive())
+      && !member(TESTER, this_player()->query_real_name()))
+    return 0;*/
+ 
+  if ( !QueryProp(TRANKFERTIG) ) 
+  {
+    write("Im Kessel befindet sich aber gar kein Trank.\n");
+  }
+  // Abfuellen ist nur fuer den Spieler moeglich, der die Kraeuter
+  // reingetan hat.
+  else if (check_busy(1))
+  {
+    tell_object(PL, BS("Diesen Trank hast Du doch gar nicht selbst "
+      "gebraut! Du solltest noch eine Weile warten, ob "+
+      capitalize(current_user)+" ihn nicht doch noch selbst abfuellen "
+      "will. Wenn nicht, koenntest Du nur noch versuchen, den Kessel "
+      "auszuleeren - jedenfalls es erscheint Dir viel zu riskant, das "
+      "Gebraeu selbst zu trinken, das "+capitalize(current_user)+
+      " da zusammengeruehrt hat."));
+  }
+  else if (BLUE_NAME(params[2])==TRANKITEM)
+  {
+    int ret = params[2]->Fill(all_inventory());
+    switch( ret ) {
+      case -3:
+      case -1:
+        write(BS("Fehler beim Fuellen der Phiole. Bitte sag einem Magier "
+          "Bescheid und nenne den Fehlercode "+ret+"."));
+        break;
+      case -2:
+        write(BS("Die Phiole ist bereits gefuellt."));
+        break;
+      default:
+        write(BS("Du nimmst den Kessel und fuellst seinen konzentrierten "
+          "Inhalt in Deine Glasflasche. Hoffentlich ist Dir hier ein "
+          "toller Trank gelungen."));
+        say(BS(PL->Name(WER)+" nimmt den Kessel und fuellt dessen "
+          "konzentrierten Inhalt in eine kleine Glasflasche. Was "+
+          PL->QueryPronoun(WER)+" da wohl gebraut hat?"));
+        clear_kessel();
+        break;
+    }
+  }
+  else {
+    write("Darein kannst Du den Trank leider nicht fuellen.\n");
+  }
+  return 1;
+}
+
+varargs string long(int mode)
+{
+  string inv_desc = make_invlist(PL, all_inventory(ME));
+  if (inv_desc=="") {
+    if (QueryProp(P_WATER))
+      return BS(Query(P_LONG)+" Derzeit ist er lediglich mit Wasser "
+        "gefuellt.");
+    return BS(Query(P_LONG)+" Er ist im Moment leer.");
+  }
+  if (QueryProp(P_WATER))
+    return BS(Query(P_LONG)+" Er ist mit Wasser gefuellt, und Du siehst "
+              +"folgende Kraeuter in ihm schwimmen:")+inv_desc;
+  return BS(Query(P_LONG))+"Er enthaelt:\n"+inv_desc;
+}
+
+static int _query_invis()
+{
+  if (member(({"nimm", "nehm", "nehme", "leg", "lege",
+               "steck", "stecke"}), query_verb())!=-1) return 0;
+  return Query(P_INVIS, F_VALUE);
+}
+/*
+varargs string name(int casus, int demon)
+{
+  SetProp(P_INVIS, 0);
+  string ret=::name(casus, demon);
+  SetProp(P_INVIS, 1);
+  return ret;
+}
+*/
+varargs int PreventInsert(object ob)
+{
+  int plantid = ob->QueryPlantId(); 
+  int *inv = all_inventory(ME)->QueryPlantId();
+  
+  // es koennen natuerlich nur echte Kraeuter in den Kessel gelegt werden
+  if ( plantid<=0 || !IS_PLANT(ob) )
+    return 1;
+  
+  if (QueryProp(TRANKFERTIG))
+  {
+    tell_object(PL, break_string(
+      "Im Kessel ist ein fertiger Trank. Wenn Du etwas neues machen "
+      "willst, leere den Kessel oder fuelle den Trank ab."));
+    return 1;
+  }
+  // Reintun darf nur der aktuelle User, es sei denn, ein anderer Spieler 
+  // faengt frisch an, wenn der Kessel gerade unbenutzt ist.
+  else if ( check_busy(1) )
+  {
+    tell_object(PL, BS("Dieser Kessel wurde bis gerade eben noch von "+
+      capitalize(current_user)+" genutzt. Warte besser, bis der Kessel "
+      "wieder frei ist."));
+    return 1;
+  }
+  else if ( !SECURE("krautmaster")->CanUseIngredient(PL, plantid) ) 
+  {
+    // mit Kraeutern ueber die man nichts weiss, kann man nicht brauen
+    tell_object(PL, BS("Ueber die Wirkungsweise von "+ob->name(WEM)+
+      " weisst Du bisher leider wirklich ueberhaupt nichts."));
+    return 1;
+  }
+  else if ( sizeof(inv) >= 8 ) 
+  {
+    tell_object(PL, BS("Mehr als acht Zutaten sollte man nie zu einem "
+      "Trank vereinigen, und es sind schon acht im Kessel."));
+    return 1;
+  }
+  else if (member(inv, plantid)>-1) 
+  {
+    tell_object(PL, BS("Im Kessel befindet sich bereits "+ob->name(WER)+
+      ". Du kannst kein Kraut mehr als einmal verwenden."));
+    return 1;
+  }
+  current_user = getuid(PL);
+  timeout = time()+120;
+  return ::PreventInsert(ob);
+}
+
+int PreventLeave(object ob, mixed dest)
+{
+  if (QueryProp(P_WATER)) {
+    tell_object(PL, BS("Es befindet sich bereits Wasser im Kessel, die "
+      "einzelnen Zutaten kannst Du nun leider nicht mehr einzeln "
+      "rausholen, ohne den ganzen Kessel auszuleeren."));
+      return 1;
+  }
+  // Rausnehmen ist nur fuer den aktuellen User moeglich. Alle anderen
+  // koennen auch nach Ablauf der Zeitsperre nur ausleeren.
+  else if ( check_busy(1) ) {
+    tell_object(PL, BS("Du hast "+ob->name(WEN,1)+" nicht dort hineingetan, "
+      "also kannst Du "+ob->QueryPronoun(WEN)+" auch nicht herausnehmen. "
+      "Zumindest vorerst nicht. Sollte "+capitalize(current_user)+
+      "nicht innerhalb der naechsten paar Minuten weiterbrauen, kannst "
+      "Du den Kesselinhalt zumindest mit einem guten Schluck Wasser "
+      "rausspuelen."));
+    return 1;
+  }
+  return ::PreventLeave(ob, dest);
+}
+
diff --git a/items/kraeuter/kicherpilz.c b/items/kraeuter/kicherpilz.c
new file mode 100644
index 0000000..a4b10a3
--- /dev/null
+++ b/items/kraeuter/kicherpilz.c
@@ -0,0 +1,51 @@
+// (c) 2001 by Padreic (Padreic@mg.mud.de)
+// Beschrieben von Magdalena :o) 08.08.03
+
+#pragma strong_types,rtt_checks
+
+#include <properties.h>
+#include <items/kraeuter/kraeuter.h>
+#include <items/kraeuter/kraeuterliste.h>
+
+inherit STDPLANT;
+
+#define BS(x) break_string(x, 78)
+
+void create()
+{
+  ::create();
+  customizeMe(KICHERPILZ);
+  SetProp(P_NAME,     "Kicherpilz");
+  SetProp(P_NAME_ADJ, "lustig");
+  SetProp(P_GENDER,   MALE);
+  SetProp(P_LONG,     
+    "Er hat ein gruenes Kaeppchen auf und ist fuer einen Pilz relativ gross. Ab und\n"
+   +"an zuckt er und kichert albern. Daher hat er wohl auch seinen Namen.\n");
+  SetProp(PLANT_ROOMDETAIL, 
+    "Ein besonders praechtiges Exemplar eines Kicherpilzes winkt dir\n"
+   +"aufdringlich zu, also ob es scharf darauf waere, gepflueckt zu werden.\n");
+  SetProp(P_SHORT,    "Ein Kicherpilz");
+  AddId(({ "pilz", "kicherpilz" }));
+  
+  AddDetail("kaeppchen",BS(
+     "Der Pilz scheint sich fuer die neueste Mode zu interessieren. "
+    +"Mit dem gruenen Kaeppchen ist er nach dem letzten Schrei gekleidet."));
+  AddDetail("mode",BS(
+     "Du schaust an deiner Kleidung hinunter - naja, mit dem Pilz "
+    +"kannst du nicht mithalten."));
+  AddDetail("schrei",BS(
+     "Sei ehrlich: Bei dem Gruen kann man nur schreien!"));
+  AddDetail("gruen",BS(
+     "Eigentlich ist es doch ganz gut, sich nicht fuer Mode zu "
+    +"interessieren, denn das Gruen schmerzt in den Augen."));
+ 
+  set_next_reset(200+random(200));
+}
+
+void reset()
+{
+   set_next_reset(200+random(200));
+   if (environment()) 
+      tell_object(environment(), "Der Kicherpilz kichert Dich an.\n"); 
+   ::reset();
+}
diff --git a/items/kraeuter/kraut.c b/items/kraeuter/kraut.c
new file mode 100644
index 0000000..55b3429
--- /dev/null
+++ b/items/kraeuter/kraut.c
@@ -0,0 +1,26 @@
+#pragma strong_types,rtt_checks
+
+#include <items/kraeuter/kraeuter.h>
+
+inherit STDPLANT;
+
+void create()
+{
+  ::create();
+  //printf("create(): %O\n",load_name());
+  //replace_program();
+  // Wenn es das Standardfile geclont wird, wird customizeMe(0) gerufen, was
+  // den Kraeuter-VC dazu bringt, dieses mit den Daten des Krautes zu
+  // konfigurieren, was der VC gerade erzeugt hat.
+  // load_name() bleibt fuer alle VC-erzeugten Kraeuter-Blueprints das
+  // PLANTITEM.
+  // hier darf _nicht_ previous_object()->CustomizeObject() verwandt werden,
+  // da nur die Blueprint wirklich vom VC erzeugt wird. Fuer die Clones
+  // ruft der Driver den VC nicht jedesmal erneut auf.
+  if (load_name() == PLANTITEM)
+    customizeMe(0);
+}
+
+string GetOwner() {
+  return "Padreic";
+}
diff --git a/items/kraeuter/trank.c b/items/kraeuter/trank.c
new file mode 100644
index 0000000..757b42f
--- /dev/null
+++ b/items/kraeuter/trank.c
@@ -0,0 +1,13 @@
+#pragma strong_types,rtt_checks
+
+#include <items/kraeuter/kraeuter.h>
+
+inherit STDTRANK;
+/*
+void create()
+{
+  ::create();
+  replace_program();
+}
+*/
+
diff --git a/items/kraeuter/trockner.c b/items/kraeuter/trockner.c
new file mode 100644
index 0000000..62e7417
--- /dev/null
+++ b/items/kraeuter/trockner.c
@@ -0,0 +1,475 @@
+#pragma strong_types, save_types, rtt_checks
+#pragma no_inherit, no_shadow
+
+inherit "/std/container";
+
+#include <properties.h>
+#include <defines.h>
+#include <items/kraeuter/kraeuter.h>
+
+#define BS(x) break_string(x, 78, 0, BS_LEAVE_MY_LFS)
+
+// Enthaelt die raumabhaengig variable Kurzbeschreibung, die der Trockner 
+// annimmt, wenn gerade ein Kraut getrocknet wird.
+private string short_desc;
+
+// Globale Variable fuer die Qualitaet, damit man den Wert nicht im 
+// call_out() mitgeben muss, und sie somit auch nicht mit call_out_info()
+// abfragbar ist.
+private int drying_quality;
+
+private void dry_plant(object kraut, string *msgs);
+private void destroy_herb(object kraut);
+private string my_short();
+private int|string my_noget();
+private string my_long();
+private string* my_ids();
+private string|string* my_name();
+private mixed my_mat();
+
+protected void create() {
+  if ( !clonep(ME) ) {
+    set_next_reset(-1);
+    return;
+  }
+  ::create();
+
+  Set(P_SHORT, #'my_short, F_QUERY_METHOD);
+  Set(P_LONG, #'my_long, F_QUERY_METHOD);
+  Set(P_NOGET, #'my_noget, F_QUERY_METHOD);
+  Set(P_IDS, #'my_ids, F_QUERY_METHOD);
+  Set(P_NAME, #'my_name, F_QUERY_METHOD);
+  Set(P_MATERIAL, #'my_mat, F_QUERY_METHOD);
+  // Properties zu securen ist vielleicht etwas sehr paranoid.
+  Set(P_SHORT, SECURED|NOSETMETHOD, F_MODE_AS);
+  Set(P_LONG, SECURED|NOSETMETHOD, F_MODE_AS);
+  Set(P_NOGET, SECURED|NOSETMETHOD, F_MODE_AS);
+  Set(P_IDS, SECURED|NOSETMETHOD, F_MODE_AS);
+  Set(P_NAME, SECURED|NOSETMETHOD, F_MODE_AS);
+  SetProp(P_MAX_OBJECTS,1);
+  SetProp(P_MAX_WEIGHT,100000);
+  SetProp(P_TRANSPARENT,0);
+
+  AddCmd("trockne&@PRESENT", "cmd_trocknen", "Was willst Du trocknen?");
+}
+
+private string my_short() {
+  if ( first_inventory(ME) )
+    return short_desc;
+  return 0;
+}
+
+// Querymethoden, die Langbeschreibung und weitere Properties des im 
+// Trockner enthaltenen Krautobjektes nach draussen weiterreichen, um die
+// Illusion zu erzeugen, dass wirklich das echte Kraut im Raum zu sehen sei.
+// Alle Funktionen gehen davon aus, dass das zu trocknende Kraut das erste
+// (und einzige) Objekt im Inventar des Trockners ist und geben dessen
+// Properties zurueck.
+private string my_long() {
+  object inv = first_inventory(ME);
+  if ( objectp(inv) )
+    return inv->QueryProp(P_LONG)+inv->Name(WER,1)+
+      " wird gerade getrocknet.\n";
+  return 0;
+}
+
+private string|string* my_name() {
+  object inv = first_inventory(ME);
+  if ( objectp(inv) )
+    return inv->QueryProp(P_NAME);
+  return Query(P_NAME,F_VALUE);
+}
+
+private mixed my_mat() {
+  object inv = first_inventory(ME);
+  if ( objectp(inv) )
+    return inv->QueryProp(P_MATERIAL);
+  return ([]);
+}
+
+private int|string my_noget() {
+  object inv = first_inventory(ME);
+  if ( objectp(inv) )
+    return inv->Name(WER,1)+" wird gerade getrocknet, Du solltest "+
+      inv->QueryPronoun(WEN)+" liegenlassen, bis "+
+      inv->QueryPronoun(WER)+" fertig ist.";
+  return 1;
+}
+
+private string* my_ids() {
+  object inv = first_inventory(ME);
+  if ( objectp(inv) )
+    return inv->QueryProp(P_IDS);
+  return Query(P_IDS,F_VALUE);
+}
+
+// Kommandofunktion zum Starten des Tocknungsvorganges. Holt sich die
+// relevanten Daten aus dem Krautmaster ab, setzt Meldungen und Texte und
+// wirft den Trocknungs-Callout an.
+static int cmd_trocknen(string str, mixed *param) {
+  // Master liefert leeres Array oder eins mit 2 Elementen ({delay, quality})
+  // environment(ME) liest er selbstaendig aus
+  int *drying_data = PLANTMASTER->QueryDryingData();
+  object kraut = param[0];
+
+  // Der Trockner taeuscht vor, selbst das Kraut zu sein, das zum Trocknen
+  // im Raum liegt. Daher wird hier noch geprueft, ob der Spieler vielleicht
+  // den Trockner selbst zu trocknen versucht. 
+  if ( kraut == ME ) {
+    tell_object(PL, BS(kraut->Name(WER,1)+" wird bereits getrocknet, Du "
+      "solltest "+kraut->QueryPronoun(WEN)+" besser liegenlassen."));
+  }
+  // Es muss sich auch um ein Kraut handeln und nicht irgendwas anderes.
+  else if ( load_name(kraut) != PLANTITEM ) {
+    return 0;
+  }
+  // Spieler muss das Kraut im Inventar haben.
+  else if ( environment(kraut) != PL ) {
+    tell_object(PL, BS(
+      "Du musst "+kraut->name(WEN,1)+" schon in die Hand nehmen, um "+
+      kraut->QueryPronoun(WEN)+" sorgfaeltig trocknen zu koennen."));
+  }
+  // Das Kraut darf nicht unwirksam sein, was durch eine Plant-ID von -1 
+  // gekennzeichet ist.
+  else if ( param[0]->QueryPlantId() == -1 ) {
+    tell_object(PL, BS(
+      kraut->Name(WER,1)+" haette ohnehin keine Wirkung, da kannst Du Dir "
+      "die Muehe sparen, "+kraut->QueryPronoun(WEN)+" noch aufwendig zu "
+      "trocknen."));
+  }
+  // Master hat keine Daten geliefert, also befindet sich der Trockner
+  // offenbar in einem unzulaessigen Raum.
+  else if ( sizeof(drying_data) != 2 ) {
+    tell_object(PL, BS(
+      "Dieser Ort ist nicht geeignet, um "+kraut->name(WEN,1)+" hier zu "
+      "trocknen."));
+  }
+  // Kraut ist schon getrocknet? Dann waere eine weitere Trocknung unsinnig.
+  else if ( kraut->QueryDried() ) {
+    tell_object(PL, BS(kraut->Name(WER,1)+" ist schon getrocknet, eine "
+      "weitere Behandlung wuerde "+kraut->QueryPronoun(WEM)+" zu stark "
+      "zusetzen, "+kraut->QueryPronoun(WEN)+" gar zerstoeren."));
+  }
+  // Es ist schon eine Pflanze im Trockner? Dann nicht noch eine reintun.
+  else if ( first_inventory(ME) ) {
+    tell_object(PL, BS("Hier wird gerade schon etwas getrocknet."));
+  }
+  // Aus irgendeinem Grund schlaegt die Bewegung des Krautes in den Trockner
+  // fehl? Dann muss sich das ein Magier anschauen, denn das geht nicht mit
+  // rechten Dingen zu.
+  else if ( kraut->move(ME, M_PUT) != MOVE_OK ) {
+    tell_object(PL, BS("Aus einem Dir unerfindlichen Grund schaffst Du es "
+      "nicht, die Trocknung "+kraut->name(WESSEN,1)+" zufriedenstellend "
+      "durchzufuehren und brichst den Versuch wieder ab. Du solltest einem "
+      "Magier Bescheid sagen, dass hier etwas nicht stimmt."));
+  }
+  // Alles geklappt, alle Bedingungen erfuellt? Dann koennen wir jetzt
+  // tatsaechlich endlich das Kraut trocknen.
+  else {
+    int drying_delay = drying_data[0]; // nur lokal benoetigt
+    drying_quality = drying_data[1]; // globale Variable
+    string where = load_name(environment(ME));
+    string msg_self, msg_other;
+    string kr = kraut->name(WEN,1);
+    string* callout_msgs = ({
+        kraut->Name(WER,1)+" ist jetzt in einem zufriedenstellenden "
+        "Zustand. Besser wirst Du es an diesem Ort vermutlich nicht "
+        "hinbekommen, daher beendest Du die Trocknung und nimmst "+
+        kraut->QueryPronoun(WEN)+" wieder an Dich.",
+        PL->Name(WER)+" schaut "+kr+" pruefend an und "
+        "beendet dann die Trocknung, offenbar zufrieden mit dem Resultat."});
+    int blocker; // auf 1 setzen, falls das Trocknen verhindert werden soll
+    // Hier koennen jetzt abhaengig vom Raum passende Meldungen gesetzt
+    // werden. Die zulaessigen Standorte hier noch weiter zu obfuscaten
+    // waere zwar moeglich, aber zu unuebersichtlich geworden.
+    switch(where) {
+      /*
+       * GEBIRGE 
+       */
+      case "/d/gebirge/silvana/cronoertal/room/th7u":
+        msg_self = "Du legst "+kr+" vorsichtig und in gebuehrendem Abstand "
+          "zu den Flammen neben die Feuerstelle und wartest gespannt, ob "
+          "die Trocknung wohl gelingen wird.";
+        msg_other = PL->Name(WER)+" legt etwas neben die Feuerstelle, "
+          "vermutlich, um es zu trocknen.";
+        short_desc = kraut->Name(WER)+" liegt zum Trocknen am Feuer";
+        break;
+      /*
+       * EBENE 
+       */
+      case "/d/ebene/zardoz/burg/kueche":
+        msg_self = "Du legst "+kr+" vorsichtig an eine der kuehleren "
+          "Stellen des Bleches im Ofen, es soll ja trocknen, und nicht "
+          "backen.";
+        msg_other = PL->Name(WER)+" legt etwas Gruenzeug auf das Blech im "
+          "Ofen.";
+        short_desc = kraut->Name(WER)+" liegt zum Trocknen im Ofen";
+        break;
+      case "/d/ebene/esme/masinya/rooms/kueche":
+        msg_self = "Du haengst "+kr+" ueber den Herd, um "+
+          kraut->QueryPronoun(WEN)+" in der Abwaerme trocknen zu lassen.";
+        msg_other = PL->Name(WER)+" haengt ein Kraut zum Trocknen ueber "
+          "den Herd.";
+        short_desc = kraut->Name(WER)+" haengt zum Trocknen ueber dem Herd";
+        break;
+      case "/d/ebene/throin/brauerei/room/darre06":
+        msg_self = "Du legst "+kr+" zu dem Malz in den "
+          "Keimkasten in der Hoffnung, dass "+kraut->QueryPronoun(WER)+
+          " auf diese Weise getrocknet werden kann.";
+        msg_other = PL->Name(WER)+" legt etwas eigenes Gruenzeug zu dem "
+          "Malz in den Keimkasten.";
+        short_desc = kraut->Name(WER)+" liegt zum Trocknen im Keimkasten";
+        break;
+      case "/d/ebene/arathorn/orakel/room/zelt":
+        msg_self = "Du legst "+kr+" vorsichtig ans "
+          "Lagerfeuer. Du schaust unsicher zu Chinkuwaila, doch der "
+          "alte Schamane nickt zustimmend, Du hast wohl alles richtig "
+          "gemacht.";
+        msg_other = PL->Name(WER)+" legt eine Pflanze ans Lagerfeuer, wohl "
+          "um sie zu trocknen.";
+        short_desc = kraut->Name(WER)+" wird gerade am Lagerfeuer getrocknet";
+        break;
+      /*
+       * WUESTE
+       */
+      case "/d/wueste/tsunami/schule/rooms/kraeuter":
+        blocker = objectp(present_clone("/d/wueste/tsunami/schule/mon/hexe", 
+                    environment(ME)));
+        if ( !blocker ) {
+          msg_self = "Du steckst "+kr+" in Muetterchen "
+            "Isewinds Trockenofen, der wohlig zu knistern beginnt.";
+          msg_other = PL->Name(WER)+" legt vorsichtig ein Kraut ";
+          short_desc = kraut->Name(WER)+" wird gerade im Ofen getrocknet";
+        }
+        else {
+          msg_self = "Muetterchen Isewind haelt Dich auf, sie scheint "
+            "niemanden an ihren Trockenofen heranlassen zu wollen.";
+          msg_other = PL->Name(WER)+" wird von Muetterchen Isewind an der "
+            "Benutzung des Ofens gehindert.";
+        }
+        break;
+      /*
+       * WALD
+       */
+      case "/d/wald/feigling/quest/room/huette3":
+        msg_self = "Du legst "+kr+" so nah ans Feuer, "
+          "wie Du glaubst, dass es der Trocknung nicht schadet.";
+        msg_other = PL->Name()+" legt eine Pflanze an die Kochstelle.";
+        short_desc = kraut->Name(WER)+" liegt zum Trocknen an der "
+          "Feuerstelle";
+        break;
+      case "/d/wald/leusel/quest/rooms/laborsuedosten":
+        msg_self = "Du legst "+kr+" in eins der "
+          "Tonschiffchen und schiebst es in den mittelheissen Ofen hinein. "
+          "Hoffentlich geht das gut, es kommt Dir da drinnen schon fast zu "
+          "warm fuer eine ordnungsgemaesse Trocknung vor.";
+        msg_other = PL->Name(WER)+" schiebt ein Kraut in einem "
+          "Tonschiffchen in einen der Oefen hinein, um es zu trocknen.";
+        short_desc = kraut->Name(WER)+" dampft in einem Tonschiffchen im "
+          "ersten Ofen vor sich hin";
+        break;
+      /*
+       * INSELN
+       */
+      case "/d/inseln/zesstra/vulkanweg/room/r8":
+        msg_self = "Du legst "+kr+" vorsichtig auf die "
+          "heissen Felsen in der Naehe des Lavasees, auf dass die "
+          "heissen Winde "+kraut->QueryPronoun(WEN)+" trocknen moegen.";
+        msg_other = PL->Name(WER)+" legt ein Kraut auf den Felsen ab, um es "
+          "von der heissen Luft trocknen zu lassen.";
+        short_desc = kraut->Name(WER)+" liegt zum Trocknen auf dem Felsen";
+        break;
+      case "/d/inseln/miril/zyklopen/room/palast/insel1p6":
+        // QueryOven() liefert 2 fuer "Feuer", 1 fuer "Glut", 0 fuer "aus".
+        switch (environment(ME)->QueryOven()) {
+          case 2:
+            msg_self = "Du legst "+kr+" vorsichtig an das Feuer, das in "
+              "der Feuerstelle brennt, sorgsam bemueht, dass "+
+              kraut->QueryPronoun(WER)+" nicht zuviel Hitze abbekommt.";
+            msg_other = PL->Name(WER)+" legt sorgsam ein Kraut in die Naehe "
+              "des Feuers, das in der Feuerstelle brennt.";
+            break;
+          case 1:
+            msg_self = "Du legst "+kr+" an die Feuerstelle, pruefst die "
+              "Hitze und rueckst "+kraut->QueryPronoun(WEN)+" noch etwas "
+              "naeher an die Glut, dann trittst Du zufrieden einen Schritt "
+              "zurueck.";
+            msg_other = PL->Name(WER)+" legt "+kraut->name(WEN)+" an die "
+              "Feuerstelle, schubst noch ein wenig daran herum und tritt "
+              "dann von der Glut zurueck, "+PL->QueryPronoun(WER)+" scheint "
+              "recht zufrieden zu sein.";
+            break;
+          default:
+            blocker=1;
+            msg_self = "In dem Kamin findest Du nicht einmal etwas Glut, "
+              "geschweige denn offenes Feuer. So wird das mit dem Trocknen "
+              "nichts, und auf dem Herd ist Dir das Risiko zu gross, dass "
+              "Fett aus der Pfanne auf "+kr+" spritzt.";
+            break;
+        }
+        short_desc = kraut->Name(WER)+" liegt zum Trocknen an der "
+          "Feuerstelle";
+        break;
+      /*
+       * POLAR
+       */
+      case "/d/polar/tilly/llp/rentner/kueche":
+        msg_self = "Der Herd gibt eine infernalische Hitze ab. Zum Kochen "
+          "ist das toll, aber Du brauchst doch einen Moment, um ein "
+          "geeignetes Plaetzchen fuer "+kr+" zu finden.";
+        msg_other = PL->Name(WER)+" legt ein Kraut auf den heissen Herd "
+          "und schiebt es unruhig noch ein wenig hin und her, als waere "+
+          PL->QueryPronoun(WEM)+" die Hitze beinahe ein wenig zu gross.";
+        short_desc = kraut->Name(WER)+" liegt auf dem schmiedeeisernen "
+          "Herd";
+        break;
+      /*
+       * VLAND
+       */
+      case "/d/vland/morgoth/room/kata/ukat13":
+        object c = present_clone("/d/vland/morgoth/obj/kata/rfdcorpse", 
+              environment(ME));
+        // Bequemer, das auf 0 zu setzen, wenn's klappt, bei sovielen
+        // Hinderungsgruenden. ;-)
+        blocker = 1;
+        // Leiche liegt da.
+        if ( objectp(c) ) 
+        {
+          // Feuerdaemon anwesend: der blockt den Versuch
+          if ( present_clone("/d/vland/morgoth/npc/kata/firedemon3",
+                environment(ME)) ) 
+          {
+            msg_self = "Der Feuerdaemon droht Dir mit sengender Hoellenpein. "
+              "Beschwichtigend trittst Du einen Schritt zurueck.";
+            msg_other = PL->Name(WER)+" tritt auf den Aschehaufen zu, wird "
+              "aber von dem Feuerdaemon bedroht und weicht wieder zurueck.";
+          }
+          // Aschehaufen nicht mehr heiss genug?
+          else if ( c->QueryDecay()<2 ) {
+            msg_self = c->Name(WER,1)+" ist schon zu sehr abgekuehlt und "
+              "wuerde nicht mehr genug Hitze spenden, um "+kr+" zu trocknen.";
+          }
+          else 
+          {
+            blocker = 0;
+            msg_self = "Dich vorsichtig umschauend, legst Du "+kr+" in die "
+              "Naehe "+c->name(WESSEN,1)+". Hoffentlich gelingt das in "
+              "dieser unwirtlichen Umgebung!";
+            msg_other = PL->Name(WER)+" beugt sich zum Boden hinuntern und "
+              "legt vorsichtig ein Kraut in die Naehe "+c->name(WESSEN,1)+".";
+          }
+          short_desc = kraut->Name(WER)+" liegt neben "+c->name(WEM,1)+
+            ", offenbar soll "+kraut->QueryPronoun(WER)+" getrocknet werden";
+        }
+        // Keine Leiche da? Dann geht's nicht.
+        else {
+          msg_self = "Genausowenig, wie Dir die Flammen in diesem Inferno "
+            "etwas anhaben koennen, so wenig kannst Du sie nutzen, um "+
+            kr+" zu trocknen.";
+        }
+        break;
+      case "/d/vland/morgoth/room/kata/kata5":
+        object ob = present_clone("/d/vland/morgoth/npc/kata/ghost",
+            environment(ME));
+        blocker = 1;
+        // Geist anwesend? Keine Chance.
+        if ( objectp(ob) ) {
+          msg_self = ob->Name(WER,1)+" stoert Dich in Deiner Konzentration, "
+            "Du kannst so nicht arbeiten!";
+        }
+        // Umgebung noch neblig? Dann nicht trocknen.
+        else if ( environment(ME)->QueryFog() ) {
+          msg_self = "In diesem verdammten Nebel ist absolut nichts zu "
+            "sehen. Ausserdem ist es hier viel zu feucht, "+kr+" wuerde "
+            "ohnehin nur vor Deiner Nase wegschimmeln.";
+        }
+        // Feuer brennt nur noch 90 Sekunden? Dann lohnt sich das nicht.
+        else if ( query_next_reset(environment()) < time()+90 ) {
+          msg_self = "Ein pruefender Blick auf das Feuer zeigt Dir, dass "
+            "es wohl nicht mehr lange genug brennen wird, um "+kr+" noch "
+            "erfolgreich trocknen zu koennen.";
+        }
+        else {
+          blocker = 0;
+          msg_self = "Du legst "+kr+" in angemessenem Abstand zum Feuer "
+            "auf den Boden und wartest gespannt, ob Dir hier wohl eine "
+            "brauchbare Trocknung gelingen wird.";
+          msg_other = PL->Name(WER)+" bueckt sich zum Boden und legt etwas "
+            "ans Feuer, anscheinend ein Kraut, das "+PL->QueryPronoun(WER)+
+            " trocknen will.";
+          short_desc = kraut->Name(WER)+" liegt zum Trocknen am Feuer";
+        }
+        break;
+      case "/d/vland/alle/koomi_v/wschenke/room/waldschenke":
+        msg_self = "Dieser Kachelofen ist ungemein praktisch. Du legst "+
+          kr+" einfach oben drauf, und die kuschelige Waerme trocknet "+
+          kraut->QueryPronoun(WEN)+" beinahe von selbst.";
+        msg_other = PL->Name(WER)+" legt ein Kraut zum Trocknen oben auf "
+          "den Kachelofen, offenbar recht angetan von dessen kuscheliger "
+          "Waerme.";
+        short_desc = kraut->Name(WER)+" liegt zum Trocknen auf dem "
+          "Kachelofen";
+        break;
+      /*
+       * DEBUGZWECKE
+       */
+      case "/players/arathorn/workroom":
+        msg_self = "Du haeltst das Kraut vors Feuer und beginnst die "
+          "Trocknung.";
+        msg_other = PL->Name(WER)+" schickt sich an, ein Kraut am Feuer zu "
+          "trocknen.";
+        short_desc = kraut->Name(WER)+" liegt zum Trocknen am Feuer";
+        break;
+    }
+    // Raummeldungen entsprechend der eingestellten Texte ausgeben.
+    tell_object(PL, BS(msg_self));
+    if ( msg_other )
+      tell_room(environment(ME), BS(msg_other), ({PL}));
+    // Callout starten, wenn niemand das Trocknen verhindert.
+    if ( !blocker )
+      call_out(#'dry_plant, drying_delay, kraut, callout_msgs);
+    // Ansonsten das Kraut in den Spieler zurueck, das ja oben schon
+    // in den Trockner bewegt wurde.
+    else {
+      kraut->move(PL, M_GET);
+    }
+  }
+  return 1;
+}
+
+// Kraut wird getrocknet, sofern der Spieler noch im Raum ist, ...
+private void dry_plant(object kraut, string *msgs) {
+  if ( objectp(PL) && environment(PL) == environment(ME) ) {
+    tell_object(PL, BS(msgs[0]));
+    tell_room(environment(ME), BS(msgs[1]), ({PL}));
+    kraut->move(PL, M_GET);
+    kraut->DryPlant(drying_quality);
+  }
+  // ... ansonsten laeuft die Trocknung weiter, und das Kraut verbrennt.
+  else {
+    tell_room(ME, BS(kraut->Name(WER,1)+" wird extrem dunkel, bald wird "+
+      kraut->QueryPronoun(WER)+" zu nichts mehr zu gebrauchen sein!"));
+    // Das Delay fuer diesen zweiten Callout ist immer fix. Kommt hoffentlich
+    // selten genug vor und braucht daher eher nicht extra aus dem Master
+    // geholt zu werden.
+    call_out(#'destroy_herb, 20, kraut);
+  }
+}
+
+// Zerstoerung des Krautes. Da die Krautobjekte selbst eine Meldung 
+// ausgeben, wenn DryPlant(0) gerufen wird, wird erst das Kraut ins
+// Environment bewegt und erst danach die Funktion gerufen.
+private void destroy_herb(object kraut) {
+  kraut->move(environment(ME),M_PUT);
+  kraut->DryPlant(0);
+}
+
+// Nur die korrekten Krautobjekte koennen in den Trockner bewegt werden.
+// Schuetzt natuerlich nicht vor M_NOCHECK, aber wenn das vorkommen sollte,
+// muss vielleicht noch weiter abgesichert werden, oder der verursachende
+// Magier ausgeschimpft. ;-) 
+varargs int PreventInsert(object ob) {
+  if (load_name(ob) == PLANTITEM && clonep(ob)) 
+    return ::PreventInsert(ob);
+  return 1;
+}
diff --git a/items/kraeuter/virtual_compiler.c b/items/kraeuter/virtual_compiler.c
new file mode 100644
index 0000000..d48370e
--- /dev/null
+++ b/items/kraeuter/virtual_compiler.c
@@ -0,0 +1,300 @@
+// (c) by Padreic (Padreic@mg.mud.de)
+
+#pragma no_inherit,no_clone,strong_types,rtt_checks
+
+#include <defines.h>
+#include <properties.h>
+#include <v_compiler.h>
+#include <items/kraeuter/kraeuter.h>
+#include <wizlevels.h>
+
+inherit "/std/virtual/v_compiler";
+inherit "/std/thing/language";
+inherit "/std/thing/description";
+
+// mit Hilfe dieses mappings kommt man sowohl an die ID und die Eigenschaften,
+// als auch an die Liste der Raeume in denen das Kraut mit dem filenamen room
+// gefunden werden kann.
+// ([ "key": ({ ({eigenschaften}), ([raeume]) }) ])
+private mapping krautdaten;
+
+// AN: enthaelt die Liste der gueltigen Kraeuter-Dateinamen ohne .c
+// am Ende. Ich vermute, dass es deswegen ein Mapping ist, damit in 
+// Validate() einfach member() drauf gemacht werden kann und man nur 0/1
+// als Rueckgabewerte pruefen muss, statt -1 bei nem member() auf ein Array.
+private mapping validfiles;
+
+public void update(mapping data)
+{
+  if (previous_object() == find_object(PLANTMASTER))
+  {
+    krautdaten = data;
+    validfiles = mkmapping(m_indices(krautdaten));
+  }
+}
+
+// Wird benutzt, um kurze IDs von Kraeutern zu raten. Diese IDs werden
+// eingetragen, wenn der Krautname die ID als Teilstring enthaelt.
+#define IDLIST ({ "klee", "rebe", "hahnenfuss", "rettich", "kraut", "wurz",\
+                     "moos", "enzian", "rautenwicke", "pilz", "nelke",\
+                     "lichtnelke", "wicke", "zwiebel", "hanf", "kresse"})
+
+void create()
+{
+   seteuid(getuid());
+
+   v_compiler::create();
+   description::create();
+
+   SetProp(P_COMPILER_PATH, __DIR__);
+   SetProp(P_STD_OBJECT, PLANTITEM);
+   
+   PLANTMASTER->UpdateVC();
+}
+
+string Validate(string file)
+{
+   if (!stringp(file)) return 0;
+   file = ::Validate(explode(file, "#")[0]);
+#if MUDNAME == "MorgenGrauen"
+   return (member(validfiles, file) ? file : 0);
+#else
+   return file;
+#endif
+}
+
+private nosave object simul_efun;
+
+// fuer SIMUL_EFUN_FILE
+#include <config.h>
+
+// AN: Funktion liefert das clonende Objekt als dessen Blueprint-Namen,
+// indem es den Caller-Stack durchlaeuft und nach einem Objekt sucht,
+// das weder der Master, noch ein Simul-Efun-Objekt, noch dieser VC selbst
+// ist. Der Name des gefundenen Objekts wird zurueckgegeben, oder 0.
+nomask private string get_cloner()
+{
+   int i;
+   object po;
+
+   if (!simul_efun)
+   {
+      if (!(simul_efun=find_object(SIMUL_EFUN_FILE)))
+         simul_efun=find_object(SPARE_SIMUL_EFUN_FILE);
+   }
+   // wenn sie jetzt nicht existiert - auch gut, dann gibt es halt keine
+   // sefuns.
+
+   for (i=0; po=previous_object(i); i++)
+   {
+      if (po==master() || po==simul_efun || po==ME || po==previous_object())
+         continue;
+      return BLUE_NAME(po);
+   }
+   return 0;
+}
+
+// Konfiguriert das erzeugte Objekt entsprechend der dafuer im Kraeutermaster
+// bekannten Daten. Vergibt auf die Plant-ID.
+varargs string CustomizeObject(string file)
+{
+   if (previous_object()->QueryPlantId()) return 0; // bereits initialisiert
+   
+   if (stringp(file))
+      file=Validate(file);
+   else file=::CustomizeObject();
+   if (!file) return 0;
+
+   closure sp=symbol_function("SetProp", previous_object());
+   mixed arr=krautdaten[file];
+   if (pointerp(arr))
+   {
+      // Welches Objekt clont das File?
+      string cloner = get_cloner();
+      string rooms = arr[1];
+      mixed props = arr[0];
+      // Wird das Kraut legal von einem eingetragenen Cloner erzeugt? Nur dann
+      // bekommt es eine gueltige Plant-ID.
+     int legal=member(rooms, get_cloner()) || cloner==PLANTMASTER;
+     if (!legal && this_interactive() && IS_ARCH(this_interactive()))
+        legal=1;
+     
+      // Konfiguriert wird das Objekt dann, wenn es per VC erzeugt wird oder
+      // ein Clone einer per VC erzeugten BP ist - d.h. wenn es nicht aus
+      // einem real existierenden File auf der Platte existiert. Das ist dann
+      // der Fall, wenn der Loadname gleich dem Standardplantobjekt des VC
+      // ist.
+      if (load_name(previous_object())==PLANTITEM)
+      {
+        if ((props[INGREDIENT_NAME]=="Klee") ||
+            (props[INGREDIENT_NAME][<4..]=="klee")) {
+           funcall(sp, P_NAME, ({ props[INGREDIENT_NAME],
+                                  props[INGREDIENT_NAME]+"s",
+                                  props[INGREDIENT_NAME],
+                                  props[INGREDIENT_NAME]}));
+        }
+        else funcall(sp, P_NAME,     props[INGREDIENT_NAME]);
+        funcall(sp, P_NAME_ADJ, props[INGREDIENT_ADJ]);
+        funcall(sp, P_GENDER,   props[INGREDIENT_GENDER]);
+        funcall(sp, P_LONG,     props[INGREDIENT_LONG]);
+        funcall(sp, PLANT_ROOMDETAIL, props[INGREDIENT_ROOMDETAIL]);
+        if (props[INGREDIENT_DEMON]==RAW) {
+           funcall(sp, P_ARTICLE, 0);
+           funcall(sp, P_SHORT, previous_object()->Name(WER));
+           funcall(sp, P_ARTICLE, 1);
+        }
+        else funcall(sp, P_SHORT,
+             previous_object()->Name(WER,props[INGREDIENT_DEMON]));
+        previous_object()->AddId(lowerstring(props[INGREDIENT_NAME]));
+        // bei zusammengesetzten Namen, auch den hauptnamen akzeptieren
+        string str=lowerstring(props[INGREDIENT_NAME]);
+        string *names=explode(str, "-");
+        if (sizeof(names)>1) previous_object()->AddId(names[<1]);
+        names=explode(str, " ");
+        if (sizeof(names)>1) previous_object()->AddId(names[<1]);
+        foreach(string id: IDLIST)
+        {
+          if (strstr(str, id)==-1) continue;
+          previous_object()->AddId(id);
+          break;
+        }
+        // Adjective vorher deklinieren
+        str=props[INGREDIENT_ADJ];
+        if (stringp(str))
+        {
+          str=DeclAdj(lowerstring(str), WEN, 0);
+          previous_object()->AddAdjective(str);
+        }
+      }  // Ende Konfiguration eines VC-erzeugten Objekts
+      // Plant-ID wird fuer alle Objekte auf irgendwas gesetzt.
+      previous_object()->SetPlantId(legal ? props[INGREDIENT_ID] : -1);
+   }
+   // Keine Krautdaten bekannt...
+   else
+   {
+     funcall(sp, P_NAME,     "Kraut");
+     funcall(sp, P_GENDER,   NEUTER);
+     funcall(sp, P_SHORT,    "Ein Testkraut ("+capitalize(file)+")");
+     funcall(sp, P_LONG,     "Ein nicht naeher spezifiziertes Testkraut.\n");
+     funcall(sp, PLANT_ROOMDETAIL,
+         "Ein nicht naeher spezifiziertes Testkraut ("
+         +capitalize(file)+").\n");
+     previous_object()->AddId("kraut");
+     previous_object()->SetPlantId(-1);
+   }
+   return file;
+}
+
+int NoParaObjects()
+{   return 1;   }
+
+// AN: Funktion erzeugt aus den vorliegenden Daten der Kraeuterliste ein
+// physikalisch existierendes File in diesem Verzeichnis, zB wenn die Daten
+// erweitert werden sollen. Die Kraeuterliste stellt nur generische Objekte
+// zur Verfuegung, die keine Details haben. Wenn die Objekte ausgeschmueckt
+// werden sollen, koennen diese auch als Datei hier liegen.
+// Wird vom Plantmaster aus gerufen. Die Existenz von Klartext-
+// Fehlermeldungen laesst darauf schliessen, dass diese Funktion dafuer
+// vorgesehen war, vom Planttool aus gerufen zu werden. Dies wird dadurch
+// bestaetigt, dass dort wie hier alle von Magiern benutzbaren Kommando-
+// funktionen mit _ beginnen (_showplant(), _addroom() etc.), und die
+// Kommandofunktion im Planttool generell in der Lage ist, alle _*() 
+// im Plantmaster zu rufen, sofern existent und fuer den Magier freigegeben.
+// AN/TODO: ggf. sollte man hier noch pruefen, ob die VC-Blueprint des
+// angeforderten Krautes gerade existiert, denn sonst wuerde das auf der
+// Platte liegende, scheinbar (nicht) geladene Objekt nicht mit dem
+// VC-Objekt uebereinstimmen. Evtl. reicht es aus, die Blueprint einfach
+// zu zerstoeren und neuzuladen.
+int _createfile(string filename)
+{
+   int i;
+   string str, short, long, gender, *name, roomdetail;
+   string *ids;
+   string plantfile;
+
+/*   if (object_name(previous_object())!=PLANTMASTER) {
+      write("Illegal usage of _createfile()!\n");
+      return 1;   
+   }*/
+// ^^^ Zook, ggf.spaeter wieder Kommentar entfernen. 
+
+   mixed arr;
+   if (!pointerp(arr=krautdaten[filename])) {
+      write("Unknown plant '"+filename+"'.\n");
+      return 1;
+   }
+   if (file_size(PLANTDIR+filename+".c")>=0) {
+      write("error: file "+PLANTDIR+filename+".c already exists.\n");
+      return 1;
+   }
+   mixed props = arr[0];
+
+   // Kurzbeschreibung erzeugen
+   SetProp(P_NAME,     props[INGREDIENT_NAME]);
+   SetProp(P_NAME_ADJ, props[INGREDIENT_ADJ]);
+   SetProp(P_GENDER,   props[INGREDIENT_GENDER]);
+   if (props[INGREDIENT_DEMON]==RAW) {
+       SetProp(P_ARTICLE, 0);
+       short=Name(WER);
+       SetProp(P_ARTICLE, 1);
+   }
+   else short=Name(WER,props[INGREDIENT_DEMON]);
+   ids = ({ lowerstring(props[INGREDIENT_NAME]) });
+   // bei zusammengesetzten Namen, auch den hauptnamen akzeptieren
+   str=lowerstring(props[INGREDIENT_NAME]);
+   name=explode(str, "-");
+   if (sizeof(name)>1) ids += ({ name[<1] });
+   name=explode(str, " ");
+   if (sizeof(name)>1) ids += ({ name[<1] });
+   for (i=sizeof(IDLIST)-1; i>=0; i--) {
+       if (strstr(str, IDLIST[i], 0)==-1) continue;
+       ids += ({ IDLIST[i] });
+       break;
+   }
+   switch(props[INGREDIENT_GENDER]) {
+     case MALE:   gender="MALE"; break;
+     case FEMALE: gender="FEMALE"; break;
+     case NEUTER: gender="NEUTER"; break;
+     default: gender=props[INGREDIENT_GENDER];
+   }
+   long="    \""+implode(old_explode(props[INGREDIENT_LONG], "\n"), 
+                   "\\n\"\n   +\"")+"\\n\"";
+   roomdetail="    \""+implode(
+      old_explode(props[INGREDIENT_ROOMDETAIL], "\n"), "\\n\"\n   +\"")+
+      "\\n\"";
+   plantfile=
+    "#pragma strong_types,rtt_checks\n\n"
+    "#include <properties.h>\n"
+    "#include <items/kraeuter/kraueter.h>\n"
+    "#include <items/kraeuter/kraeuterliste.h>\n\n"
+    "inherit STDPLANT;\n\n"
+    "protected void create()\n"
+    "{\n"
+    "  ::create();\n";
+   plantfile+="  customizeMe("+upperstring(filename)+");\n";
+   plantfile+=
+    "  SetProp(P_NAME,     \""+props[INGREDIENT_NAME]+"\");\n"
+    "  SetProp(P_NAME_ADJ, \""+(props[INGREDIENT_ADJ]||"")+"\");\n"
+    "  SetProp(P_GENDER,   "+gender+");\n"
+    "  SetProp(P_LONG,     \n"+
+    long+");\n"
+    "  SetProp(PLANT_ROOMDETAIL, \n"+
+    roomdetail+");\n"
+    "  SetProp(P_SHORT,    \""+short+"\");\n";
+   plantfile+="  AddId(({";
+   for (i=sizeof(ids)-1; i>=0; i--)
+     plantfile+=" \""+ids[i]+"\",";
+   plantfile[<1]=' ';
+   plantfile+="}));\n";
+   // Adjective vorher deklinieren
+   if (stringp(short=props[INGREDIENT_ADJ])) {
+     short=DeclAdj(lowerstring(short), WEN, 0)[0..<2];
+     plantfile+="  AddAdjective(\""+short+"\");\n";
+   }
+   plantfile+="}\n";
+   write(plantfile);
+   //write_file(PLANTDIR+filename+".c", plantfile);
+   write("Filename: "+PLANTDIR+filename+".c\n");
+   return 1;
+}
+
diff --git a/items/money.c b/items/money.c
new file mode 100644
index 0000000..4a9a5f4
--- /dev/null
+++ b/items/money.c
@@ -0,0 +1,340 @@
+// MorgenGrauen MUDlib
+//
+// money.c -- Unser Geld
+//
+// $Id: money.c 8893 2014-08-04 19:48:56Z Zesstra $
+
+inherit "/std/unit";
+
+#pragma strong_types,rtt_checks
+
+#include <properties.h>
+#include <language.h>
+#include <defines.h>
+#include <unit.h>
+#include <money.h>
+
+// zum debuggen (debugmode kommt aus /std/unit.c
+#include <living/comm.h>
+#define ZDEBUG(x) if (stringp(debugmode) && find_player(debugmode)) \
+  find_player(debugmode)->ReceiveMsg(x,MT_DEBUG,0,object_name()+": ",ME)
+//#define ZDEBUG(x)
+
+protected void NotifyMove(object dest, object oldenv, int method)
+{
+  // Logg-Funktion, um Nicht-Standard-Geldbugs zu finden.
+  // Eingebaut 27.03.2000 - Tiamak
+  // Vor vereinigen mit anderen Geldobjekten in NotifyMove().
+  object moneylog = find_object("/p/daemon/moneylog");
+  if ( (!environment() && previous_object() &&
+        !query_once_interactive(previous_object()) &&
+        load_name(previous_object()) != GELD) &&
+        moneylog)
+      moneylog->AddMoney( previous_object(), Query(U_REQ) );
+
+  // Hier passiert Vereinigung mit anderen Geldobjekten... Etc.
+  ::NotifyMove(dest, oldenv, method);
+
+  // Zu diesem Zeitpunkt sind Vereinigungen mit anderen Geldobjekten in dest
+  // schon gelaufen, hier muessen jetzt noch Geldboersen und Seherkarten
+  // beruecksichtigt werden.
+  // Sollverhalten ist:
+  // Vereinigung mit Boersen+geldkarten nur in Lebewesen.
+  // Ausserdem soll nicht vereinigt werden, wenn man muenzen aus einer Boerse
+  // nimmt. 
+  // A) Betrag ist positiv:
+  // A1) mit der ersten geld-enhaltenen Geldboerse im Inventar vereinigen.
+  //     Gibt es keine geld-gefuellte, wird die erste leere genommen.
+  // B) Betrag ist negativ:
+  //    Es wird versucht, mit geldgefuellten Boersen und aktiven Seherkarten
+  //    (d.h. Karten, diesem Environment gehoeren) zu vereinigen.
+  //    Es wird erst einer Boersen "abgebucht" (falls vorhanden) und dann
+  //    (falls noch noetig) von einer Geldkarte. Ist der Betrag am Ende
+  //    negativ, wird ein Fehler ausgeloest.
+  if (!living(dest))
+    return;
+  // wenn wir aus einer Boerse in diesem Environment kommen, vereinigen wir
+  // uns nicht wieder erneut.
+  if (load_name(oldenv) == BOERSE
+      && environment(oldenv) == environment())
+    return;
+
+  int amount = QueryProp(P_AMOUNT);
+  ZDEBUG(sprintf("NotifyMove 1: amount: %d\n",
+         amount));
+  if (amount > 0)
+  {
+    object boerse = present(GELDBOERSE_MIT_GELD, environment())
+                    || present(BOERSEID, environment());
+    if (boerse)
+    {
+      boerse->MergeMoney(this_object());
+      // Sollten wir jetzt P_AMOUNT == 0 haben, zerstoert uns der Code aus
+      // unit.c spaeter.
+      ZDEBUG(sprintf("NotifyMove nach Boersenvereinigung 1: amount: %d\n",
+             QueryProp(P_AMOUNT)));
+    }
+  }
+  else if (amount < 0)
+  {
+    object boerse = present(GELDBOERSE_MIT_GELD, environment());
+    if (boerse)
+    {
+      boerse->MergeMoney(this_object());
+      ZDEBUG(sprintf("NotifyMove nach Boersenvereinigung 2: amount: %d\n",
+             QueryProp(P_AMOUNT)));
+    }
+    // wenn immer noch was auszugleichen ist, Geldkarte versuchen.
+    if (QueryProp(P_AMOUNT) < 0)
+    {
+      object geldkarte = present(SEHERKARTEID_AKTIV, environment());
+      if (geldkarte)
+      {
+        geldkarte->MergeMoney(this_object());
+        ZDEBUG(sprintf("NotifyMove nach Kartenvereinigung: amount: %d\n",
+               QueryProp(P_AMOUNT)));
+      }
+    }
+    if (QueryProp(P_AMOUNT) < 0)
+      catch(raise_error(sprintf(
+            "Geld mit negativem Betrag immer noch negativ nach "
+            "Vereinigung mit allen Geldquellen im Inventar: %O. Rest: %d\n",
+            environment(), QueryProp(P_AMOUNT))); publish);
+  }
+}
+
+int _set_autoloadobj( mixed args )
+{
+  if (pointerp(args))
+    args=args[0];
+  if (stringp(args))
+    sscanf(args,"%d",args);
+  if (!intp(args))
+    args=0;
+  return SetProp(P_AMOUNT,args);
+}
+
+int _query_autoloadobj()
+{
+  return (int)Query(P_AMOUNT, F_VALUE);
+}
+
+string current_long() {
+ int r;
+ r=Query(U_REQ);
+ return(break_string(
+  ((r==1)?"":"Du betrachtest eine der Muenzen genauer:\n")+
+  "Die Oberflaeche der Goldmuenze ist vom taeglichen Gebrauch ziemlich "
+  "mitgenommen. Kratzer und sogar Bissspuren zieren die Praegemuenze "
+  "zusaetzlich zum Konterfei "+
+  ({"des Jof","der Rumata","des Zook"})[(Query(P_AMOUNT)+r)%3]+
+  ". Der Rand "+
+  ((!(r%2))?"scheint etwas beschaedigt zu sein.":
+            "ist wenigstens unbeschaedigt."),
+  78,0,BS_LEAVE_MY_LFS));
+}
+
+static int action_schnipps(string str) {
+ if(!id(str)) return 0;
+ write(break_string(
+  ((Query(U_REQ)==1)?"Du nimmst die Muenze":
+                     "Du nimmst eine der Muenzen")+
+  " und schnippst sie in die Luft. Sie klingt hell auf. "+
+  ((this_player() && this_player()->QueryAttribute(A_DEX)>10)?
+   "Geschickt faengst Du sie wieder auf.":
+   "Sie plumpst Dir wieder in die Hand und beinahe laesst Du "
+   "sie fallen."),78));
+ if(this_player() && environment(this_player()))
+  tell_room(environment(this_player()),
+            break_string(this_player()->Name()+" schnippt mit hellem "
+                         "Klingen ein Muenze in die Luft und faengt sie "
+                         "wieder.",78),
+            ({this_player()}));
+ return 1;
+}
+
+static int action_pruefe(string str) {
+ if(!id(str)) return 0;
+ write(break_string(
+  ((Query(U_REQ)==1)?"Du nimmst die Muenze":
+                     "Du nimmst eine der Muenzen")+
+  " und beisst vorsichtig hinein. Dein Zahn versinkt tief im reinen Gold, "
+  "und Du bist Dir nun sicher, dass diese Muenze auch wirklich echt ist.",
+  78));
+ if(this_player() && environment(this_player()))
+  tell_room(environment(this_player()),
+            break_string(this_player()->Name()+" beisst in eine Muenze "
+                         "und schaut irgendwie befriedigt drein.",78),
+            ({this_player()}));
+ return 1;
+}
+
+
+static string DetKonterfei() {
+ string m;
+ switch((Query(P_AMOUNT)+Query(U_REQ))%3) {
+  default:
+  case 0:
+        m="Jofs rundes Gesicht grinst Dich vertrauenserweckend und "
+          "freundlich an.";break;
+  case 1:
+        m="Rumata scheint Dir zuzublinzeln.";break;
+  case 2:
+        m="Zooks Gesicht schaut ziemlich frisch gepraegt drein. Wenn "
+          "eine der Muenzen beim Schnippen klingt, dann bestimmt die.";break;
+ }
+ return(break_string(m,78));
+}
+
+
+static string DetRand() {
+ return(break_string(
+  ((!(Query(U_REQ)%2))?
+            "Der Rand der Muenze ist zerklueftet und abgeschabt. Ob "
+            "da jemand versucht hat, das Gold der Muenze abzuschaben, "
+            "um sich etwas nebenher zu verdienen?":
+            "Der Rand ist vollkommen in Ordnung, ein wirklich frische "
+            "Praegung."),78));
+}
+
+
+static int action_wurf(string str)
+{
+  int num, part;
+
+  if (!id(str))
+    return 0;
+
+  num = Query(U_REQ);
+  write (break_string(
+	 ((num==1)?"Du nimmst die Muenze":
+	  sprintf("Du nimmst %d Muenzen", num))+
+	   ", wirfst sie hoch, laesst sie zu Boden prasseln und "
+	   "betrachtest das Ergebnis:", 78));
+  if (this_player() && environment(this_player()))
+    tell_room(environment(this_player()),
+	      break_string(this_player()->Name()+" wirft "+
+         	   ((num==1)?"eine Muenze":
+			   sprintf("%d Muenzen", num))+
+		   " hoch, laesst sie zu Boden prasseln und betrachtet "
+		   +"das Ergebnis:", 78), ({this_player()}));
+
+  if (num == 1) {
+    if (random(1000000) == 123456) {
+      write("   Die Muenze bleibt auf dem Rand stehen.\n");
+      if (this_player() && environment(this_player()))
+	tell_room(environment(this_player()),
+		  "   Die Muenze bleibt auf dem Rand stehen.\n",
+		  ({this_player()}));
+    }
+    else if (random(100) < 50) {
+      write("   Kopf.\n");
+      if (this_player() && environment(this_player()))
+	tell_room(environment(this_player()),
+		  "   Kopf.\n",
+		  ({this_player()}));
+    }
+    else {
+      write("   Zahl.\n");
+      if (this_player() && environment(this_player()))
+	tell_room(environment(this_player()),
+		  "   Zahl.\n",
+		  ({this_player()}));
+    }
+  }
+  else {
+    part = 5*num + random(num+1) - random(num+1) // etwas Gauss-verteilen
+		 + random(num+1) - random(num+1)
+		 + random(num+1) - random(num+1)
+		 + random(num+1) - random(num+1)
+		 + random(num+1) - random(num+1);
+    part = (part+5)/10;
+
+    if (part) {
+      printf("   %dx Kopf", part);
+      if (part != num)
+	printf(" und %dx Zahl", num-part);
+      if(this_player() && environment(this_player()))
+	tell_room(environment(this_player()),
+		  sprintf("   %dx Kopf", part)+
+		  ((part!=num)?sprintf(" und %dx Zahl", num-part):"")+
+		  ".\n",
+		  ({this_player()}));
+    }
+    else {
+      printf("   %dx Zahl", num);
+      if (this_player() && environment(this_player()))
+	tell_room(environment(this_player()),
+		  sprintf("   %dx Zahl.\n", num),
+		  ({this_player()}));
+    }
+    write (".\n");
+  }
+
+  write(break_string(
+	"Schnell sammelst Du "+
+	((num==1)?"Deine Muenze":"Deine Muenzen")+" wieder ein.", 78));
+  if (this_player() && environment(this_player()))
+    tell_room(environment(this_player()),
+	      break_string(this_player()->Name()+ " sammelt schnell "+
+	      ((num==1)?(this_player()->QueryPossPronoun(FEMALE,WEN, SINGULAR)
+			 +" Muenze wieder ein."):
+	       (this_player()->QueryPossPronoun(FEMALE,WEN, PLURAL)+
+		" Muenzen wieder ein."))), ({this_player()}));
+  return 1;
+}
+
+protected void create()
+{
+  mixed plist, i;
+
+  ::create();
+  SetProp(P_NAME,({"Muenze","Muenzen"}));
+  Set(P_LONG,#'current_long);
+  SetProp(P_SHORT,"Geld");
+  SetProp(P_INFO,"Du hast bei diesem Geld ein sicheres Gefuehl.\n");
+  SetProp(P_MATERIAL,([MAT_GOLD:100]));
+  AddSingularId("muenze");
+  AddPluralId("muenzen");
+  AddSingularId("goldstueck");
+  AddPluralId("goldstuecke");
+  AddId(({"geld", GELDID}));
+  SetProp(P_GENDER,FEMALE);
+  SetCoinsPerUnits(1,1);
+  SetGramsPerUnits(1,4);
+
+  if (!clonep(this_object())) {
+    set_next_reset(-1);
+    return;
+  }
+  AddDetail(({"rand","muenzrand"}),#'DetRand);
+  AddDetail(({"oberflaeche","flaeche"}),break_string(
+   "Diese Muenze ist schon durch viele Haende gegangen. Die Kratzer "
+   "zeugen davon, dass sie nicht selten allein getragen wurde und die "
+   "Bissspuren von mangelndem Vertrauen.",78));
+  AddDetail("kratzer",break_string(
+   "Das Konterfei ist schon ganz schoen zerkratzt.",78));
+  AddDetail(({"bissspur","bissspuren"}),break_string(
+   "Da hat doch tatsaechlich jemand so wenig Vertrauen in das Gold "
+   "gezeigt, dass er hineingebissen hat, um es zu pruefen.",78));
+  AddDetail(({"bild","konterfei","praegung"}),#'DetKonterfei);
+  AddDetail("gold","Es glaenzt Dich verheissungsvoll an.\n");
+
+  AddCmd(({"pruef","pruefe","beiss","beisse","test","teste"}),
+         #'action_pruefe);
+  AddCmd(({"schnipp","schnippe","schnipps","schnippse"}),
+         #'action_schnipps);
+
+  AddCmd( ({ "wirf", "werf", "werfe" }), #'action_wurf);
+}
+
+varargs string GetDetail(mixed key,mixed race,int sense) {
+ string m;
+ if(stringp(m=::GetDetail(&key,&race,&sense)) && sizeof(m)) {
+  int r;
+  r=Query(U_REQ);
+  if(r!=1) m=sprintf("Du betrachtest eine der %d Muenzen genauer:\n",r)+m;
+ }
+ return m;
+}
+
diff --git a/items/pfeifchen.c b/items/pfeifchen.c
new file mode 100644
index 0000000..c0d8976
--- /dev/null
+++ b/items/pfeifchen.c
@@ -0,0 +1,149 @@
+inherit "/std/thing";
+
+#include <properties.h>
+#include <language.h>
+
+int tm;
+int gestopft = 0;
+int rauchen  = 0;
+
+string des;
+
+string _query_long(){
+  string s;
+  s="Ein einfaches Holzpfeifchen: Ohne Verzierungen oder besondere "
+    "Extras, sondern schlicht und stabil genug fuer ein Abenteurerleben. "
+    "Es eignet sich hervorragend dazu, einmal zu entspannen und guten "
+    "Tabak zu geniessen";
+  if(gestopft) s+=". Das Pfeifchen ist gestopft";
+  if(rauchen)  s+=" und angezuendet.";
+  else         s+=".";
+  return(break_string(s,78));
+}
+
+string _query_short(){
+  if(rauchen)  return "Ein Pfeifchen (angezuendet)";
+  if(gestopft) return "Ein Pfeifchen (gestopft)";
+  else         return "Ein Pfeifchen";
+}
+
+protected void create(){
+  if(!clonep(this_object()))return ;
+  thing::create();
+  tm=0;
+  SetProp(P_GENDER,NEUTER);
+  SetProp(P_NAME,"Pfeifchen");
+  SetProp(P_WEIGHT,10);
+  SetProp(P_VALUE,0);
+  AddId(({"pfeifchen","holzpfeifchen"}));
+  SetProp(P_NODROP,1);
+  SetProp(P_NEVERDROP,1);
+  SetProp(P_MATERIAL,MAT_IRON_WOOD);
+  AddCmd(({"rauch","rauche"}),"cm_smoke");
+  AddCmd(({"stopf","stopfe"}),"cm_stopf");
+}
+
+static int cm_stopf(string str){
+  string s1,s2;
+  object ob;
+  _notify_fail("Syntax: stopfe pfeifchen mit <was>\n");
+  if(!str) return 0;
+  if(sscanf(str,"%s mit %s",s1,s2)==2){
+    if(id(s1)){
+      if(!ob=present(s2,this_player())){
+        write("So etwas hast Du doch gar nicht bei Dir.\n");
+        return 1;
+       }
+      if((ob->id("tabak")) || (ob->QueryMaterial(MAT_CANNABIS)>50)){
+        if(rauchen){
+          write(break_string("Du rauchst Dein Pfeifchen doch gerade. Damit "
+           "musst Du schon warten, bis Du fertig bist.",78));
+          return 1;
+         }
+        if(gestopft){
+          write(break_string("Du hast Dein Pfeifchen bereits gestopft. Es "
+           "liesse sich nun vortrefflich rauchen.",78));
+          return 1;
+         }
+        else{
+          write(break_string("Du stopfst Dein Pfeifchen mit "+
+           ob->name(WEM,1)+
+           " und freust Dich schon darauf, es zu rauchen.",78));
+          tell_room(environment(this_player()),this_player()->Name()+
+           " stopft ein Pfeifchen.\n",({this_player()}));
+          if(!ob->GetSmokeDescription()) des="Es scheint sich um keinen "
+           "besonders guten Tabak zu handeln. Nun, ja. Besser als nichts "
+           "immerhin.";
+          else des=ob->GetSmokeDescription();
+          if(!ob->QueryProp(P_AMOUNT))
+            ob->remove();
+          else
+            ob->AddAmount(-1);
+          gestopft = 1;
+          return 1;
+         }
+       }
+      write(break_string("Das laesst sich aber schlecht rauchen, such "
+       "Dir lieber einen ordentlichen Tabak.",78));
+      return 1;
+     }
+   }
+  return(0); //non-void Funktion, Zesstra
+}
+
+static int cm_smoke(string str){
+  object ob;
+
+  _notify_fail("Was moechtest Du rauchen?\n");
+  if(!str) return 0;
+  if(!id(str)) return 0;
+  if(rauchen){
+    write("Das machst Du doch bereits, nicht so hektisch.\n");
+    return 1;
+   }
+  if(!gestopft){
+    write("Vielleicht solltest Du Dein Pfeifchen erst mal stopfen?\n");
+    return 1;
+   }
+  if(tm > time()){
+    write("Nana, ein Pfeifchen geniesst man. Sei mal nicht so hektisch.\n");
+    return 1;
+   }
+  tm = time()+20;
+  rauchen = 1;
+  tell_room(environment(this_player()),this_player()->Name()+" raucht in "
+   +"Ruhe ein Pfeifchen.\n",({this_player()}));
+  write("Du rauchst in Ruhe Dein Pfeifchen.\n");
+  write(break_string(des,78));
+  if(find_call_out("smoke2")==-1)
+    call_out("smoke2",20,getuid(this_player()));
+  return 1;
+}
+
+int smoke2(object pl){
+  object ob;
+  if(!rauchen) return 0;
+  if(!ob=find_player(pl)) return 0;
+  if(environment()!=ob) return 0;
+  tell_object(ob,"Genuesslich pustest Du ein paar Rauchkringel in die Luft.\n");
+  tell_room(environment(ob),ob->Name()+" pustet genuesslich ein paar "
+   +"Rauchkringel in die Luft.\n",({ob}));
+  if(find_call_out("smoke3")==-1)
+    call_out("smoke3",20,getuid(environment()));
+  return 1;
+}
+
+int smoke3(object pl){
+  object ob;
+  if(!rauchen) return 0;
+  if(!ob=find_player(pl)) return 0;
+  if(environment()!=ob) return 0;
+  tell_object(ob,break_string("Genuesslich pustest Du ein paar Rauchkringel "
+   "in die Luft, rauchst Dein Pfeifchen auf und klopfst es aus.",78));
+  tell_room(environment(ob),break_string(ob->Name()+" pustet genuesslich ein "
+   "paar Rauchkringel in die Luft, beendet das Rauchpaeuschen und klopft "
+   +(ob->QueryProp(P_GENDER)==1?"sein":"ihr")+" Pfeifchen aus.",78),({ob}));
+  rauchen = 0;
+  gestopft = 0;
+  return 1;
+}
diff --git a/items/schaufel.c b/items/schaufel.c
new file mode 100644
index 0000000..bd4940b
--- /dev/null
+++ b/items/schaufel.c
@@ -0,0 +1,26 @@
+#pragma strong_types,rtt_checks
+
+inherit "/std/thing";
+
+#include <properties.h>
+#include <language.h>
+
+void create()
+{
+  ::create();
+  SetProp(P_SHORT,"Eine Schaufel");
+  SetProp(P_LONG,"Du kannst versuchen, mit dieser Schaufel zu graben.\n");
+  AddId("schaufel");
+  AddId("\nschaufel");
+  SetProp(P_NAME, "Schaufel");
+  SetProp(P_GENDER, FEMALE);
+  SetProp(P_VALUE, 50);
+  SetProp(P_WEIGHT, 1200);
+	AddCmd( ({"grab","grabe","buddel","buddele"}), "grab" );
+}
+
+int grab(string str) 
+{
+  _notify_fail("Du kannst hier nicht graben.\n");
+  return 0;
+}
diff --git a/items/seercard.c b/items/seercard.c
new file mode 100644
index 0000000..a899e9f
--- /dev/null
+++ b/items/seercard.c
@@ -0,0 +1,359 @@
+// MorgenGrauen MUDlib
+//
+// obj/seercard.c -- bargeldloser Zahlungsverkehr auf Guthabenbasis
+//
+
+#pragma strict_types
+
+inherit "/std/thing";
+
+#include <defines.h>
+#include <properties.h>
+#include <language.h>
+#include <unit.h>
+#include <moving.h>
+#include <wizlevels.h>
+#include <money.h>
+
+#define KONTO "seercard_kontostand"
+#define BESITZER_GUELTIG \
+    (environment() && query_once_interactive(environment()) && \
+    getuid(environment()) == owner)
+
+// zum debuggen und extra public
+public string debugmode;
+public string __set_debug(string recv) {return debugmode=recv;}
+#include <living/comm.h>
+#define ZDEBUG(x) if (stringp(debugmode) && find_player(debugmode)) \
+  find_player(debugmode)->ReceiveMsg(x,MT_DEBUG,0,object_name()+": ",ME)
+//#define ZDEBUG(x)
+
+private string owner;
+
+static int _query_amount()
+{
+    int res;
+
+    // Wenn die Karte im Inv des Besitzers ist, Kontostand liefern
+    if ( BESITZER_GUELTIG && IS_SEER(environment()) ){
+        res = (int) environment()->Query(KONTO);
+
+        // ... allerdings nur, wenn er gueltig ist ;-)
+        if ( !intp(res) || res < 0 || res > 100000 )
+            return environment()->Set( KONTO, 0 ), 0;
+        else
+            return res;
+    }
+
+    // Fuer Fremde ist die Karte wertlos (bis auf ihren Materialwert)
+    return 0;
+}
+
+static string _feld()
+{
+    if ( !BESITZER_GUELTIG )
+        return break_string( "Das Feld schimmert aus jeder Richtung anders - "
+                             "aber mehr kannst Du nicht erkennen.", 78 );
+
+    return "Du kannst in dem Schimmern ein paar Ziffern erkennen.\n";
+}
+
+
+static string _bild()
+{
+    if ( this_player() && getuid(this_player()) == owner )
+        return break_string( "Du findest, dass das Bild ganz schlecht "
+                             "getroffen ist. Dass man selber aber auch immer "
+                             "so unvorteilhaft abgebildet wird!", 78 );
+
+    return break_string( "Du findest, dass " + capitalize(owner) + " sehr gut "
+                         "getroffen ist. Anscheinend wirst nur Du immer so "
+                         "unvorteilhaft abgebildet.", 78 );
+}
+
+// Ueber das Argument <silent> kann nun gesteuert werden, ob man die 
+// zusaetzliche Meldung ausgeben will oder nicht. Dies ist jetzt nur beim
+// Untersuchen der Karte der Fall, der Befehl "guthaben" gibt wie frueher
+// nur das Guthaben aus.
+private string _guthaben(int silent)
+{
+    int i;
+
+    if ( !BESITZER_GUELTIG )
+        return "Du kannst im Schimmern nichts erkennen.\n";
+
+    if ( !(i = _query_amount()) )
+        return "Welches Guthaben? :-)\n";
+
+    string msg =  
+      "Dein Guthaben betraegt " + ((i > 1) ? to_string(i) : "eine") +
+      " Muenze" + ((i > 1) ? "n" : "") + ".\n";
+    if ( !silent ) 
+      msg += 
+        "Du erinnerst Dich an die Worte des Schalterbeamten, dass Deine "
+        "Seer-Card (TM) immer erst dann belastet wird, wenn Du Dein Bargeld "
+        "komplett verpulvert hast.";
+    return break_string(msg, 78, 0, BS_LEAVE_MY_LFS);
+}
+
+// Wrapper fuer das Detail "guthaben", um das neue Argument angeben zu 
+// koennen
+static string _guthaben_det(string key) {
+  return _guthaben(0);
+}
+
+protected void create()
+{
+    if ( !clonep(ME) ){
+        set_next_reset(-1);
+        return;
+    }
+
+    ::create();
+
+    SetProp( P_LOG_FILE, "report/tiamak.rep" );
+    SetProp( P_NAME, "Geldkarte" );
+    SetProp( P_INFO,
+             break_string( "So sehr Du Dich auch anstrengst, Du kommst "
+                           "einfach nicht hinter das Geheimnis dieser "
+                           "Karte. Du weisst nur eines mit Sicherheit: "
+                           "es muss etwas mit Magie zu tun haben.", 78 ) );
+    SetProp( P_GENDER, FEMALE );
+    SetProp( P_MATERIAL, ([ MAT_PEAR_WOOD: 80, MAT_MISC_MAGIC: 20 ]) );
+    SetProp( P_WEIGHT, 50 );
+    SetProp( P_VALUE, 1000 );
+    SetProp( P_NOBUY, 1 );
+
+    AddSounds( SENSE_DEFAULT,
+               break_string( "Du kannst nichts hoeren. Es sind anscheinend "
+                             "auch keine losen Teile vorhanden.", 78 ) );
+
+    AddSmells( SENSE_DEFAULT, "Auch bargeldlose Zahlungsmittel stinken "
+               "nicht. ;-)\n" );
+
+    AddDetail( "sicherheit", "So etwas bietet diese Karte nicht!\n" );
+    AddDetail( "geheimnis", "Es lautet \"guthaben\". Aber verrate es "
+               "nicht weiter!\nAngeblich kannst Du das Guthaben sogar direkt "
+               "wieder abheben.\n" );
+    AddDetail( "magie", "Wenn man sie so einfach untersuchen koennte, "
+               "waere sie nicht halb so\ngeheimnisvoll.\n" );
+    AddDetail( "rechteck",
+               break_string( "An dieser Karte ist alles rechteckig: das Bild, "
+                             "das merkwuerdige Feld und die Karte selber.",
+               78) );
+    AddDetail( ({ "holz", "birnbaumholz" }), "Es handelt sich um das "
+               "mindestens genauso seltene wie magische Birnbaumholz.\n" );
+    AddDetail( ({ "schriftzug", "schrift" }), "Nur wo \"Seer-Card\" drauf "
+               "steht, ist auch wirklich eine Seer-Card drin.\n" );
+    AddDetail( ({ "buchstabe", "buchstaben" }), "Sie bilden den "
+               "unvermeidlichen Schriftzug \"Seer-Card (TM)\".\n" );
+    AddDetail( "drittel", "Na unten halt.\n" );
+    AddDetail( ({ "seite", "seiten" }), "Eine von beiden.\n" );
+    AddDetail( ({ "rechte seite", "rechts" }), "Das ist die eine.\n" );
+    AddDetail( ({ "linke seite", "links" }), "Das ist die andere.\n" );
+    AddDetail( "rueckseite", "Die Rueckseite ist total leer und "
+               "langweilig.\n" );
+    AddDetail( ({ "zahl", "zahlen", "ziffern", "ziffer" }), "Vielleicht sollen "
+               "sie Dein Guthaben darstellen?\n" );
+    AddDetail( ({ "feld", "schimmern", "richtung" }), #'_feld/*'*/ );
+    AddDetail( "bild", #'_bild/*'*/ );
+    AddDetail( "guthaben", #'_guthaben_det/*'*/ );
+    AddDetail( ({ "muenze", "muenzen" }), "Tipp mal \"guthaben\" ein.\n" );
+
+    AddCmd( "guthaben", "_kontostand" );
+    AddCmd( ({ "heb", "hebe" }), "_abheben" );
+
+    AddId( ({ SEHERKARTEID, "geldkarte", "seercard", "seer-card",
+                  "karte", "card" }) );
+}
+
+
+static int _kontostand( string str )
+{
+    if ( !this_player() || environment(this_object()) != this_player() )
+        return 0;
+
+    if ( !str || str == "" ){
+        write( _guthaben(1) );
+        return 1;
+    }
+
+    return 0;
+}
+
+
+// Abfrage des Kartenbesitzers von aussen
+public string query_owner()
+{
+    return owner;
+}
+
+
+// Lokale Property-Methoden
+
+static string _query_long()
+{
+    string str;
+
+    str = "Eigentlich ist die Seer-Card ziemlich schlicht gehalten. Sie ist "
+        "als ein etwa daumendickes Rechteck aus dunklem Holz geformt. "
+        "Auf der rechten Seite ist ein Bild von " +
+        ((this_player() && getuid(this_player()) == owner) ? "Dir" :
+         capitalize(owner)) + " aufgemalt. Links "
+        "daneben befindet sich ein schmucker Schriftzug in grossen silbernen "
+        "Buchstaben. Im unteren Drittel der Karte befindet sich ein dezent "
+        "schimmerndes rechteckiges Feld.";
+
+    return break_string( str, 78, 0, BS_LEAVE_MY_LFS );
+}
+
+
+static string _query_short()
+{
+    if ( !owner || !sizeof(owner) )
+        return "Eine Geldkarte";
+
+    if ( this_player() && getuid(this_player()) == owner )
+        return "Deine Seer-Card (TM)";
+
+    return "Die Geldkarte von " + capitalize(owner);
+}
+
+
+static string _query_autoloadobj()
+{
+    // Die Karte ist nur fuer den Eigentuemer autoload - auch, wenn sie in
+    // einem Paket o.ae. steckt
+    foreach (object env: all_environment())
+    {
+      if (getuid(env) == owner)
+          return owner;
+    }
+    return 0;
+}
+
+
+static string _set_autoloadobj( string wert )
+{
+    // Darf nach Personalisierung nicht mehr geaendert werden.
+    if ( !owner && stringp(wert) )
+    {
+
+        if ( member( ({ 'x', 'z', 's' }), wert[<1] ) != -1 ){
+            AddAdjective( wert+"'" );
+            AddAdjective( wert );
+        }
+
+        if ( wert[<1] != 's' )
+            AddAdjective( wert+"s" );
+
+        return owner = wert;
+    }
+    return 0;
+}
+
+
+static string _query_keep_on_sell()
+{
+    // Der Besitzer der Karte 'behaelt' sie automatisch
+    // Teil 2 der Abfrage, falls die Karte in einem Paket o.ae. steckt
+    if ( BESITZER_GUELTIG || this_player() && getuid(this_player()) == owner )
+        return owner;
+
+    // Bei den anderen je nach Wunsch
+    return Query(P_KEEP_ON_SELL);
+}
+
+
+// Man kann aus dem Guthaben auch wieder klingende Muenzen machen.
+// Wenn es denn sein muss.
+static int _abheben( string str )
+{
+    int summe, guthaben;
+    string dummy;
+    
+    if ( !this_player() || environment(this_object()) != this_player() )
+        return 0;
+
+    if ( str == "1 muenze ab" )
+        summe = 1;
+    else
+        if ( !stringp(str) ||
+             sscanf( str, "%d muenzen ab%s", summe, dummy ) != 2 ||
+             summe < 1 || dummy != "" ){
+            _notify_fail( "Wieviele Muenzen moechtest Du denn abheben?\n" );
+            return 0;
+        }
+
+    if ( (guthaben = _query_amount()) < summe ){
+        _notify_fail( "So hoch ist Dein Guthaben aber nicht!\n" );
+        return 0;
+    }
+
+    if ( (int) this_player()->AddMoney(summe) != 1 ){
+        write( "Soviel Geld koenntest Du gar nicht mehr tragen.\n" );
+        return 1;
+    }
+
+    environment()->Set( KONTO, guthaben - summe );
+
+    write( break_string( "Du schuettelst Deine Seer-Card (TM) vorsichtig "
+                         "hin und her und murmelst ein paar geheime Worte.\n"
+                         "Ploetzlich macht es *PLOPP* und Du haeltst Geld "
+                         "in den Haenden!", 78, 0, BS_LEAVE_MY_LFS ) );
+    return 1;
+}
+
+protected void NotifyMove(object dest, object oldenv, int method)
+{
+    ::NotifyMove(dest,oldenv,method);
+
+    // Besitzer der Karte setzen, falls noch keiner existiert
+    if ( !owner && environment() &&
+         query_once_interactive(environment()) )
+    {
+         owner = getuid(environment());
+
+        if ( member( ({ 'x', 'z', 's' }), owner[<1] ) != -1 ){
+            AddAdjective( owner );
+            AddAdjective( owner+"'" );
+        }
+        if ( owner[<1] != 's' )
+            AddAdjective( owner+"s" );
+    }
+}
+
+varargs int id(string str, int lvl)
+{
+  if (str==SEHERKARTEID_AKTIV
+      && BESITZER_GUELTIG)
+      return 1;
+  return ::id(str, lvl);
+}
+
+public void MergeMoney(object geld)
+{
+  if (geld && previous_object() == geld
+      && load_name(geld) == GELD
+      && BESITZER_GUELTIG)
+  {
+    int fremdamount = geld->QueryProp(P_AMOUNT);
+    int meinamount = _query_amount();
+    ZDEBUG(sprintf("MergeMoney: meinamount: %d, fremdamount: %d\n",
+          meinamount,fremdamount));
+    if (meinamount > 0 && fremdamount < 0)
+    {
+      int amount_to_merge = min(meinamount, abs(fremdamount));
+      environment()->Set( KONTO, meinamount - amount_to_merge, F_VALUE );
+      geld->SetProp(P_AMOUNT, fremdamount + amount_to_merge);
+    }
+    ZDEBUG(sprintf("MergeMoney: Final: meinamount: %d, fremdamount: %d\n",
+          _query_amount(),geld->QueryProp(P_AMOUNT)));
+  }
+}
+
+// Fuer die Zuordnung durch das Hoerrohr etc.
+public string GetOwner()
+{
+    return "Tiamak";
+}
diff --git a/items/seil.c b/items/seil.c
new file mode 100644
index 0000000..c5cf079
--- /dev/null
+++ b/items/seil.c
@@ -0,0 +1,286 @@
+#include <properties.h>
+#include <language.h>
+#include <seil.h>
+inherit "/std/thing";
+
+#pragma strict_types,rtt_checks
+
+object tied_to_ob;
+string tied_name;
+
+void create(){
+  ::create();
+
+  AddId( ({"seil", "\nseil"}) );
+  SetProp(P_NAME, "Seil");
+
+  SetProp(P_GENDER, NEUTER);
+  SetProp(P_LONG,break_string("Du siehst ein ganz normales Seil. Du kannst es an "+
+                  "Gegenstaenden festbinden und wieder loesen. Das Seil besteht "+
+                  "aus solider fester Steinbeisserwolle.",78));
+  AddDetail(({"wolle","steinbeisserwolle"}),"Diese Wolle ist eine besonders feste und stabile Wolle.\n");
+  SetProp(P_VALUE, 15);
+  SetProp(P_TIE_AUTO,1);
+  SetProp(P_WEIGHT, 300);
+
+  SetProp(P_MATERIAL,({MAT_MISC_STONE,MAT_WOOL}));
+  AddCmd( ({"binde","bind","knote","befestige","mach","mache"}), "tie" );
+
+  // der Befehle loesen wird auf die anderen Befehle umgebogen und dient nur
+  // der besseren benutzbarkeit des seiles.
+  AddCmd( ({"loese" }), "loesen" );
+
+}
+
+// dieses Ding wird u.a. geerbt. Damit die BP beim Erben auch initialisiert
+// wird (fuer die Laeden), muss create_super() das create() rufen.
+protected void create_super() {
+  create();
+}
+
+string _query_short()
+{
+ string artikel;
+ switch( QueryProp(P_GENDER) )
+ {
+  case NEUTER : artikel="das";break;
+  case MALE   : artikel="der";break;
+  case FEMALE :	artikel="die";break;
+  default     : artikel="das";
+ }
+
+ if (tied_to_ob)
+  return this_object()->Name(WER)+", "+artikel+" an "
+     + (tied_name?tied_name:(string)(tied_to_ob->name(WEM)))
+     + " festgebunden ist";
+ return (string)this_object()->Name(WER);
+
+}
+
+mixed _query_noget()
+{
+ if (tied_to_ob)
+  return "Das geht nicht, solange "+name(WER)+" festgebunden ist.\n";
+ return 0;
+}
+
+int tie(string str)
+{
+  string t1, t2;
+  object ob;
+  string verb;
+  mapping tied_map;
+
+  _notify_fail("Binde was?\n");
+
+  // zunaechst den User notieren, damit spaeter immer drauf 
+  // zugegriffen werden kann.
+  // Wegen kompatibilitaet wird das nicht direkt an tie()/untie()
+  // uebergeben.
+  SetProp(P_TIE_USER,this_player());
+
+  if (!str||!stringp(str)) return 0;
+
+  verb = query_verb();
+  
+  //automatischer aus objecten/raeumen generierter aufruf
+  if(QueryProp(P_TIE_VERB)) verb=QueryProp(P_TIE_VERB); 
+  	
+  if (sscanf(str, "%s an %s", t1, t2) != 2 && 
+      sscanf(str,"%s los",t1) != 1 &&
+      sscanf(str,"%s fest",t1) != 1 )
+   return 0;
+
+  if(id(t1) && str==(t1+" fest")) str="seil an raum";
+
+  if(sscanf(str,"%s an %s",t1,t2)==2)
+  {
+   if(tied_to_ob)
+   {
+    write("Es ist bereits irgendwo festgebunden.\n");
+    return 1;
+   }
+
+   if (!id(t1)) return 0;
+
+   if (t2 == "mich")
+   {
+    _notify_fail("Warum willst Du das denn machen?\n");
+    return 0;
+   }
+
+   ob = present(t2, this_player());		
+
+   if (!ob) ob = present(t2, environment(this_player()));
+
+   if (!ob)
+   {
+    if (call_other(environment(this_player()), "id", t2))
+    ob = environment(this_player());
+   }
+		
+   if(!ob && str == "seil an raum")
+   {
+    ob=environment(this_player());
+   }
+
+   _notify_fail( "Soetwas findest Du hier nicht.\n" );
+   if (!ob) return 0;
+
+   if (!(tied_name=(string)call_other(ob, "tie", t2)))
+   {
+    if(ob->QueryProp(P_INVIS)) return 0;
+    
+    if (ob != environment(this_player()))
+    {
+     _notify_fail("Du kannst "+name(WER)+" nicht an "+ob->name(WEM)+
+                 " festbinden.\n");
+     return 0;
+    }
+    else
+    {
+     _notify_fail("Du kannst "+name(WER)+" nicht daran festbinden.\n");
+     return 0;
+    }
+
+   }
+		
+  /* Is he carrying the rope ? */
+  if (environment() == this_player()) 
+  {
+   this_object()->move(environment(this_player()));
+  }
+
+  tied_to_ob = ob;
+
+  if (tied_to_ob != environment(this_player()) || 
+      environment(this_player())->name()!=0 )
+   {
+    tied_name = (string)(tied_to_ob->name(WEM));
+   }
+  else
+   {
+    if( !stringp(tied_name) ) tied_name="etwas";
+   }
+
+  if(QueryProp(P_TIE_VERB))
+  {
+    // das seil wird gesteuert
+    tell_room(environment(),QueryProp(P_TIE_MESSAGE));
+
+    // seil wieder in roh-zustand versetzen.
+    SetProp(P_UNTIE_MESSAGE,0);
+    SetProp(P_TIE_VERB,0);
+  }
+  else
+  {
+   write("Du bindest "+name(WER)+" an " + tied_name + " fest.\n");
+   say(this_player()->name(WER) + " bindet "+name(WER)+" an "
+   + tied_name + " fest.\n");
+  }
+
+  // den object mitteilen, an wen es gebunden ist.
+  if(tied_to_ob->QueryProp(P_TIED)==0) tied_to_ob->SetProp(P_TIED,([]) );
+  tied_to_ob->SetProp(P_TIED,tied_to_ob->QueryProp(P_TIED)+([this_object(): 
+     ([
+       "player":this_player(),
+       "time"  :time()
+     ]) ]));
+
+  return 1;
+ }
+
+ if( (member( ({
+         "binde",
+         "bind",
+         "knote",
+         "mach",
+         "mache",
+         "loese" 
+         }),verb                 
+    )!=-1) && 
+    sscanf(str,"%s los",t1)==1)
+  {
+   if (!tied_to_ob)
+   {
+    write(Name(WER)+" ist nirgendwo festgebunden.\n");
+    return 1;
+   }
+
+   if (!call_other(tied_to_ob, "untie"))
+   {
+    write("Das klappt leider nicht.\n");
+    return 1;
+   }
+
+   if(QueryProp(P_TIE_VERB))
+   {
+    // das seil wird gesteuert
+    tell_room(environment(),QueryProp(P_UNTIE_MESSAGE));
+
+    // wieder in roh-zustand versetzen.
+    SetProp(P_UNTIE_MESSAGE,0);
+    SetProp(P_TIE_VERB,0);
+   }
+   else
+   {
+    write("Du bindest "+name(WER)+" los.\n");
+    say(this_player()->name()+" bindet "+name(WER)+" los.\n");
+   }
+
+  tied_map=([])+tied_to_ob->QueryProp(P_TIED);
+  tied_map=m_copy_delete(tied_map,this_object());
+
+  tied_to_ob->SetProp(P_TIED,tied_map);
+
+  tied_to_ob = (object) 0;
+ 
+  return 1;
+ }
+ return 0;
+}
+
+int loesen(string str)
+{
+ if(str == "seil"  ||
+    str == lower_case(QueryProp(P_NAME)) ||
+    id(str)
+ )
+ {
+  return tie("seil los");
+ }
+ _notify_fail("Was moechtest Du loesen?\n");
+ return 0;
+}
+
+
+object query_tied_to_ob()
+{
+  return tied_to_ob;
+}
+
+varargs int binde_seil(string ziel,string msg)
+{
+ if(!QueryProp(P_TIE_AUTO)) return 0;
+
+ // diese funktion bindet ein Seil und kann von einem object aus 
+ // aufgerufen werden.
+ SetProp(P_TIE_VERB,"binde");
+
+ if(!msg) msg = Name(WER)+" wird auf magische Art und Weise festgebunden.\n";
+
+ SetProp(P_TIE_MESSAGE,msg);
+ return tie("seil an "+ziel); 
+}
+
+varargs int loese_seil(string msg)
+{
+ if(!QueryProp(P_TIE_AUTO)) return 0;
+
+ if(!msg) msg = Name(WER)+" loest sich.\n";
+ 
+ SetProp(P_TIE_VERB,"binde");
+ SetProp(P_UNTIE_MESSAGE,msg);
+ return tie("seil los");
+}
+