Added public files

Roughly added all public files. Probably missed some, though.
diff --git a/room/death/death_room.c b/room/death/death_room.c
new file mode 100644
index 0000000..5e59f20
--- /dev/null
+++ b/room/death/death_room.c
@@ -0,0 +1,669 @@
+// MorgenGrauen MUDlib
+//
+// death_room.c -- Der Todesraum
+//
+// $Id: death_room.c 9138 2015-02-03 21:46:56Z Zesstra $
+
+
+#pragma strict_types
+
+#include <defines.h>
+#include <properties.h>
+#include <moving.h>
+#include <language.h>
+#include <wizlevels.h>
+#include <daemon.h>
+#include <new_skills.h>
+
+inherit "/std/room";
+
+mixed *players;
+mapping msgCache;
+
+
+private void flush( int unusedOnly );
+private string expand( string table, int value );
+private string parseText( string msg, object pl );
+private void do_remove();
+private varargs mixed get_sequence( string str );
+void add_player( object pl );
+static int filter_ldfied( string str );
+public int SmartLog( string creat, string myname, string str, string date );
+public mixed hier_geblieben( mixed dest, int methods, string direction,
+                             string textout, string textin );
+public void init()
+{
+  this_player()->move("/room/death/virtual/death_room_"+getuid(this_player()),
+	     M_NOCHECK|M_SILENT|M_NO_SHOW);
+  return;
+}
+
+public void create()
+{
+  if (IS_CLONE(this_object())) return;
+    ::create();
+    
+    players = ({});
+    flush(0);
+
+    SetProp( P_NAME, "Lars" );
+    SetProp( P_GENDER, MALE );
+    SetProp( P_ARTICLE, 0 );
+    SetProp( P_LIGHT,1 );
+    SetProp( P_NO_TPORT, NO_TPORT_OUT );
+    SetProp( P_LOG_FILE, "TOD/Todesraum" );
+    SetProp( P_INT_SHORT, "Arbeitszimmer des Todes" );
+    SetProp( P_INT_LONG, break_string(
+             "Ein dunkler Raum, erleuchtet von dunklem Licht, das sich der "
+             "Dunkelheit nicht so sehr zu widersetzen scheint, indem es "
+             "leuchtet, als dass es der dunkelste Punkt in einer weniger "
+             "dunklen Umgebung ist. Im seltsamen Licht erkennst Du einen "+
+             "zentral aufgestellten Schreibtisch, der mit Diagrammen und "
+             "Buechern bedeckt ist. Die Waende verschwinden hinter Regalen, "
+             "die gefuellt sind mit in Leder gebundenen, dunklen Waelzern, "
+             "von denen geheimnisvolle Runen leuchten.\nTod.", 78, 0, 1 ) );
+}
+
+
+public void reset()
+{
+    ::reset();
+    flush(1);
+}
+
+private void flush( int unusedOnly )
+{
+    string *mi;
+    int i;
+
+    if ( unusedOnly ){
+        if ( i = sizeof(mi = m_indices(msgCache)) ){
+            for ( ; i--; )
+                if ( msgCache[mi[i], 1] )
+                    msgCache[mi[i], 1] = 0;
+                else
+                    msgCache = m_copy_delete( msgCache, mi[i] );
+        }
+    }
+    else
+        msgCache = ([]);
+}
+
+
+private string expand( string table, int value )
+{
+    int sz, wert, i;
+    string *texte;
+
+    sz = sizeof( texte = explode( table, "##" ) - ({""}) );
+    
+    for ( i = 0; i < sz; i++ )
+        if ( i%2 ){
+            sscanf( texte[i], "%d", wert );
+            
+            if ( value < wert )
+                break;
+        }
+        else
+            table = texte[i];
+
+    return table;
+}
+
+
+#define TOS(s) s[<1]
+#define STOS(s) s[<2]
+#define PUSH(x,s) (s+= ({ x }))
+#define POP(s)	(s=s[0..<2])
+
+// ziemlich vom htmld abgekupfert ;)
+private string
+parseText( string msg, object pl ) 
+{
+  string *words, *texte, *todo, *done;
+  int endFlag;
+
+  int sz = sizeof( words = regexplode(msg, "[<][^>]*[>]") );
+  todo = ({ });
+  done = ({""});
+
+  for ( int i=1; i<sz; i+=2 ){
+      string cmd = words[i][1..<2];
+      TOS(done) += words[i-1];
+
+      if ( cmd[0] == '/' ){
+          endFlag = 1;
+          cmd = cmd[1..];
+      }
+      else
+          endFlag = 0;
+      
+      switch( cmd[0] ){
+      case 'A': /*** Alignment ersetzen ***/
+          if (!endFlag){
+              PUSH( cmd, todo );
+              PUSH( "", done );
+          }
+          else
+              if ( todo[<1] == "A" ){
+                  STOS(done) += expand(TOS(done), (int) pl->QueryProp(P_ALIGN));
+                  done = done[0..<2];
+                  todo = todo[0..<2];
+              }
+          break;
+          
+      case 'D': /*** Tode ersetzen ***/
+          if ( !endFlag ){
+              PUSH( cmd, todo );
+              PUSH( "", done );
+          }
+          else
+              if ( todo[<1] == "D" ){
+                  STOS(done) += expand(TOS(done), (int) pl->QueryProp(P_DEADS));
+                  POP(done);
+                  POP(todo);
+              }
+          break;
+          
+      case 'L': /*** Level ersetzen ***/
+          if ( !endFlag ){
+              PUSH( cmd, todo );
+              PUSH( "", done );
+          }
+          else
+              if ( todo[<1] == "L" ){
+                  STOS(done) += expand(TOS(done), (int) pl->QueryProp(P_LEVEL));
+                  POP(done);
+                  POP(todo);
+              }
+          break;
+          
+      case 'Z': /*** Zufall ersetzen ***/
+          if ( !endFlag ){
+              PUSH( cmd, todo );
+              PUSH( "", done );
+          }
+          else{
+              if ( todo[<1][0] == 'Z'){
+                  int cnt, rnd, wert, sz2;
+                  
+                  if ( !sscanf(todo[<1], "Z=%d", rnd) )
+                      STOS(done) += "\n###\n### Syntax Error in <Z>!\n###\n\n";
+                  else {
+                      rnd = random(rnd);
+                      sz2 = sizeof( texte = explode(TOS(done), "##") );
+                      wert=0;
+                      cnt=0;
+                      
+                      for ( int k = 1; k < sz2; k += 2 ){
+                          sscanf( texte[k], "%d", wert );
+                          cnt += wert;
+                          if ( rnd < cnt ) {
+                              STOS(done) += texte[k+1];
+                              break;
+                          }
+                      }
+                  }
+                  POP(done);
+                  POP(todo);
+              }
+          }
+          break;
+
+      case 'G': /*** Gender ersetzen ***/
+          if ( !endFlag ){
+              PUSH( cmd, todo );
+              PUSH( "", done );
+          }
+          else{
+              if( sizeof( texte = regexplode(TOS(done), ":") ) == 3 )
+                  STOS(done) += texte[2*((int) pl->QueryProp(P_GENDER)
+                                         == FEMALE)];
+              POP(done);
+              POP(todo);
+          }
+          break;
+
+      case 'R': /*** Rasse ersetzen ***/
+          if ( !endFlag ){
+              PUSH( cmd, todo );
+              PUSH( "", done );
+          }
+          else{
+              int race;
+
+              texte = regexplode( TOS(done), "\\|" );
+              race = 2 * (member( ({ "Mensch", "Elf", "Zwerg", "Hobbit",
+                                         "Feline", "Dunkelelf" }),
+                                  (string) pl->QueryProp(P_RACE) ) + 1);
+              
+              if ( race >= sizeof(texte) )
+                  race = 0;
+
+              STOS(done) += texte[race];
+              POP(done);
+              POP(todo);
+          }
+          break;
+
+      case 'n': /*** Name, normal geschrieben ***/
+          TOS(done) += (string) (pl->name(RAW));
+          break;
+
+      case 'N': /*** Name, in Grossbuchstaben ***/
+          TOS(done) += upperstring(pl->name(RAW));
+          break;
+      }
+  }
+  PUSH( words[<1], done );
+  return implode( done, "" );
+}
+
+
+public void heart_beat()
+{
+    for ( int j = sizeof(players); j--; )
+        if ( !objectp(players[j][0]) ||
+             environment(players[j][0]) != 
+	     find_object("/room/death/virtual/death_room_"+getuid(players[j][0])) )
+            players[j] = 0;
+
+    players -= ({0});
+
+    if ( !sizeof(players) ) {
+        set_heart_beat(0);
+        return;
+    }
+
+  for ( int j = sizeof(players); j--; ) {
+      int nr;
+      string msg;
+
+      nr = ++players[j][1];
+
+      if ( mappingp(players[j][2]) )
+          msg = players[j][2][nr];
+      else
+          msg = 0;
+      
+      if ( !msg )
+          msg = players[j][3][1][nr];
+      
+      if ( msg )
+          tell_object( players[j][0], parseText( msg, players[j][0] ) );
+  }
+  
+  do_remove();
+}
+
+private void
+do_remove()
+{
+    int res;
+    string prayroom;
+    object plobj, pl;
+    
+    for ( int j = sizeof(players); j--; ){
+        if ( players[j][1] >= players[j][3][0]){
+            pl = players[j][0];
+            while ( plobj = present("\ndeath_mark", pl) )
+                plobj->remove();
+            
+            if ( !(prayroom = (string) pl->QueryPrayRoom()) )
+                prayroom="/room/pray_room";
+
+            pl->Set( P_TMP_MOVE_HOOK, 0 );
+            pl->Set( P_NO_ATTACK, 0, F_QUERY_METHOD );
+            pl->Set( P_LAST_KILLER, 0 );
+            pl->Set( P_KILLER, 0 );
+            pl->Set( P_ENEMY_DEATH_SEQUENCE, 0 );
+            pl->Set( P_NEXT_DEATH_SEQUENCE, 0 );
+            pl->Set( P_POISON, 0, F_QUERY_METHOD );
+            
+            if ( catch( res = (int) pl->move(prayroom, M_GO|M_SILENT|M_NOCHECK) )
+                 || res < 1 )
+                pl->move( "/room/pray_room", M_GO|M_NOCHECK );
+
+            players[j] = 0;
+        }
+    }
+
+    players -= ({0});
+
+    if ( !sizeof(players) )
+        set_heart_beat(0);
+}
+
+private varargs mixed
+get_sequence( string str )
+{
+    string *sequences;
+    int i, len, cacheable;
+    
+    if ( !stringp(str) || catch( len = file_size(str) ) || len <= 0 ){
+        sequences = get_dir( "/room/death/sequences/*" ) - ({ ".", "..", ".svn" });
+        str = "/room/death/sequences/" + sequences[random( sizeof(sequences) )];
+    }
+
+    if ( cacheable = ((sizeof(str) > 21) &&
+                      (str[0..21] == "/room/death/sequences/")) ){
+        if ( member(msgCache, str) ){
+            msgCache[str, 1] = 1;  // Touch it!
+            return ({ msgCache[str], str });
+        }
+    }
+    
+    sequences = explode( read_file(str), "\n" );
+    sscanf( sequences[0], "%d", len );
+    string seq = implode( sequences[1..], "\n" );
+    sequences = regexplode( seq, "[0-9][0-9]*:" );
+    mapping m = ([]);
+    
+    for ( i = 1; i < sizeof(sequences)-1; i += 2 )
+        m[(int) sequences[i]] = sequences[i+1];
+
+    if ( cacheable )
+        msgCache += ([ str: ({ len, m }); 1 ]);
+
+    return ({ ({ len, m }), str });
+}
+
+// Description:   Adds a player to the list
+void add_player( object pl )
+{
+    int kart, kgen;
+    int escaped;
+    object kill_liv, kill_ob;
+    mixed dseq, act_seq, killer_name, killer_msg;
+ 
+    set_heart_beat(1);
+    kgen = MALE;
+
+    foreach(object prev : caller_stack(1)) { 
+        if ( !objectp(prev) || prev == pl )
+            continue;
+
+        string fn = object_name(prev);
+
+        if ( fn[0..12] == "/secure/login" && !kill_liv ){
+            escaped = 1;
+            break;
+        }
+
+        if ( fn[0..7] == "/secure/" && fn[0..13] != "/secure/merlin" )
+            continue;
+
+        if ( fn[0..21] == "/room/death/death_mark" )
+            continue;
+
+        if ( living(prev) ){
+            kill_liv = prev; // Killer
+            break;
+        }
+
+        kill_ob = prev; // killendes Objekt
+    }
+
+    object pre = (object) pl->QueryProp(P_KILLER);
+    if ( objectp(pre) ) {
+        dseq = (mixed) pre->QueryProp(P_ENEMY_DEATH_SEQUENCE);
+
+        if( !(killer_name = (mixed) pre->QueryProp(P_KILL_NAME)) ){
+            killer_name = (mixed) pre->QueryProp(P_NAME);
+            kart = (int) pre->QueryProp(P_ARTICLE);
+            kgen = (int) pre->QueryProp(P_GENDER);
+        }
+
+        killer_msg = (mixed)pre->QueryProp(P_KILL_MSG);  
+    }
+
+    if ( !killer_name && kill_liv && function_exists( "QueryProp", kill_liv ) ){
+        dseq = (mixed) kill_liv->QueryProp(P_ENEMY_DEATH_SEQUENCE);
+
+        if( !(killer_name = (mixed) kill_liv->QueryProp(P_KILL_NAME)) ){
+            killer_name = (mixed) kill_liv->QueryProp(P_NAME);
+            kart = (int) kill_liv->QueryProp(P_ARTICLE);
+            kgen = (int) kill_liv->QueryProp(P_GENDER);
+        }
+
+        killer_msg = (mixed) kill_liv->QueryProp(P_KILL_MSG);
+        pre = kill_liv;
+    }
+
+    if ( !killer_name && kill_ob && function_exists( "QueryProp", kill_ob ) ){
+        dseq = (mixed) kill_ob->QueryProp(P_ENEMY_DEATH_SEQUENCE);
+
+        if( !(killer_name = (mixed) kill_ob->QueryProp(P_KILL_NAME)) ){
+            killer_name = (mixed) kill_ob->QueryProp(P_NAME);
+            kart = (int) kill_ob->QueryProp(P_ARTICLE);
+            kgen = (int) kill_ob->QueryProp(P_GENDER);
+        }
+
+        killer_msg = (mixed) kill_ob->QueryProp(P_KILL_MSG);
+        pre = kill_ob;
+    }
+    
+    // falls keine Sequenz gesetzt, eventuelle eigene Todessequenz nehmen
+    if (!dseq)
+      dseq = (mixed)pl->QueryProp(P_NEXT_DEATH_SEQUENCE);
+
+    act_seq = 0;
+
+    if ( mappingp(dseq) )
+        act_seq = get_sequence( "/room/death/sequences/lars" );
+    else if ( pointerp(dseq) )  // ganze Todessequenz...
+        act_seq = ({ dseq, 0 });
+    else if ( stringp(dseq) )
+        act_seq = get_sequence(dseq);
+
+    if(pl->query_hc_play()>1)
+    {
+        act_seq=({({22,([1:"Du faellst und faellst...\n",
+                        5:"und faellst...\n",
+                        10:"und faellst...\n",
+                        12:"direkt in die Arme von TOD.\n",
+                        14:"Triumphierend laechelt er Dich an.\n",
+                        16:"NUN GEHOERST DU FUER IMMER MIR!\n",
+                        18:"HAHHHAHAHAAAAAAAAAAHAAAAAAAAA!\n",
+                        20:"TOD schlaegt Dir mit seiner Sense den Kopf ab.\n"])}),0});
+    }
+    if ( !act_seq )
+        act_seq = get_sequence();
+
+    if ( !mappingp(dseq) )
+        dseq = 0;
+
+    int i;
+    for ( i = sizeof(players); i--; )
+        if ( players[i][0] == pl )
+            break;
+
+    if ( i == -1 )
+        players += ({ ({ pl, 0, dseq, act_seq[0], act_seq[1], pre }) });
+    else
+        players[i][5] = pre;
+
+
+        if ( escaped ){
+            killer_name = "";
+            killer_msg = upperstring(getuid(pl)) + " VERSUCHTE, MIR ZU "
+                "ENTKOMMEN - JETZT HABE ICH WIEDER EXTRA-ARBEIT MIT "+
+                ((int) pl->QueryProp(P_GENDER) != 2 ? "IHM" : "IHR") +
+                " ...";
+        }
+        else if ( !killer_name ) {
+                if ( (string) pl->QueryProp(P_KILLER) == "gift" ){
+                    killer_name = "Vergiftung";
+                    kgen = FEMALE;
+                    kart = 1;
+                }
+                else{
+                    killer_name = "Etwas Geheimnisvolles und Unbekanntes";
+                    kgen = NEUTER;
+                    kart = 0;
+                }
+        }
+
+        if ( !pointerp(killer_msg) )
+            killer_msg = ({ killer_msg, 0, 0 });
+        else if ( sizeof(killer_msg) < 3 )
+            killer_msg += ({ 0, 0, 0 });
+
+        if ( stringp(killer_msg[0]) )
+            killer_msg[0] = sprintf( killer_msg[0], capitalize(getuid(pl)) );
+
+        SetProp( P_NAME, killer_name );
+        SetProp( P_ARTICLE, kart );
+        SetProp( P_GENDER, kgen );
+        string killname = Name(WER);
+        SetProp( P_NAME, "Lars" );
+        SetProp( P_ARTICLE, 0 );
+        SetProp( P_GENDER,MALE );
+
+        int magiertestie;
+        string testplayer = (string) pl->QueryProp(P_TESTPLAYER);
+        if (sizeof(testplayer))
+        {
+          if (testplayer[<5..<1]!="Gilde")
+            magiertestie = 1;
+        }
+          
+        string kanal;
+        if  (magiertestie || IS_LEARNING(pl))
+            kanal = "TdT";
+        else
+            kanal = "Tod";
+
+        CHMASTER->join( kanal, this_object() );
+
+        if ( (!stringp(killer_name) || killer_name != "") &&
+             (sizeof(killer_msg) < 4 || !killer_msg[3]) ){
+            if ( killer_msg[2] == PLURAL )
+                CHMASTER->send( kanal, this_object(),
+                                killname + " haben gerade " +
+                                capitalize(getuid(pl)) + " umgebracht." );
+            else
+                CHMASTER->send( kanal, this_object(),
+                                killname + " hat gerade " +
+                                capitalize(getuid(pl)) + " umgebracht." );
+        }
+
+        i = (int) pl->QueryProp(P_DEADS);
+        if ( i && (getuid(pl) == "key" || i%100 == 0 || i%250 == 0) ){
+            SetProp( P_NAME, "Tod" );
+            CHMASTER->send( kanal, this_object(),
+                            sprintf( "DAS WAR SCHON DAS %dTE MAL!", i ) );
+            SetProp( P_NAME, "Lars" );
+        }
+
+        if( killer_msg[0] ){
+            if ( stringp(killer_name) && killer_name == "" ){
+                CHMASTER->send( kanal, this_object(),
+                                break_string( funcall(killer_msg[0]), 78,
+                                              "["+kanal+":] " )[0..<2],
+                                MSG_EMPTY );
+                return; 
+            }
+            else {
+                if ( (killer_msg[1] < MSG_SAY) || (killer_msg[1] > MSG_GEMOTE) )
+                    killer_msg[1] = MSG_SAY;
+
+                SetProp( P_NAME, killer_name );
+                SetProp( P_ARTICLE, kart );
+                SetProp( P_GENDER, kgen );
+                CHMASTER->send( kanal, this_object(), funcall(killer_msg[0]),
+                                killer_msg[1] );
+                SetProp( P_NAME, "Lars" );
+                SetProp( P_ARTICLE, 0 );
+                SetProp( P_GENDER, MALE );
+            }
+        }
+
+        if ( pointerp(killer_msg = (mixed) pl->QueryProp(P_DEATH_MSG)) &&
+             sizeof(killer_msg) == 2 && stringp(killer_msg[0]) &&
+             intp(killer_msg[1]) ){
+            SetProp( P_NAME, capitalize(getuid(pl)) );
+            SetProp( P_ARTICLE, 0 );
+            SetProp( P_GENDER, pl->QueryProp(P_GENDER) );
+            CHMASTER->send( kanal, this_object(), killer_msg[0],
+                            killer_msg[1] );
+            SetProp( P_NAME, "Lars" );
+            SetProp( P_ARTICLE, 0 );
+            SetProp( P_GENDER, MALE );
+        }
+
+        if (pl->query_hc_play()>1){
+            SetProp( P_NAME, "Tod" );
+            CHMASTER->send( kanal, this_object(),"NUN GEHOERST DU FUER EWIG MIR!" );
+            SetProp( P_NAME, "Lars" );
+        }
+}
+
+public int
+SmartLog( string creat, string myname, string str, string date )
+{
+    int i;
+    string fn;
+    
+    for ( i = sizeof(players); i--; )
+        if ( players[i][0] == this_player() )
+            break;
+
+    // Spieler (Magier?) ist in keiner Todessequenz -> normales Repfile
+    if ( i == -1 )
+        return 0;
+
+    if ( !(fn = players[i][4]) ){
+        // Spieler hat eine unbekannte Todessequenz (kein Filename, Sequenz
+        // wurde komplett in P_ENEMY_DEATH_SEQUENCE abgelegt)
+        creat = "TOD/unbekannt.rep";
+        fn = "unbekannte Todessequenz";
+    }
+    else
+        // Jede Sequenz mit nem eigenen Repfile
+        creat = "TOD/" + explode( fn, "/" )[<1] + ".rep";
+
+    log_file( creat, myname + " von " + getuid(this_interactive())
+              + " ["+fn+"] (" + date + "):\n" + str + "\n" );
+
+    return 1;
+}
+
+public mixed hier_geblieben( mixed dest, int methods, string direction,
+                             string textout, string textin ) 
+{
+    // Magier duerfen Spieler heraustransen
+    if ( this_interactive() && IS_LEARNER(this_interactive()) &&
+         (this_interactive() != previous_object() ||
+          IS_DEPUTY(this_interactive())) ){
+        previous_object()->Set( P_TMP_MOVE_HOOK, 0 );
+        return ({ dest, methods, direction, textout, textin });
+    }
+
+    // Spieler haengt noch in der Todessequenz
+    for ( int i = sizeof(players); i--; )
+        if ( objectp(players[i][0]) && previous_object() == players[i][0] &&
+             environment(previous_object()) == find_object(
+	  "/room/death/virtual/room_death_" + getuid(previous_object()))&&
+             interactive(previous_object()) ) {
+	    // Move nur erlaubt, wenn das Ziel wieder der Todesraum ist.
+	    // wenn mal fuer nen bestimmten Zwecks Bewegungen raus aus dem
+	    // Todesraum erforderlich sind, sollten hier entsprechende
+	    // Ausnahmen eingebaut werden.
+	    if ( (stringp(dest) && 
+		  dest == object_name(environment(previous_object()))) ||
+		 (objectp(dest) &&
+		  dest == environment(previous_object())) ) {
+		previous_object()->Set( P_TMP_MOVE_HOOK, 0 );
+		return ({ dest, methods, direction, textout, textin });
+	    }
+            else
+                return -1;
+        }
+
+    // Spieler ist nicht mehr im Raum oder eingeschlafen
+    if ( previous_object() )
+        previous_object()->Set( P_TMP_MOVE_HOOK, 0 );
+    
+    return ({ dest, methods, direction, textout, textin });
+}