Added public files

Roughly added all public files. Probably missed some, though.
diff --git a/std/thing/sockets.c b/std/thing/sockets.c
new file mode 100644
index 0000000..64d9899
--- /dev/null
+++ b/std/thing/sockets.c
@@ -0,0 +1,254 @@
+// MorgenGrauen MUDlib
+/** @file
+* Implementation fuer Sockelitems.
+* Langbeschreibung... TODO
+* @author Zesstra + Arathorn
+* @date xx.05.2008
+* @version $Id$
+*/
+
+/* Changelog:
+*/
+#pragma strong_types
+#pragma save_types
+#pragma no_clone
+#pragma no_shadow
+#pragma pedantic
+#pragma range_check
+
+#define NEED_PROTOTYPES
+#include <thing/sockets.h>
+#undef NEED_PROTOTYPES
+#include <defines.h>
+#include <lpctypes.h>
+
+#ifndef DEBUG
+/** Outputs debug message to Maintainer, if Maintainer is logged in. 
+*/
+#define DEBUG(x) __debug_msg__(x)
+#endif
+
+
+private void __debug_msg__(string x) {
+  if (find_player("zesstra"))
+      tell_object(find_player("zesstra"),"SDBG: "+x+"\n");
+}
+
+/** Setzt \a item in einen passenden Sockel ein.
+  Wird vom Handwerker gerufen. Sofern die Pruefung mittels TestSocketItem()
+  erfolgreich ist, werden die Props dieses Objekt durch die im Item
+  gespeicherten in P_SOCKET_PROPS ergaenzt, ggf. P_RESTRICTION geaendert und
+  Name der Blueprint, Name und P_SOCKET_PROPS in P_SOCKETS gespeichert, um
+  spaeter nachvollziehen zu koennen, wie dieses Objekt bereits modifiziert
+  wurde.
+  @attention Am Ende der Funktion wird \a item zerstoert und darf nicht mehr
+  benutzt werden!
+  @param[in] item Objekt, welches in einen passenden Socket eingesetzt werden
+  soll.
+  @return 1, falls Einsetzen erfolgreich, <0 wenn nicht.
+  @sa TestSocketItem(object)
+ */
+public int MountSocketItem(object item) {
+  if (!objectp(item)) return SOCKET_NO_OBJECT;
+  if ((int res=TestSocketItem(item)) != SOCKET_OK)
+    return res;
+  mapping idata=(mapping)item->QueryProp(P_SOCKET_PROPS);
+  // TODO: Spezialbehandlung fuer Props, bei denen das Objekt erhalten bleiben
+  // muss. (z.B. P_DEFEND_FUNC).
+
+  // zu modifizierende Props addieren
+  foreach(string propname, mixed pval: idata) {
+    SetProp(propname, AddToEntity(QueryProp(propname), pval) );
+  }
+  // Restrictions hinzufuegen.
+  SetProp(P_RESTRICTIONS, 
+      AddToEntity(QueryProp(P_RESTRICTIONS), 
+	item->QueryProp(P_SOCKET_RESTR_USE)) );
+
+  // Daten ueber dieses Socketitem abspeichern.
+  mixed sockets=QueryProp(P_SOCKETS)[item->QueryProp(P_SOCKET_TYPE)];
+  // freier Sockel muss existieren (->TestSocketItem())
+  int index=member(sockets, SOCKET_FREE);
+  sockets[index] = idata + (["BLUE_NAME": load_name(item),
+                           "DESCRIPTION": item->name(WER) ]);
+
+  // ggf. Beschreibung aktualisieren?
+  // ggf. Sonderbehandlung fuer Props, bei denen das Objekt noch gebraucht
+  // wird (z.B. P_DEFEND_INFO)
+
+  // Prop schuetzen, sobald Daten drin stehen.
+  Set(P_SOCKETS, PROTECTED|NOSETMETHOD, F_MODE_AS);
+
+  // item entsorgen
+  if (!item->remove(1))
+    raise_error(sprintf("MountSocketItem() in %O: %O hat Ausfuehrung von "
+	  "remove() verweigert.\n", ME, item));
+  return SOCKET_OK;
+}
+
+/** Prueft, ob \a item in einen Sockel eingesetzt werden kann.
+  Prueft, ob es fuer das Item einen passenden Sockel gibt und ob 
+  es die formalen Anforderungen erfuellt, dort eingesetzt zu werden. 
+  Kann vom Handwerker vor dem echten Einsetzen gerufen werden.
+  Wird auch von MountSocketItem(object) gerufen.
+  @param[in] item Objekt, welches auf Eignung zum Einsetzen in einen Sockel
+  getestet werden soll.
+  @return 1, falls ein passender und freier Sockel existiert, 0 sonst.
+  @sa MountSocket(object)
+*/
+public int TestSocketItem(object item) {
+
+  if (!objectp(item)) return SOCKET_NO_OBJECT;
+  
+  // ist es ein Sockelitem und hat es einen gueltigen Typ?
+  mapping idata = (mapping)item->QueryProp(P_SOCKET_PROPS);
+  if (!mappingp(idata) || !sizeof(idata))
+    return SOCKET_NO_DATA;
+  string styp=(string)item->QueryProp(P_SOCKET_TYPE);
+  if (!stringp(styp)
+      || member(VALID_SOCKET_TYPES, styp) == -1)
+    return SOCKET_INVALID_TYPE;
+
+  // Hat dieses Item ueberhaupt Sockel? Und wenn ja, haben wir nen freien
+  // Socke fuer den betreffenden Typ?
+  mapping mysockets = QueryProp(P_SOCKETS);
+  if (!mappingp(mysockets) || !sizeof(mysockets)) 
+    return SOCKET_NO_SOCKETS;
+  if (!member(mysockets, styp)
+      || !member(mysockets[styp], SOCKET_FREE) == -1 )
+    return SOCKET_NONE_AVAILABLE;
+
+  // Handwerker pruefen.
+  // TODO: Soll die Fehlermeldung komplett vom Aufrufer erledigt werden oder
+  // soll es einen Heinweis geben, warum der Handwerker nicht geeignet ist?
+  object craftsman = previous_object();
+  mapping restr = (mapping)item->QueryProp(P_SOCKET_RESTR_MOUNT);
+  if (!objectp(craftsman)
+      || (mappingp(restr)
+	&& "/std/restriction_checker"->check_restrictions(craftsman,
+	  restr)))
+    return SOCKET_NO_EXPERTISE;
+
+  // da P_RESTRICTION nur beim Anziehen/Zuecken geprueft wird, darf man ein
+  // Item nicht in getragenem Zustand modifizieren.
+  if (objectp((object)item->QueryProp(P_WIELDED))
+      || objectp((object)item->QueryProp(P_WORN)))
+    return SOCKET_ITEM_INUSE;
+
+  return SOCKET_OK;
+}
+
+/** Liefert Infos ueber die Sockets (Typ, was drin ist, etc.\ ).
+  Primaer fuer Gilden gedacht.
+*/
+public mixed GetSocketInfo() {
+}
+
+/* **************************** private ************************* */
+
+/** Addiert zwei Variablen, sofern sie kompatibel sind.
+  Lassen sich die beiden Datentypen nicht sinnvoll addieren, erfolgt keine
+  Addition und \a old wird zurueck geliefert (z.B. bei Objekten, Closures).
+  Hierbei erfolgt z.B. bei Mappings eine wertweise Addition, keine blosse
+  Ersetzung der Keys wie bei der normalen Mapping-Addition.
+  @param[in,out] old Datum, zu dem addiert werden soll. Wird bei Mappings
+  geaendert.
+  @param[in] new Datum, welches addierten soll.
+  @return Summe von old und new, falls die Datentypen kompatibel sind. Falls
+  nicht, kann old zurueckgegeben werden. Der Datentyp von 
+  @attention \b Rekursiv! Kann teuer werden.\n
+    Kann (modifizierte) \a old oder \a new oder ganz neues Datum 
+    zurueckliefern, d.h. der zurueckgelieferte Datentyp muss nicht dem
+    Datentyp von old entsprechen. Ebenso erzeugt z.B. die Addition zweier
+    Arrays ein neues Array.
+    Wenn die korrespondierenden Werte nicht den gleichen Datentyp haben,
+    findet u.U. keine Addition statt oder es wird eine Datentyp-Umwandlung
+    durchgefuehrt, z.B. Int + Float == Float.\n
+  */
+private mixed AddToEntity(mixed old, mixed new) {
+
+  // einfachste Faelle:
+  if (!old)
+    return new;
+  else if (!new)
+    return old;
+
+  // Typ bestimmen
+  int oldtype = typeof(old);
+  int newtype = typeof(new);
+  // Variablen gleichen Typs sind einfach.
+  if (oldtype == newtype) {
+    switch (oldtype) {
+      // einige Typen werden stumpf addiert.
+      case T_NUMBER:
+      case T_STRING:
+      case T_FLOAT:
+      case T_POINTER: // TODO: anderes Verhalten?
+	return old+new;
+      // Mappings werden wertweise addiert.
+      case T_MAPPING:
+	// nur wenn die Breite des 2. Summanden <= der des 1. Summanden ist,
+	// lassen sich Mappings hiermit addieren.
+	if (widthof(new) > widthof(old))
+	  return old;
+	// new auf old addieren. Keys werden nicht ersetzt, sondern nach
+	// Moeglichkeit die werte unter den keys jeweils addiert.
+	// map() nur zum Uebergeben aller Keys+Value. AddToMapping aendert
+	// direkt das uebergebene Mapping old.
+	map(new, #'AddToMapping, old); 
+	// alles hier nicht aufgefuehrte kann nicht addiert werden.
+      default: return old;
+    }
+  }
+  // Ints und Floats sind auch noch gut addierbar.
+  else if ((oldtype == T_FLOAT && newtype == T_NUMBER) ||
+           (oldtype == T_NUMBER && newtype == T_FLOAT) )
+    return old + new;
+  // Arrays lassen sich auch gut verwursten (new kann kein Array sein).
+  // Umgekehrter Fall waere auch meoglich, aber der Datentyp von old waere
+  // sehr deutlich unterschiedlich vom urspruenglichen.
+  else if (oldtype == T_POINTER)
+    return old+({new});
+  // Strings und Zeichenliterale (Ints) sind Ansichtssache.
+  else if (oldtype == T_STRING && newtype == T_NUMBER)
+    return sprintf("%s%c",old,new);
+  else if (oldtype == T_NUMBER && newtype == T_STRING)
+    return sprintf("%c%s",old,new);
+
+  // Fall-through
+  return old;
+}
+
+/** Addiert einen Schluessel und seine Werte zu einem Mapping, ggf.\ auf die
+ * bestehenden Werte des Mappings \a old.
+ * Der Key und seine Werte ersetzen bestehende Werte in \a old nicht, wie es
+ * die normale Mapping-Addition des Driver macht. Stattdessen wird versucht,
+ * die neuen Werte auf die entsprechenden alten Werte zu addieren. Falls die
+ * Datentypen zweier Werte inkompatibel sind, erfolgt keine Addition und der
+ * alte Werte hat Bestand.
+  @param[in] key (mixed) Wert, der in das Mapping addiert wird.
+  @param[in] values (mixed)
+  @param[in,out] old Mapping, in das addiert wird.
+  @attention Die Breites des 2. Summanden darf \b nicht groesser sein als die
+  Breite des 1, Summanden! \n
+    Die korrespondieren Werte sollten den gleichen Datentyp haben, sonst
+    findet u.U. keine Addition statt oder es wird eine Datentyp-Umwandlung
+    durchgefuehrt, z.B. Int + Float == Float.\n
+  */
+private void AddToMapping(mixed key, mixed values, mapping old) {
+  if (!mappingp(old)) return;
+  if (!pointerp(values)) values = ({values});
+
+  // wenn der Key noch nicht existiert, ists einfach.
+  if (!member(old, key))
+    m_add(old, key, values...); // flatten operator ... cool. ;-)
+  else {
+    // sonst muessen wir teure handarbeit machen. Insb. weil die Values einen
+    // beliebigen Datentyp haben koennen, u.a. Mappings, weswegen wir wieder
+    // rekursiv AddToEntity() rufen muessen.
+    for(int i=sizeof(values) ; i-- ; ) {
+      old[key,i] = AddToEntity(old[key,i], values[i]);
+    }
+  }
+}
+