Added public files

Roughly added all public files. Probably missed some, though.
diff --git a/std/room/kraeuter.c b/std/room/kraeuter.c
new file mode 100644
index 0000000..24f5193
--- /dev/null
+++ b/std/room/kraeuter.c
@@ -0,0 +1,240 @@
+#define NEED_PROTOTYPES
+#include <thing/properties.h>
+#include <thing/language.h>
+#include <thing/description.h>
+#include <thing/commands.h>
+#undef NEED_PROTOTYPES
+#include <moving.h>
+#include <items/kraeuter/kraeuter.h>
+#include <defines.h>
+#include <living/combat.h> // Fuer P_FREE_HANDS
+
+// Standardwert von 2 h fuer vollstaendige Regeneration des Krautes. 
+// Einfaches Nachwachsen ist typischerweise die Haelfte davon.
+#define STD_WACHSTUM  7200
+#define BS(x)         break_string(x, 78)
+
+// Struktur (6 Eintraege pro Kraut):
+// ([ filename : ({ Zeit_bis_nachgewachsen, Zeit_bis_komplett_regeneriert,
+//                  Kraut-IDs, Kraut-Adjektive, Kraut->Name(WER,1),
+//                  ID_des_Bewacher-NPCs }) ])
+mapping plantMap = ([]);
+
+// kann benutzt werden um schnell und einfach eine Pflanze in einem Raum
+// hinzuzufuegen. Beispiel: AddPlant(BAERENKLAU);
+// Diese Funktion erzeugt automatisch ein AddCmd() fuer das Pfluecken und
+// (falls noch nicht vorhanden) Details fuer die Pflanze.
+// Rueckgabewerte:
+// 1 -> Erfolg; -1 -> filename ungueltig
+varargs int AddPlant(string filename, string|string* npcId)
+{
+  mixed arr;
+
+  // Dateiname nicht uebergeben? Dann tun wir erstmal gar nix.
+  if (!stringp(filename)) 
+    return -1;
+  object ob=load_object(filename);
+   
+  // Wenn wir zu dem Kraut schon Daten haben (erkennbar an >2 Eintraegen),
+  // werfen wir einen Fehler, damit das beim Laden des Raumes schon
+  // erkannt wird.
+  if (pointerp(arr=plantMap[filename]) && sizeof(arr)>2)
+    raise_error("AddPlant(): "+filename+" already exists.\n");
+
+  // IDs und Adjektive parsen und den Datensatz zusammenstellen
+  string *ids = ob->Query(P_IDS, F_VALUE)-({ "Ding" });
+  string *adj = ob->Query(P_ADJECTIVES, F_VALUE);
+  
+  if (!pointerp(arr) || sizeof(arr)<2) 
+    arr = ({0,0});
+  if ( !npcId )
+    npcId = ({});
+  else if (stringp(npcId))
+    npcId = ({npcId});
+  plantMap[filename]=({arr[0], arr[1], ids, adj, ob->Name(WER, 1), npcId });
+   
+  // Details erzeugen aus Adjektiven und IDs
+  adj = ob->QueryProp(P_NAME_ADJ);
+  
+  // aktuelles Geschlecht zwischenspeichern, wird spaeter wiederhergestellt
+  int gender = Query(P_GENDER, F_VALUE);
+  Set(P_GENDER, ob->Query(P_GENDER, F_VALUE), F_VALUE);
+  
+  // erzeugt fuer jede moegliche Kombination aus Adjektiv im Akkusativ
+  // und ID des Krautes ein Detail.
+  adj = map(adj, #'DeclAdj, WEN, 0);
+
+  string *det=({});
+  foreach(string _id : ids) {
+    foreach(string _adj : adj) {
+      det += ({ _adj + _id });
+    }
+  }
+
+  det += ids;
+  // keine existierenden Details ueberschreiben
+  det -= m_indices(Query(P_DETAILS, F_VALUE) || ([]));
+  if (sizeof(det)) 
+    AddDetail(det, ob->Query(PLANT_ROOMDETAIL, F_VALUE));
+  
+  // Eine Befehlsfunktion brauchen wir natuerlich auch.
+  AddCmd(({"pflueck", "pfluecke", "ernte"}), "_pfluecken");
+  
+  return 1;
+}
+
+// Wenn jemand per Hand das Plantdetail hinzufuegen moechte...
+// z.B. bei Verwendung von GetPlant() anstelle von AddPlant()
+void AddPlantDetail(string filename)
+{
+  // Pfad in Objektpointer wandeln
+  object ob=load_object(filename);
+   
+  // Details erzeugen
+  string *det = ({});
+  string *ids = ob->Query(P_IDS, F_VALUE)-({ "Ding" });
+  string *adj = ob->QueryProp(P_NAME_ADJ);
+  // aktuelles Geschlecht zwischenspeichern, wird spaeter wiederhergestellt
+  int gender=Query(P_GENDER, F_VALUE);
+  Set(P_GENDER, ob->Query(P_GENDER, F_VALUE));
+  // erzeugt fuer jede moegliche Kombination aus Adjektiv im Akkusativ
+  // und ID des Krautes ein Detail.
+  adj = map(adj, #'DeclAdj, WEN, 0);
+  foreach(string _id : ids) {
+    foreach(string _adj : adj) {
+      det += ({ _adj + _id });
+    }
+  }
+  AddDetail(det+ids, ob->Query(PLANT_ROOMDETAIL, F_VALUE));
+  // Geschlecht zuruecksetzen
+  Set(P_GENDER, gender, F_VALUE);
+}
+
+// Prueft, ob die Pflanze zu "filename" in diesem Raum schon nachgewachsen
+// ist.
+protected int CheckPlant(string filename)
+{
+  mixed arr=plantMap[filename];
+  if (!pointerp(arr) || sizeof(arr)<2) {
+    arr=plantMap[filename]=({ 0, 0 });
+  }
+  // Solange die Zeit arr[0] noch nicht erreicht ist, ist das Kraut nicht 
+  // nachgewachsen, dann gibt es gar nix.
+  return (time()>arr[0]);
+}
+
+// Moechte man AddPlant() nicht benutzen, weil man die Pflanze nicht einfach
+// pfluecken, sondern vielleicht abschneiden, oder ausgraben soll, so kann
+// man sich mittels GetPlant(filename) das Objekt erzeugen lassen. Gibt
+// GetPlant() 0 zurueck, ist die Pflanze noch nicht wieder weit genug
+// nachgewachsen.
+object GetPlant(string filename)
+{
+  int *arr=plantMap[filename];
+  if (!pointerp(arr) || sizeof(arr)<2)
+  {
+     arr=plantMap[filename]=({ 0, 0 });
+  }
+  // arr[0] enthaelt den Zeitpunkt, wann das Kraut nachgewachsen ist,
+  int nachgewachsen = arr[0];
+  // arr[1] denjenigen, wann es vollstaendig regeneriert ist.
+  int regeneriert = arr[1];
+
+  // Vor dem Nachgewachsen-Zeitpunkt kann man gar nix ernten.
+  if (time()<nachgewachsen) return 0; // noch nicht nachgewachsen
+
+  // Restzeit bis zur vollstaendigen Regeneration.
+  regeneriert-=time();
+  
+  // Wenn vollstaendig regeneriert, ist STD_WACHSTUM die neue Zeit bis zur
+  // Regeneration. Wenn noch nicht vollstaendig regenriert, Restzeit
+  // verdoppeln und STD_WACHSTUM nochmal drauf addieren.
+  regeneriert = (regeneriert<=0 ? STD_WACHSTUM 
+                                : (regeneriert*2)+STD_WACHSTUM);
+  // nachgewachsen ist die halbe Regenerationszeit
+  arr[0]=nachgewachsen=time()+(regeneriert/2);
+  // Zeit voelliger Regeneration
+  arr[1]=regeneriert+=time();
+  
+  return clone_object(filename);
+}
+
+static int _pfluecken(string str)
+{
+  int res;
+
+  if (!mappingp(plantMap)) return 0;
+  _notify_fail("WAS moechtest Du pfluecken?\n");
+
+  // IDs und Adjektive zwischenspeichern
+  mixed ids = Query(P_IDS, F_VALUE);
+  mixed adj = Query(P_ADJECTIVES, F_VALUE);
+
+  foreach(string key, mixed krautinfo : plantMap) 
+  {
+    if ( sizeof(krautinfo) != 6 )
+      continue;
+ 
+    // IDs und Adjektive des Krautes kopieren 
+    Set(P_IDS, krautinfo[2], F_VALUE);
+    Set(P_ADJECTIVES, krautinfo[3], F_VALUE);
+
+    // Syntaxpruefung wird dann mit id() gemacht.
+    if (id(str)) 
+    {
+      object ob;
+      object bewacher;
+      res=1;
+
+      // Liste der eingetragenen Bewacher-IDs durchlaufen und pruefen, ob
+      // mindestens einer davon anwesend ist.
+      foreach( string npcId : krautinfo[5] )
+      {
+        bewacher = present(npcId, ME);
+        if (objectp(bewacher))
+          break;
+      }
+      
+      if ( !PL->QueryProp(P_FREE_HANDS) ) 
+      {
+        tell_object(PL, BS("Du hast keine Hand frei, um etwas pfluecken "
+          "zu koennen."));
+      }
+      // Ist der Bewacher anwesend? Dann kann man das Kraut nicht pfluecken.
+      else if ( objectp(bewacher) )
+      {
+        tell_object(PL, BS(bewacher->Name(WER, 2)+" laesst Dich "
+          "leider nicht nah genug heran. Irgendwie musst Du Dich wohl "
+          "zunaechst um "+bewacher->QueryPronoun(WEN)+" kuemmern."));
+      }
+      // Wenn GetPlant() ein Objekt liefert, kann was gepflueckt werden.
+      else if ( objectp(ob=GetPlant(key)) ) 
+      {
+        if ( ob->move(PL, M_GET) == MOVE_OK )
+        {
+          write(BS("Vorsichtig pflueckst Du "+ob->name(WEN, 1)+
+            " und nimmst "+ob->QueryPronoun(WEN)+" an Dich."));
+        }
+        else 
+        {
+          write(BS("Vorsichtig pflueckst Du "+ob->name(WEN, 1)+", kannst "+
+            ob->QueryPronoun(WEN)+" aber nicht nehmen."));
+          ob->move(environment(PL), M_GET);
+        }
+      }
+      // Wenn alles nicht, dann ist das Kraut noch nicht wieder da.
+      else 
+      {
+        write(BS(krautinfo[4]+" ist noch nicht reif genug "
+          +"und muss erst noch etwas wachsen."));
+        break;
+      }
+    }
+  }
+   // IDs und Adjektive zuruecksetzen.
+  Set(P_IDS, ids, F_VALUE);
+  Set(P_ADJECTIVES, adj, F_VALUE);
+
+  return res;
+}
+