 - eigentlich muessten die ganzen FUnktionen say,
   tell_object, tell_room nicht unbedingt als efuns existierensondern koennten
   direkt in den entsprechenden Zielobjekten indirekt write() aufrufen
   Dazu regelmaessiges Buffer-leeren.
 - Raum: auch REFRESH_PREFUNC, was vor dem ganzen Refresh aufgerufen wird.
- Generisches Init<Prop> mit mehreren Argumenten einbauen, dass auf
   Set<Prop> zurueckfaellt.
 - "Conditional Texts" ( ({ IS_WIZARD, "...", ALL, "..." }) ) muessen
   kein eigener Datentyp sein, sondern koennen ueber Closures gehandhabt
   werden: Set(P_LONG, CTEXT(({...}))).
 - Chatting-Implementierungen:
    - Taktgabe durch zentrales Objekt, dass die Umgebungen aller Spieler
      antriggert
    - Callout/HB je Chatobjekt, gestoppt wenn kein Spieler da ist, neu
      gestartet wenn einer reinkommt.
    - Call to DoChat() aus dem Heartbeat der Livings heraus.
   Fremdgetakteter Chat muss env und all_inv(env) beruecksichtigen.
 - assert() nachbilden und standardmaessig zur Verfuegungstellen.
   Auch ein assertmsg()
 - Exit-Checking moeglichst nur aktivieren durch hinzufuegen einer
   Check-Closure; ueberlagern von CheckAction() nicht notwendig machen.
 - UpdateProps() vorsehen: nur die angegebenen Props werden geaendert,
     alle anderen bleiben so.
 - Spezielle Add-Props, e.g. ADD_P_Ads?
 - SetProperties: unterscheiden koennen zwischen Reset everthing and
   Update the given ones. NF hat automatisch und nur letzteres.
 - Neue Prop: IsVirtual (secure/master.c, std/base.c)
 - Heartbeat: Am besten, dem Heartbeat-Scheduler ueber
   Funktionsregistrierungen regeln, dann kann das ganze Slot-Gedoens
   wegfallen.
 - Not possible: don't inherit loaded objects and vice versa.
     Not possible as the GD doesn't call create(hooks) for already loaded
     objects.
 - /obj/shut auf den Stand von NF bringen.
 - Standardfunktion, um Gegenstaende zu verstecken (wie 'search doormat'
   -> golden key appears).
 - master:slow_shut/quota_demon?: Out of Memory announcen.
 - Shutdown: Shutdown-demon und Armageddon-NPC trennen. Den Demon
     in /arch/svc unterbringen.
 - Syslog-Channel: fuer Nachrichten wenn wo was reseted wird, replaced
     oder so.
 - Wizards koennen NPCs uebernehmen um so das Spiel interessanter zu
   gestalten. Moeglich sind zwei Stufen: mitgeteilt bekommen, was der NPC
   sieht, hoert...; oder der NPC _sein_ (und mitgeteilt bekommen, was der
   Playercharakter sieht/hoert...). Was bei Kontrolle mehrerer NPCs?
   Schaden am NPC schlaegt auf Besetzer durch.
   Umsetzen der exec() nicht ratsam.
   Nicht NF: diese Moeglichkeit auch Spielern zu verfuegung stellen
   (Zauberspruch oder so), plus zusaetzliche Game-Mechanics, die das
   Erkennen/Abwehren von besetzten NPCs (speziell Quest-NPCs) erlaubt.
 - Save-Dirstruktur:
     /save/p/m/mateese.o ist das Player-Savefile
     /save/p/m/mateese/... fuer andere Savefiles, die zu dem Spieler
       gehoeren.
   Oder
     /save/m/mateese.o ist das Player-Savefile
     /save/svc/<svcname>/... fuer andere Savefiles, wobei svc auch
     gilden umfassen koennen, e.g. /save/svc/spellbooks/m/mateese.o
   /rsc ist eigentlich ueberfluessig, /o und /r tun dasselbe und sind
   leichter verstaendlich.
 - Rooms: die Refresh-funktion kann entweder alles selbst machen, oder
     den zu verwendenden Mode zurueckgeben.
 - Simple Skriptingmoeglichkeit fuer NPCs, und sei es eine
   State-Arrayinitialisierung.
 - Resistance/Vulnerability (Rochus, 15. Apr 1996, 15:00:43):
   Die vorgeschlagene Aenderung ist auf grosse Zustimmung bei den
   richtigen Leuten gestossen und wird daher eingebaut :)
   Demnaechst wird also gemittelt, d.h.
    ([DT_FIRE:-0.5, DT_COLD:1.0])
   ergibt dann bei einem Angriff mit
    ({DT_FIRE,DT_COLD})
   genau (0.5+2.0)/2 mal den Schaden, bei
    ({DT_COLD,DT_SLASH,DT_MAGIC})
   waere es (2.0+1.0+1.0)/3 mal der Schaden usw.
 - > > Da du dann den code selbst schreibst, der commandos ausfuehrt, kannst du
   > > da alle hooks reinhaengen, die du magst.
   >
   > Gilt das auch fuer die Auswertung, ob ein Kommando erfolgreich
   > (return 1) oder nicht erfolgreich war (return 0)?
   >
   > Oder anders gefragt: wie geht der Ablauf dann ueberhaupt vor sich?

   Wenn ihr bereit seid, objecte, die spezielle sachen mit
   add_action() machen wie quicktyper etwas anzupassen, kann man die
   suche stark beschleunigen:

   wenn ein object bewegt wird, ruft der move hook in ihm init() auf, und
   die commandos werden zu einem mapping in dem raum / user addiert.

   wenn nun ein commando ausgefuehrt wird, wird erst der raum gefragt, und
   danach das user-eigene mapping abgesucht (mit einer simplen
   indizierung :-)

   Damit man objecte auch wieder entfernen kann, wird ein zweites mapping
   pro raum/user gefuehrt, in dem zu jedem object ein array gespeichert wird,
   das referenzen auf den inhalt des ersten enthaelt.
   Den Eintag braucht man natuerlich nur, wenn tatsaechlich ein init()
   existiert, das add_action() gebraucht.
   definiert

   object_mapping
   object----------------------->array
                                 ||||| Verweise auf alle action_mappings
                                 VVVVV in denen dieses object auftaucht
   command_mapping
       verb ----------------> action_mapping
                                 object ----------> function_name/closure
 - Players->Go(dest, msg) ist sinnvoll?
   Oder halt die Unitopia-Idee, dass die Raeume das Kommando filtern.
 - Bei AddExit() den Ausgaengen bereits eine Messae a la "into the
   tent" mitgeben koennen.
 - Fehlermeldungen (BUGS, TYPO,...) in einer Datenbank halten, dass
   man sie problemlos loeschen kann. Lokale Fehlerdateien sind dann
   nur verweise.
 - Heartbeat: keinen Scheduler, aber dafuer beliebige Anzahl Hooks und
   folgende Methodik:

   /heart:
     public int Heartbeat()
     // Return !0 if heart is still needed.
     {
       evtl. Short-Callout-Code.
     }

     public (private?) nomask void heart_beat()
     {
       int rc;
       if (Netdead))
         stop heart.
       foreach (hook)
       {
         if (funcall(hook))
           rc = 1;
       }
       if (Heartbeat())
         rc = 1;
       if (!rc)
         set_heart_beat(0);
     }
 - Playersafefiles mit Version ausstatten, so kann man Updates leichter
   durchfuehren.
 - /sys/stddefines.h mit TO und so
 - Stat "Luck"
 - "Wizard"-Sonderkommandos durch Spielen/Lehren vergeben.
 - Zufallsgenerator nach GURPS-Verteilung.
 - Ausweichmethodik im Props zulassen: Daten, die lokal nicht gefunden werden,
     knnen in der Blueprint abgefragt werden. Damit braucht ein Clone nur die
     Daten zu halten, die lokal sind. Neues Flag: ALWAYS_LOCAL, ALWAYS_GLOBAL.
     Nach Erzeugung eines Klones wird per call_out() eine Funktion gestartet,
     die alle wegwerfbaren Daten in dem Props wegwirft.
     Werden alle Props auf einmal gesetzt, wird diese Funktion auch verwendet.
 - Add/Sub in den Props (Ulantris)
 - xxx.yyy.zz-Strukturierung in den Props auf Mappings abbilden. Arrays analog
   (Ulantris). Die Mappings/Arrays werden geschachtelt gespeichert, die
   Funktionen bilden xxx.yyy passend ab.
 - Unique-NPCs mit eigenen Savefiles.
 - Ulantris: Spell-Idee.
 - Newsserver: Extra-Subject-File im internen Format.
 - Keine XP, Playerlevel aus den Skills errechnen?
 - Wichtige NPC-Toetungen mitzaehlen, nur beim ersten Mal XP geben. In der Long
   oder der Fame der Player mitfhren.
 - CmdData im player ueber sefuns zugreifen.
 - Combat: Trefferzonen und -daten (Treff, Wahrscheinlichkeit, zug. Ruestung)
     So ist ein simples Limbs-Orientation mit Rassenunterschieden moeglich.
 - Props: Generisches Add(name, value), Sub(name, value), dass dann auch
     Filterfunktionen bercksichtigt (thanks to Ulantris for this idea).
   Fr das Add/Sub gleich allgemeine Funktion zum Addieren von Daten
   schreiben. Mit dieser Funktion in Get() das temporre Erweitern von
   Daten implementieren (siehe NF: ExtraLong und Freunde).
 - Dynamische Strings per process_string() implementieren (?)
 - Alle Texte dem Spieler per ->message(string str, void|int nowrap))
   mitteilen. Diese Funktion fhrt dann ein process_string() durch und ein
   Linewrap. Wrapperfunktionen ala receive(string type, mixed str, string nowrap)
   knnen dann tell/see/hear etc unterscheiden, und fuer str entweder einen
   string oder ein Array von ({ filter_closure, string })-Tupeln
   akzeptieren (Dies evtl. auch bei message()).
   Hierzu nochmal das TubMud'sche Message-System angucken.
 - docs: Docs in zwei Varianten?: referenz und ausfuehrliche Beschreibung
       : separate Prop-Docs auch mit Beispiel und "redundanten Informationen"
       : Index, auch ueber Konzeptstichwoerter
 - b/base: Per Flags vermerken, ob die expliziten lfuns existieren:
     if (!(mode & PM_TESTED))
     {
       if ("QueryName" exists)
         mode |= PM_QEXISTS;
       if ("SetName" exists)
         mode |= PM_SEXISTS;
       if ("Name" exists)
         mode |= PM_GEXISTS;
       mode |= PM_TESTED;
       store mode;
     }
     if (mode & PM_QEXISTS)
       ->QueryName()...
 - ChangeAttr()/ModAttr() gleich auf Propertybasis anlegen.
 - Site-spezifisches banish. Mehrere Banishebenen.
   Usernamen konnen fuer Sitenamen reserviert werden, um ein Sitebanisch zu umgehen.
 - Dinger bekommenein oder mehrere Flags (Invis, (natural) Frog, (natural)Ghost,
   NotRealThing) anhand dere u.a. ihre Short oder durchlaessigkeit geaendert wird.
 - Extra 'ShortShort()'?
 - Prop 'Elevation'fuer fliegende / erhoeht angebrachte Dinge..
   So koennen auch fliegende Player geschaffen werden, oder erhoehte Ausgaenge
   aus Fallgruben.
 - Anfang und Ende eines command()s muessen im this_player() mitgeteilt
   werden, d.h. dass auch runtime_error() einen entsprechenden Aufruf
   erhalten muss. Der Code muss auch vorsehen, dass nach einer command()
   diverse registrierte Objekte/closures (so noch existent) aufgerufen
   werden.
   Damit lassen dann z.B. transiente Objekte realisieren: bei einem id()
   abgespaltete Unitteilobjekte koennen jetzt versuchen, sich wieder zu
   verschmelzen; ins Leben gerufene Detailobjekte lassen sich wieder
   zerstoeren.
   Andere Anwendung: wenn ein Raum alles fallengelassene wegteleportiert,
   geschieht das nicht im notify_enter() direkt, sondern in einer extra-Funktion
   die von notify_enter() im player als 'postprocess' registriert wird.
 - Lokalisation von sachen ("present()") laesst sich am besten ueber einen
   Event realisieren, dr mit dem preparsten Text und einer Suchart (look, fondle,
   remove, insert) losgeschickt wird. Bei Anzahlen/Ordinals gehoert noch
   ein Predicate dazu, dass den Dingern sagt, ob sie ueberhaupt beachtet
   werden sollen.
 - Events sind auch ganz praktisch. Z.B look:
   'look at a, b and c' laesst einen Event ({ EVENT_LOOK, a, b, c })
   los, in den die Objekte a, b, c ihren Daten eintragen, die dann dem
   Living angezeigt werden. da der look 'non-silent' ist, koennen alle
   Objekte auch gleich 'Foo looks at a, b and you' und dergleichen machen.
 - Neues Move-flag 'M_EXTRA_NOTIFY', so dass man mehrere Objekte durch
   lfuns moven kann, das Zielobjekt sie aber erst dann als
   'angekommen' akzeptiert, wenn die extra-Notify-Funktion aufgerufen
   wird. So koennen die normalen Notify-Funktionen mit dem Gewicht
   hantieren, extra-Raumsachen wie destruct koennen dann spaeter passieren.
 - Unsichtbarkeit muss ein extra Propertyflag sein, fuer den Fall,
   dass Short() extra Magie treiben muss.
 - Arbitration der globalen Variablen von Tub abgucken.
 - Array von ExtraLong/ExtraShorts verwalten - macht einiges einfacher.
 - Virtuelle Objekte durch bei Bedarf erzeugte Objekte simulieren, die
   nach einiger Zeit wieder destructed werden.
 - Virtuelle Objekte durch mappings realisieren. Properties und Funktionsaufrufe
   werden entweder aus dem Mapping befriedigt, oder der 'Wert' is eine closure
   die aufgerufen wird. Zusaetzlich besitzt das Mapping einen mandatorischen
   Eintrag 'Controlling Objekt' auf den FUnktionsaufrufe (also auch Propkrams)
   die im Mapping nicht drinstehen, umgelenkt werden:
     object->v_handle(mapping v_item, funname, args...)
   Dafuer die sefun call() schreiben.
 - Move nicht mehr in den Objekte lokal tun, sondern durch externe
   efun, die dann auch gleich mehrere Objekte auf einmal bewegen kann.
     obj[...]->qMove(dest, how, extra)
     from->qLeave(obj[], dest, how, extra)
     dest->qEnter(obj[], from, how, extra)
     obj[...]->doMove(dest, how, extra) (???)
     from->didLeave(obj[], dest, how, extra)
     dest->didEnter(obj[], from, how, extra)
     obj[...]->didMove(dest, how, extra)
   Natuerlich mit entsprechenden Filtern.
 - Hull-Objekte brauchen ein Flag 'NotRealHull', Stuehle z.B.
   Alternativ eine Transparenz von 1000 dafuer verwenden, oder P_INVIS
   auswerten.
 - Echte und Virtual Objects zulassen. Virtual Objects sind einfach
   nur das Property-Mapping (z.B. fuer Details und so). Die
   Suchroutine search() braucht dafuer dann auch flags
   SEARCH_NO_VIRTUAL und so. Alle Lokationsroutinen sollten mit
   virtual objects zurechtkommen.
 - Der Schaden eines Typs wird durch drei Werte reprsentiert:
     DAMAGE:   Basis-Schadenswert
     PHYS_REL: Wechselwirkung mit physikalischen Gegenstaenden, in %
     PHK_REL:  Wechselwirkung mit lebenden Gegenstaenden, in %
   Die Schutzwirkung einer Ruestung wird berechnet zu
     <absorbierte HP> = <Schutzwirkung>*(PHYS_REL || 1)
   Die absorbierten HP werden von DAMAGE abgezogen, yielding ModDAMAGE.
   Der real angerichtete Schaden bei Dingen ist:
     <SchadensHP> = ModDAMAGE * (PHYS_REL || 1)
   und bei Lebewesen:
     <SchadensHP> = ModDAMAGE * (PHK_REL || PHYS_REL || 1)
   Der bei Ruestung/Waffe angerichtete Degradationschaden wird durch die
   absorbierten HP bestimmt.
   Eine normale Waffe haette eine Schadensbestimmung von DAMAGE 20, ein
   panzerbrechendes Geschoss ({ DAMAGE 20, PHYS_REL 50 }), und ein
   Roentgengeraet ({ DAMAGE 100, PHYS_REL 0, PHK_REL 100 }).
 - Damage-Types als Integer+BitFlags interpretieren:
     Damage-Typen:
       DT_GEN   : fuer Default-Ruestungsabwehr.
       DT_PHYS  : physische Schadenswirkung
       DT_MAGIC : magische Schadenswirkung
       DT_MENTAL: mentale Schadenswirkung
     Damage-Ursachen:
       DC_PHYS  : physikalisch verursachter Schaden
       DC_MAGIC : magisch verursachter Schaden
       DC_MENTAL: mental verursachter Schaden (PSI)
     Damaga-Modifier:
       DF_LOCAL: Schadenswirkung auf Trefferstelle begrenzt (ein nicht-lokaler
         Schuss auf einen Container wuerde alle enthaltenen Dinge schaedigen).
 - Abgefragte/Gesetzte Properties grundsaetzlich filtern. Filter anmelden.
     Filter(string name, void|closure filter, void|int which_functions)
   <which_function> gibt an, welche der vier Funktionen (Set, SetHook, Get, Query)
   gefiltert werden soll, default ist nur Get(), ein spezieller Wert dient
   zum entfernen des Filters.
   Ist <filter> = 0, werden alle Filter fuer diese Prop entfernt.
 - Generische Propfunktionen im kernel einbauen a la
     Get (object|mapping obj, string name, ...)
   die so auf diese Weise automatisch mit virtuellen Objekten (simple Mappings mit
   den Propertywerten zurechkommen).
 - Long()-Beschreibungen vor Ausgabe automatisch wordwrappen wenn sie nicht auf einen
   "\n" enden.
 - Prop 'Is', die Schluesselwoerter zur Klassifikation des Objektes enthaelt, wie
   'thing', 'room', 'container', 'key', aber auch Attribute wie 'burnable' etc.
   Diese sind mit id() und gezielt ueber is() abtestbar.
 - id() und alle abhaengigen Funktionen werden so umdefiniert, dass sie einen Integer,
   das gesuchte Objekt oder als virtuelles Objekt das Propertymapping zurueckgeben.
 - Dir-Aufteilung aendern: komplett-Inheritable Objekte nach /std, die
   Basismodule nach /b, so dass z.B. /std/thing /b/base, /b/physical und
   /b/damage inherited. Neues dir /doc/design
   Moegliche Basismodule:
     /b/base    : Propertyhandling.
     /b/physical: Beschreibung, intern und extern; Licht- und Gewichtspropagation.
     /b/combat  : Combat, sowohl fuer Dinge als auch Container.
     /b/moving  : Bewegung eines Dinges.
     /b/details : Details eines Dinges/Raumes.
       Jedes Detail wird nach seinem Namen indiziert, bekommt aber noch eine Praedikats-
       funktion zugeteilt, die ebenfalls zustimmen muss. So koennen auf simple Weise
       Restriktionen auf die gematchten Texte (sword->AddDetail("runes", PRED("on"), "text"))
       oder auf die Lokation des Betrachters anwenden. Textpredikate wie "<detail> on <id>"
       muessen auf Anfrage auch einen Teilmatch auf ("<detail>") zulassen:
         > look at runes
         (on sword): They explode. You die.
     /b/content : Move-Notify-Funktionen fuer Container-Dinge (Raeume, Bags); Locate(),
                  Msg-Announcement, Licht- und Gewichtpropagation, und so.
                  Hier findet sich auch Locate(), und die Verwaltung der Prepositionen:
                    LocationPrep: in, on
                    LeavePrep: from, out, out of, outof
                    EnterPrep: in, into, on, onto
                  Oder lieber ueber einen Parser handlen?
     /b/items   : Ausruestung eines Dinges.
     /b/exits   : Ausgaenge aus einem Raum/in einen Raum. Auch hier Praedikatfunktionen
       zulassen. Relation zu benachbarten Raeumen (ob nun exit oder nicht)?
       Tuerenhandling (moeglichst ueber ein lfun-Protokoll zwischen Tuer und Raum).
       Beschreibungen ueber Funktionen in Lang- und Kurzform greifbar
       machen: Langform fuer evtl. DynString-Longs, Kurzform fuer Brief/Obvious-mode.
       Jedem Exit auch eine Beschreibungsfunktion mitgebbar machen fuer die Langform.
         room->DescribeExit("up") koennte so bei einer offenen Falltuer "A trapdoor leads
         up" liefern, dagegen bei derselben Trapdoor nur "" wenn sie verschlossen
         und unsichtbar ist.
     /b/npc/moving: Bewegung eines Lebewesens.
   Frage: Outdoor/Indoor-Raeume? Units? Generell Pluralia?
 - Generischer Parser, zumindest Line-Tokenizer. U.a. dazu Eingaben per modify_command()
   abfangen.
 - Combat: AP und LP unterscheiden. Bei Sachen ist AP meist nicht vorhanden,
   LP geben den Materialschaden an. Bei Livings/Weapons/Armours gibt AP die
   Faehigkeit zu Aktionen an. Livings ohne AP koennen nicht mehr kaempfen,
   Armours/Weapons haben ohne AP nur noch wenig Wirkung (Verlust des statischen
   Aufbaus durch Verbeulung).
   Jeder Move eines Livings kostet einen AP (plus Gelaendemalus), die AP werden
   nach und nach aus dem Food/Wasservorrat aufgefuellt).
   Anstelle der APs koenne LPs verwendet werden.
 - Level&Experience nur als interne Berechnungshilfe nehmen, nach aussen nur durch
   Titel kennzeichnen.
 - Move-Methoden als Bitflags interpretieren (z.B. M_GO|M_NOCHECKS)
 - Im room-Locate() evtl auche "foo in bar"-Suche einbauen.
   Locate koennte ruhig auch 'all fooes' verstehen, aber dazu
   muesste man nach plural-ids parsen koennen (lfun plural_id()).
 - Den ExaLong()-Default  "You see nothing special" in Micro einbauen.
 - Fuer Sachen wie 'You can 'buy' a drink' als extra 'help room' resp. `help <object>'
   so einbauen, damit es nicht die Long-Description banalisiert.
 - Von Tub (u.a.): events, skills, jobs, fakeitems, exits, place, simulefun/describe
   lib/language...,
 - player->RealName() muss mit dem echten Namen nix zu tun haben.
   Setzt man hier einen ID-Code an (oder besser: dne Namen ohne Interpunktion wie 'oder -),
   kann man beliebige Namen zulassen, muss aber an allen moeglichen Stellen
   bersetzungen zulassen.
 - Long/Short sollten von vorneherein einen Mapping-
   Mechanismus zulassen.
   desc  := string
         := closure
         := '({' { [int|closure] string|closure } '})'

   Wenn gegeben, gibt der int (bzw. die Praedikatsclosure) an, unter welchen
   Umstaenden der nachfolgende Text mit bernommen wird, z.B. PRED_BLIND,
   PRED_NONBLIND, PRED_VISION, PRED_IVISION. PRED_HEAR, PRED_ALWAYS, PRED_OBVIOUS
   Die Props Long/Short/... stellen die Basisinformationen fr die einzelnen
   fnf Sinne (also auch P_TOUCH einfhren), die dann durch Long()/Short()/...
   passend abgewandelt werden knnen. Die Long-Prop hat dabei das Muster fr eine
   vollstaendige Beschreibung incl. Hear-Smell aber ohne Obvious exits und
   Inhalt zu enthalten.
   Describe(int 0=short, 1=long, 2=exalong) baut aus diesen Basisinformationen
   dann die Gesamtbeschreibung zusammen, haengt das Ergebnis von ->ExtraLong,
   ->Exits, ->Doors und ->Content an, und fhrt einen Zeilenumbruch durch.
   Extraflags fr das Argument: NO_HEAR, NO_TOUCH, NO_SMELL schalten die
   Interpretation der entsprechenden Eintraege im P_LONG aus, NO_EXTRA,
   NO_OBVIOUS, NO_CONTENT haengt betreffende Daten nicht an.  Enthaelt
   P_LONG keine Daten von P_TOUCH et al., werden sie vor ->ExtraLong automatisch
   eingefuegt. JUST_VISUAL wird als | aller dieser Flags definiert.
   Alternativ fuer die Props einfach nur Strings/Closures zulassen, und in
   Describe() die Sachen aneinanderhaengen und umbrechen.
 - secure/simul_efun als Standardbibliothek ausnutzen, die y.B. die Filterroutine
   fuer die Beschreibung enthaelt. Durchaus in mehrere Inherits aufteilen.
 - Room/items: Initial- und Refresh-Props unterscheiden.
 - Skills auch von der Rasse abhaengig machen?
 - std/thing: Damage, DamageCap(acity), (Damage)Resistance
              Combat schreiben.
   Resistance != Defense !!
 - std/hull umfasst exits, inner description und evtl. doors
   std/room umfasst die Room-Extras (Details, Items, Weather) und evtl. doors
 - Rekursive save/restore fuer /std/hull, rekursives AutoObject fuer /std/container
   Oder beides in ein /std/hull/object.
 - Movemessages (enters from south/leaves..) werden vom Living gehandhabt.
   Frueher waren sie in std/room/restrictions
 - Docs:
     concepts: perception, properties, light, messages, moving
     secure  : config
     mud     ; files (incl. standard-logfiles), objects (incl. Systemobjekte)
               config, design
 - move() sollte auch Strings mit Fehlermeldungen zurueckliefern koennen?
 - MG-Ebenen:
  Welche Ebenen momentan benutzt werden kann man durch -!! erfahren.
  Moechte man einer speziellen Ebene lauschen, geschieht das durch
  Benutzen des Kommandos -+<Ebene>, wobei <Ebene> der Buchstabe ist,
  welcher bei der Auflistung der Ebenen in Eckigen [] Klammern ange-
  zeigt wird. Zum Verlassen einer Ebene genuegt es, das "+" in ein
  Minus "-" umzuwandeln: --<Ebene>
  Mittels des Kommandos -! werden alle Ebenen angezeigt, denen man
  lauscht, und -?<Ebene> ist ein Kommando, um alle auf der Ebene zu-
  hoerenden Spieler aufzulisten.

  Zur Artikulation auf den Ebenen sind die Kommandos:
  -<Ebene>'<Text>  -- Hiermit sagt man etwas auf einer Ebene.
  -<Ebene> <Text>  -- dito
  -<Ebene>:<Text>  -- Dieses Kommando benutzt man um etwas
                      auf der Ebene auszudruecken (emote).
  -<Ebene>;<Text>  -- dito, nur der Name wird im Genitiv vor
                      den Text gestellt.
  Bei den letzten vier Befehlen kann die Ebene <Ebene> auch wegge-
  lassen werden, wenn eine Standardebene mit dem Befehl -~<Ebene>
  eingestellt wurde.

  Moechte man fuer kurze Zeit alle Ebenen ausstellen, kann man das
  Kommando -% benutzen, welches - nocheinmal angewendet - die Ebenen
  wieder einschaltet.
  Ein besonderes Kommando ist -+!, welches alle vorhandenen Ebenen
  einschaltet.

  -!!
  Es stehen folgende Ebenen zu Verfuegung:
  [B] Beileid........ (20) Beileidsbekundungen jeglicher Art
  [C] Channel........ ( 0) Channel Information
  [G] Grats.......... (20) Gratulationen zu geloesten Abenteuern etc
  [I] Intermud....... ( 2) Intermud Kanal (Englisch)
  [M] Moerder........ (19) Guck mal wer da spricht...
  [O] Intercode...... ( 4) Intercode Kanal, Programmierfragen (Englisch)
  [T] Tod............ (27) Wer stirbt wann?
  [a] Allgemein...... (23) Allgemeine Unterhaltungsebene
  [b] Abenteuer...... (26) Fragen die Abenteuer betreffen
  [h] Seher.......... ( 9) Diskussionsebene fuer Seher
  [k] Kultur......... (15) Kulturelle Themen, Musik, Buecher und Filme
  [l] LPC............ ( 3) Fragen zur Programmierung und LPC
  [m] Magier......... ( 4) Diskussionsebene fuer Magier
  [s] Sport.......... (12) Sport in allen Variationen
  [w] Wissenschaft... (13) Alles was mit Wissenschaft verbunden ist
  > [Moerder:Geist eines Goblins] Unglaublich, wie hat das Gundur geschafft?
  > [Channel:] Registered Snooker on Abenteuer, Wissenschaft, Tod, Kultur,
  [Channel:] Allgemein, Beileid, Moerder, Sport, Grats.
  [Moerder:Geist eines Fore-Kriegers] Jetzt hat mich doch glatt Steini erwischt
  [Moerder:Geist eines Fore-Kriegers] :(
  [Moerder:Geist eines Fore-Kriegers] Steini hat mich ermordet!
  [Moerder:Geist eines Orks] Zephyr? Ich bin dann jetzt weg.
- Jof sagt: Ich parse commandslines generell.
    Ich wandel alle Strings in kleinschrift um, mach doppelte
    Leerzeichen raus usw.
    Was die Objekte dann als Arg sehen, ist schon 'vorgeparsed'.
    Wer die Original-Argumente haben will, muss sie explizit anfordern.
- > e
  This is the room in which the retired archwizards of various muds
  gather, reminiscing nostalgically about how things used to be
  better when they were in charge.
      There is one obvious exit: west
- Extra-Texte wenn man einen Raum betritt oder verlaesst.
 - Ab dem Reboot am 15.02.1995, 11 Uhr, ist der Parser fuer alle Spieler ak-
   tiviert. Er tut folgendes:

   Schritt 1: Doppelte Leerzeichen werden durch einfache ersetzt, der gesamte
              String ab dem 1. Blank (also alles ausser dem Verb) wird
              in lowercase umgewandelt.
   Schritt 2: "im" und "ins" werden durch "in" ersetzt, ",","!" und ":" werdem
              aus dem String entfernt, ebenso die Artikel ("der","die","das",
              "des","dem","den","ein","eine","einer","eines")
   Schritt 3: Strings wie "stecke das 3. schwert in den 7.Beutel" werden
              in "stecke schwert 3 in beutel 7" umgesetzt. Dabei wird
              Zahl. vor das naechste Trennwort gestellt. Trennworte sind der-
              zeit neben dem Zeilenende "in","aus","ueber","auf","unter","mit",
              durch","fuer","von","vom","aufs","ein","weg","zurueck".

   Das Endergebnis wird dann den per AddCmd/add_action aktivierten Funktionen
  als Argument uebergeben. Die Original-Argumente kann man sich mittels
    this_player()->_unparsed_args() abholen, das Ergebnis von Schritt 1 als
    this_player()->_unparsed_args(1), das Ergebnis von Schritt 2 als
    this_player()->_unparsed_args(2).
 - Players ausidlen lassen, evtl. im master realisieren.
Nightmare Mudlib SimulEfun: consolidate()

string consolidate(int, string);

DESCRIPTION
Takes a text string describing a singular thing along with how many
of those things exist and *consolidates* it into one plural
description with a numeric text modifier representing how many
there are.

EXAMPLES
consolidate(5, "a long sword") returns "five long swords"
consolidate(2, "Excalibur") returns "two Excaliburs"
consolidate(100, "a list of players") returns "numerous lists of players"

LOCATION
/secure/SimulEfun/english.c

SEE ALSO
pluralize()

LAST MODIFIED
Nightmare 3.3

 - Es gibt jetzt einen einfachen Weg, rassenabhaenige Details zu definieren:
   Man uebergibt bei AddDetail ein Mapping, dessen keys die Rassen-
   Bezeichnungen (in Kleinbuchstaben) sind, mit einem Zusatzeintrag "0" fuer
   den Defaultwert (der wird bei Rassen genommen, fuer die nix
   eingetragen ist). Beispiel:
   (["mensch":"Du willst gar nicht durch das Fenster schauen",
     "zwerg": "Du kommst nicht ran.",
     "elf":   "Du bist zu gross uns willst Dich nicht buecken.",
     0:       "Magier lesen keine Details!"]));
 -  Wenn beim Schreiben auf ein Verzeichnis festgestellt wird, das der
    betreffende Magier keine Schreibrechte auf ein Verzeichniss hat, wird
    in diesem Verzeichniss nach einem "access_rights.c" gesucht. Wird dies
    nicht gefunden, wird ab hier weiter nach oben gesucht. Sobald ein
    solches Objekt gefunden wird, wird in diesem die Funktion 'access_rights'
    ausgerufen. Sie muss folgendermassen aussehen:
      int access_rights(string magier, string relativer_pfad);
    Dabei ist der Pfad relativ zum Verzeichniss, in dem das access_rights.c
    steht. Beispiel:

    Witz versucht auf /players/jof/obj/bla.c zu schreiben. Zunaechst wird ein
    access_rights.c in /players/jof/obj gesucht. Wenn dieses nicht
    gefunden wird, wird in /players/jof weitergesucht. Angenommen,
    hier steht eines. Dann wird
    "/players/jof/access_rights"->access_rights("witz","obj/bla.c")
    aufgerufen. Gibt dieses eine 1 zurueck, wird der Schreibzugriff
    erlaubt, bei 0 untersagt. Das ganze funktioniert in
    Unterverzeichnissen von "/d","/std","/sys" und  "players".
 - Gesichtspunkt: wenn Spieler zwar alles koennen (Magie + Kaempfen +
   ...), aber durch ihre (SP-)Ressourcen begrenzt werden, kann sich
   evtl. eher Zusammenarbeit entwickeln als wenn eine Faehigkeit die
   Ausuebung anderer beeintraechtigt (Magie vs. Kaempfen vs. ...).
   Grund waere, dass die Koordination der Zusammenarbeit leichter
   geht (anstelle von "ich kann aber nur teleportieren und so").
 - Exits: gefilterte (0 oder 1 Nebenraum) und spezielle (einer aus >=
   2 Nebenraeumen) Exits unterscheiden.
 - In diesem Laden ist jetzt "kaufe ausruestung" moeglich.
   Dabei werden dann Waffen und Ruestungen ausgesucht, die moeglichst gut sind,
   man sich noch leisten kann, noch tragen kann, und, bei Waffen,
   auch zuecken kann.
   Das ganze kostet eine kleine Beratungsgebuehr.
 - P_RESISTANCE_STRENGHTS (Rochus, 29. Aug 1995, 14:01:40):
   Statt P_RESISTANCE/P_VULNERABILITY kann man demnaechst mit
   P_RESISTANCE_STRENGHTS auskommen.
   Dies muss ein Mapping sein, in dem zu jedem Schadenstyp der
   Faktor, mit dem der Schaden multipliziert werden soll, minus 1.0 steht.
   (1.0 wird bei der Berechnung spaeter addiert, damit ein fehlender
   Eintrag immer als 1.0 beruecksichtigt wird)
   Also, anstelle von
     SetProp(P_RESISTANCE,({DT_SLASH,DT_FIRE,DT_FIRE}))
     SetProp(P_VULNERABILITY,({DT_COLD}))
   geht jetzt
     SetProp(P_RESISTANCE_STRENGHTS,
       ([DT_COLD:1.0,
         DT_SLASH:-0.5,
         DT_FIRE:-0.75])
   Insbesondere gehen jetzt auch Faktoren wie 3.0, statt nur 2er-Potenzen
   Wenn P_RESISTANCE/P_VULNERABILITY gesetzt werden wird
   P_RESISTANCE_STRENGHTS uebrigens automatisch mitgesetzt.
   Werte unter -1.0 koennen zu ungewollten Effekten fuehren.

 - Standardfunktion, um Gegenstaende zu verstecken (wie 'search doormat'
   -> golden key appears).

 - A recent idea of mine... how about interpreting domains not only as physical
   regions, but also as 'projects'? Especially for archwizards this would
   be helpful as they could 'hire' enthusiastic wizards for various tasks
   without the need of giving them global write access. Additionally, globally
   used objects/files are in well-defined places and not scattered over the
   physical domains (like the scrolls).
   Also additional services (like the once disputed help department) could be
   implemented without the need for yet another archwizards.
   I can imagine additional directories like
    for the archwizards:
      /d/building  (Transport et al)
      /d/finance   (Moneytools, CitiBank objects)
      /d/magic     (!!!)
      /d/lpc       (Example objects, docs)
      /d/combat    (Tools, docs, standard objects?)
      /d/health    (dito)
      /d/quests    (dito)
      /d/police    (?)
    for non-archwizards:
      /d/help (Docs, Schools and other things)
    Maybe for a simple directory structure, all these could be subsummed under
    /d/nf, e.g. /d/nf/magic.
 - Rubrik 14: entwicklung, Artikel: 56 von 81
   Der NEUE Befehl "unt/schau" (Hate, 23. Jan 1996, 17:29:48):
   Liebe Spieler,

   hier ein Auszug aus der Hilfeseite fuer untersuche
   man untersuche
   ...
           Betrachtet man ein <objekt> im Raum, so wird es als neuer Bezugs-
           punkt fuer weitere Betrachtungen genommen. D.h. man kann als
           naechstes ein Detail an dem Objekt betrachten, ohne eingeben zu
           muessen "unt <detail> an <objekt>", sondern es reicht dann
           "unt <detail>". Wird das Detail an dem eben betrachteten Objekt
   nicht
           gefunden, so wird der Bezugspunkt wieder auf die Umgebung und die
           Objekte im Spieler gesetzt.
   ...

   Ab sofort wird es moeglich sein, an ALLEN Objekten Details zu betrachten.
   Ansonsten funktionert der Befehl weiter so wie bisher.
   Das Prinzip hat sich nur ein wenig geaendert. Man hat jetzt immer einen
   "Bezugspunkt".
   Wenn man in einen Raum hineinkommt, ist das der Raum und das eigene Inventar.
   Betrachtet man dann ein Objekt, welches dort herumliegt, wird der Bezugs-
   punkt auf das Objekt verlagert, so dass man dann an diesem Objekt
   einzelne Details betrachten kann, ohne jedesmal "an <Objekt>" mit in den
   untersuche Befehl einbauen zu muessen.
   Der Bezugspunkt veraendert sich automatisch, wenn ein Detail nicht gefunden
   wird. Ist das Detail im Raum zu finden, wird der Raum der Bezugspunkt,
   wird es nirgends gefunden, bleibt der Bezugspunkt das Objekt.
------------------------------------------------------------------------------
From: chaos@crystal.palace.net (Matthew R. Sheahan)
Subject: Lost Souls notes
Date: 13 Jan 1996 03:38:15 GMT
Organization: Crystal Palace Networking
Message-ID: <4d79f7$f3s@puzzle.palace.net>

following are some notes on a set of development trends at Lost Souls
LPmud (lostsouls.org 3000).  i'm posting them for questions and comments,
and perhaps someone will find them useful.

long ago, we began discouraging the old clone-and-configure approach to
item and monster setup in favor of making a separate file in the area's
directory hierarchy for each.  we found this improved maintainability of
areas, wizard accountability, and world cohesion, even if it cost us
some memory.

later, the elementary modules for game objects were revamped so that,
rather than each using a set of global variables for any data it needed,
each used a single mapping in which all its data was stored.  this had
the benefits of zero overhead for unused variables, the ability to
distinguish between a "set zero" and an "unset zero" for defaults, and
so on.  this required the establishment of a function which would be
used to assure that mappings were initialized, since we couldn't rely
on old code to call ::create() appropriately.

when we implemented our item saving mechanics, we took advantage of the
mapping-based structures in place to create a system that can do limited
saving of object pointers and closures.  the initialization function was
expanded to register the mappings with a save module that could examine
and convert their contents at save-time.

most recently, taking advantage of this centralization of data tracking,
i have implemented a system which attempts to distribute the data of
clone classes across the entire class, meaning that if a piece of armour
in someone's area and its twenty clones had identical armour setup data,
there would only be _one_ mapping distributed across all instantiations
of the object.  it works like this.  when an object is first created and
mappings are registered with the save module, the save module does a
short call_out to an analysis function (so that the object will have
plenty of time to finish configuring itself).  if the object is the base
for its class, it registers its mappings with a daemon, indexed by the
filename.  if it is a clone, it queries this daemon for any mappings it
should replace with distributed versions.  the daemon compares the clone's
mappings with those of the base for its class (using an array/mapping
content analysis function, plain equivalency testing obviously won't do
it) and tells the object to replace any that are functionally identical.

one thing that was required was that all functions that modify the
modules' mappings must notify the save module that the mapping is
about to be changed, so that the save module can localize it with a
copy().  this isn't that bad.  indeed, one notes that the
level of resolution involved, module-level rather than variable-level
or object-level, seems to be about optimal; variable-level would have
prohibitive overhead and object-level would be all-or-nothing, so
that any benefit would be lost as soon as any change were made to the
object after configuration, or if anything in its configuration were
not constant.

obviously, this type of thing requires excellent garbage collection, as
many pointers are being initialized, compared, and then discarded.  the
garbage collection of the Amylaar driver appears to be adequate to this.

as might be expected, the implementation of this code has drastically
reduced our memory consumption, which was beginning to suffer from our
penchant for a feature-laden mudlib.  daemon statistics gathering shows
that about 75% of the data mappings of cloned objects on the MUD are
being replaced with distributed versions just after create-time.  this
is an enormous savings.  admins may wish to consider implementing some
system resembling this at their locations.

                                                                Chaos@LostSouls
                                                                chiaroscuro

------------------------------------------------------------------------------
From: abigail@melgor.ny.fnx.com (Abigail)
Subject: Re: NM IV and add_actions

Wouldn't it much much better to have _one_ read command, so players
can _always_ type 'read foo', and never get What? as response?
Then you only need to make the code which tests if it is light enough
once, in stead to have to repeat it every time you make a new object
which can be read. (Image, a player carrying 17 scrolls, and types
'read scroll', then the first 12 do a notify_fail "It is too dark
to read", and read the 13th, because it was coded by someone who
forgot to check for darkness...)

++ objects they
++ can 'frobnitz' without having to have an arch code a new damn verb...

You only need a few variations and a proper interface.

void cmd_read (string what) {
   if (!arg) {
        write ("What do you want to read?\n");
        return;
    }

    if (this_player () -> test_dark ()) {
        write ("It is too dark for you to read.\n");
        return;
    }

    if (this_player () -> query_ghost ()) {
        write ("You are dead! You cannot read.\n");
        return;
    }

    if (sscanf (arg, "the %s", tmp) ||
        sscanf (arg, "a %s", tmp)   ||
        sscanf (arg, "an %s", tmp) {arg = tmp;}

    obj = present (arg, this_player ());
    if (!obj) {obj = present (arg, environment (this_player ()));}
    if (!obj) {
        if (environment (this_player ()) -> id (arg) {
            obj = environment (this_player ());
        }
    }

    if (!obj) {
        write ("There is no " + arg + " here.\n");
        return;
    }

    if (obj == this_player ()) {
        write ("You cannot read yourself.\n");
        return;
    }

    if (obj -> handle_action ("read", arg)) {
        /* Let object read take over */
        return;
    }

    /* Default action */
    write ("There is nothing to read on the " + arg + ".\n");
    return;
}


Once you have this, all you need to do is code the actions which would
happen if the object is read. No need for wizards to do parsing or
testing (and forget some). No rude replies like 'What?' or 'read what?'
And no registering of actions when entering rooms or picking something up.

Abigail

------------------------------------------------------------------------------

