/////////////////////////////////////////////////////
// Map-Handling fuer kleinere Gebiete. (P-Map)
/////////////////////////////////////////////////////
// Soll Aufgrund groesstmoeglicher Flexibilitaet
// die Luecke zwischen der Standart-Map und dem
// MMPS fuellen. Ist auch auf Mudlibs lauffaehig,
// die ueber keinerlei Map verfuegen.
/////////////////////////////////////////////////////
// 181196 [Police] fuer Silicondream entwickelt (Wald)
// 060198 [Police] komplett ueberarbeitet.
// 220299 [Police] fuer Anno komplett ueberarbeitet
// (== neu geschrieben)
/////////////////////////////////////////////////////
*---* *---*
*---* DOKUMENTATION der 'Police-Map' *---*
*---* *---*
Die P-Map
[1] Bestandteile
[2] Zusammenspiel
[3] Funktionsweise
[4] Wie muss die Karte aussehen ?
[5] Wie ist das describe.c aufgebaut ?
[6] Was muss ich im virtual_compiler.c aendern ?
Features fuer Fortgeschrittene.
[7] Was kann ich denn noch so im describe.c anstellen ?
[8] Und wie sehe ich nach ob ich in der Naehe zB. eines Tores bin ?
[9] Zufaellige Textpassagen mit random()
[10] Zufaellige Textpassagen mit der neuen Funktion seed()
[11] Wie unterscheide ich denn das Nord-Tor vom Sued-Tor ?
[12] Wo setze ich Ausgaenge die sich nicht auf der Karte darstellen lassen ?
[13] Wie schliesse ich meine P-Map an den Rest des Muds an ?
[14] Kann ich auch andere Raeume als /i/room.c verwenden ?
[15] Wie kann ich Items und Npc definieren ?
[16] P-MAP und Closures
[17] Was sind denn nun die Extras beim map_room.c ?
Anmerkungen
/* ------------------------------------------------------------------ */
[1] Die Map besteht aus drei Files:
KARTE.TXT - In diesem File liegt die ASCII-Karte des Gebietes.
DESCRIBE.C - Hier stehen die Beschreibungen fuer die
einzelnen Raumtypen.
VIRTUAL_COMPILER.C - Uebersetzt die Karte und generiert automatisch
die angeforderten Raeume mit Hilfe von describe.c
DER ANWENDER SOLLTE HIER, AUSSER DEN
GEKENNZEICHNETEN BEREICHEN, NICHTS VERAENDERN !!!
(Ein weiteres File sollte nicht vergessen werden: MAP_ROOM.C
Er kann als Grundlage fuer die Raeume definiert werden (siehe [6]).
Seine Verwendung ist nicht notwendig, doch enthaelt er
ein paar kleine nuetzliche Extras. (siehe [15] und [17]) )
[2] Um zu verstehen wie das alles zusammenspielt, sollte man sich am besten
eine der bereits laufenden P-Maps ansehen.
(zB. im Augenblick /p/police/anno/map/london/...)
[3] FUNKTIONSWEISE: Beim Laden des Virtual_compilers wird karte.txt
eingelesen und in ein leicht zu verarbeitendes internes Format umgewandelt.
Wird nun ein Raum angefordert, so sieht der Virtual_compiler mit Hilfe der
Koordinaten auf seiner Karte nach, und erhaelt so das RAUMSYMBOL und die
AUSGAENGE. Die Ausgaenge werden sofort gesetzt. Das Raumymbol wird an
describe.c uebergeben. Dort wird der Raum weiterbearbeitet (Raumbeschreibung
und V_Items werden gesetzt, eventuell zusaetzliche Ausgaenge usw. Das bleibt
ganz der Phantasie des Anwenders ueberlassen).
Nun ist der Raum fertig und steht zur Verfuegung, als waere er explizit auf
der Festplatte vorhanden. Der Spieler bemerkt deshalb keinen Unterschied.
[4] Wie muss die Karte aussehen ?
Eine Karte besteht aus drei Arten von Symbolen:
- Leerzeichen ' ' -> keine Bedeutung
- Verbindungen '-' '|' '/' '\' 'X' -> Verbinden die Raeume
- Buchstaben, Zahlen, usw. -> Stehen fuer Raeume (RAUMSYMBOL)
WICHTIG: Es ist darauf zu achten dass Raeume immer an ungeraden Positionen
stehen, Verbindungen an geraden! (hoert sich komplizierter an als
es ist, guckt einfach mal auf eine vorhandene Karte)
Nach der eigentlichen Karte koennen nach einem '{{' beliebige Kommentare
angehaengt werden.
[5] Wie ist das describe.c aufgebaut ?
Im describe.c wird die Funktion
void describe(object ob,string sym,int xpos,int ypos)
aufgerufen.
ob ist ein Zeiger auf den zu bearbeitenden Raum,
sym ist das Symbol des Raumes auf der Karte.
xpos und ypos sind die Koordinaten (werden kaum benoetigt)
Den Inhalt dieser Funktion muss der Anwender selbst schreiben.
Anhand der zur Verfuegung stehenden Daten sollte der Raum beschrieben werden.
Beispiel:
if (sym=="S") /* --- STRASSEN --- */
{
ob->set_short("In London auf der Strasse");
ob->set_long ("Du stehst auf einer der zahlreichen Londoner Strassen.");
}
Erlaeuterung des Beispiels:
Befindet sich in einem Raum, der auf der Karte das Symbol 'S' hat,
bekommt er die obenstehende short und long verpasst.
Da 'ob' als Zeiger auf den Raum vorhanden ist, koennen dort beliebige
Funktionen aufgerufen werden, also auch V_Items gesetzt werden!
[6] Was muss ich im virtual_compiler.c aendern ?
Die #defines
PATH (wo stehen meine Files),
STD_ROOM (welches File soll standartmaessig als Raum verwendet werden),
PRAEFIX (Teil das Raumnamens vor den Koordinaten)
duerfen(STD_ROOM) / sollten(PRAEFIX) / muessen(PATH) angepasst werden.
SONST BITTE NICHTS AENDERN, DAFUER IST DESCRIBE.C DA.
//////////////////////////////////////////////////////////////////////////
// Features fuer Fortgeschrittene. //
//////////////////////////////////////////////////////////////////////////
[7] Was kann ich denn noch so im describe.c anstellen ?
Zum Beispiel Strassen verfolgen und Anzeigen, was in Richtung xxx liegt.
Wie mache ich das ?
if (sym=="S") /* --- STRASSEN --- */
{
ob->set_long ("Die Strasse fuehrt weiter nach "+liste(TYP(sym))+".");
}
TYP("S") liefert ein Array aller Ausgaenge,
die auf einen Raum vom Typ 'S' zeigen.
(was in unserem Beispiel 'Strasse' bedeutet)
(zB: ({"Westen","Norden"}) )
liste(TYP("S")) macht daraus einen schoen formatierten String.
(zB: "Westen und Norden")
[8] Und wie sehe ich nach ob ich in der Naehe zB. eines Tores bin ?
if (sym=="S") /* --- STRASSEN --- */
{
ob->set_long ("..."+
(TYP("T")?"Im "+liste(TYP("T"))+" ist ein Tor.":"")+
"...");
}
Wenn TYP("T") (=es gibt mindestens einen Ausgang auf das Symbol 'T')
Dann "Im "+liste(TYP("T"))+" ist ein Tor." (siehe oben)
Sonst "" (nichts ausgeben)
[9] Ausserdem kann man mittels random() Textpassagen zufallsbestimmt ausgeben.
string *arr = ({"einen Vogel","einen Hamster","eine Ratte"});
ob->set_long (".."+
"Du siehst "+arr[random(sizeof(arr))]+
"...");
(Der Befehl arr[random(sizeof(arr))] sorgt dafuer, dass hier ein
zufaelliges Element des Arrays ausgegeben wird)
[10] Mit der neuen Funktion seed(int xpos, int ypos) kann man genauso wie mit
random() Zufallszahlen erzeugen und dementsprechend Text ausgeben. Jedoch wird
man bei seed() bei den gleichen Koordinaten immer die gleiche Zufallszahl
erhalten. So kann man zB. wandernde Laternen verhindern. Fuer den Coder sind
die Positionen der Laternen dann zufaellig, fuer den Spieler erscheinen sie
jedoch fest, da in dem ihm bekannten Raum _immer_ eine Laterne steht.
(Bei random() steht mal eine da, nach dem naechsten Laden des Raumes
jedoch uU. nicht mehr.)
[11] Wie unterscheide ich denn das Nord-Tor vom Sued-Tor ?
Am einfachsten in dem man xpos/ypos mit auswertet.
[12] Wo setze ich Ausgaenge die sich nicht auf der Karte darstellen lassen ?
Da gibt es verschiedene Moeglichkeiten. Die beiden einfachsten sind:
- Den Ausgang nach Symbol setzen. (evtl. eigenes Symbol machen)
(zB. koennte es Strassenraeume mit ('S') und ohne ('s') Gullideckel geben.)
- eine IF-Abfrage nach der Position einzubauen und dort einen Ausgang zu setzen
siehe auch [14] fuer andere Moeglichkeiten.
[13] Wie schliesse ich meine P-Map an den Rest des Muds an ?
Siehe [12] und [14]
[14] Kann ich auch andere Raeume als /i/room.c verwenden ?
Aber natuerlich. Dazu sind verschiedene Moeglichkeiten vorgesehen.
Es gibt drei Arten den Raum auf der P-Map zu beschreiben:
(0) Allgemein: man kann das #define STD_ROOM im Virtual_compiler aendern,
damit ein spezielles, eigenes Raumfile als Grundlage verwendet
wird. Dies ermoeglicht es zum Beispiel, in jedem Raum eine
Add_action zur Verfuegung zustellen, um die Karte mit der
aktuellen Position auszugeben (siehe /p/police/anno/map/london)
Viel haeufiger ist es erforderlich, einzelne Raeume gezielt zu verwenden,
vor allem wenn NPC, Laeden o.ae. verwendet werden.
(1) Explizit: im Verzeichnis liegt ein ensprechendes File (london_3_4.c)
(Hier muss man allerdings beachten, dass im File die
Ausgaenge von Hand gesetzt werden muessen)
(2) Implizit: im Verzeichnis liegt fuer das entsprechende Symbol
(zB. "B" fuer Brunnen) ein File (desc_B.c), das anstatt dem
Standartfile verwendet wird.
[220299 - NOCH NICHT IMPLEMENTIERT]
(evtl. wird man spaeter auch mal im describe.c den urspruenglich
geclonten Standartfile 'fallenlassen' koennen um einen eigenen,
selbstgeclonten Raum zurueckzugeben. Dies ist jedoch nicht
besonders sauber und wird deshalb vorerst nicht unterstuetzt.)
Der Vollstaendigkeit halber noch einmal die Standartmethode:
(3) Virtuell: Die Beschreibung und die V-Items werden je nach Symbol
im File describe.c definiert.
[15] Wie kann ich Items und Npc definieren ?
Um dies zu ermoeglichen, wurde die Funktion add_to_reset(string filename)
im map_room.c eingefuehrt.
Dazu muss er natuerlich auch verwendet werden (STD_ROOM).
Wichtig: - Ein Clonen von /obj/monster mit nachtraeglicher Anpassung
ist nicht moeglich.
- Da man es dem File nicht ansehen kann, ob es zum Laden oder
zum Clonen vorgesene ist, wird es pauschal _immer_ gecloned.
if (sym=="K") /* --- KANALISATION --- */
{
ob->set_long ("...");
ob->add_to_reset("/p/duselbst/ratte");
}
[16] Zu guter letzt noch eine Ergaenzung:
Wer moechte kann auch mittels Closure ereignisgesteuerte, variable
Beschreibungen erzeugen.
"long": lambda(({}),({#'+,({#'Name,({#'this_player})}),"\n"}))
[17] Was sind denn nun die Extras beim map_room.c ?
Man kann Items/Npc einbringen (siehe [15]), sich eine Karte des Gebietes
ausgeben lassen (Die eigene Position ist markiert) und sich die Ausgaenge
des Raumes graphisch darstellen lassen. Am besten schaut man sich mal den
Source von map_room.c an. Das File kann gefahrlos veraendert werden.
-------------------------------------------------------------------------
ANMERKUNGEN:
Der Connector 'X' wurde auf Wunsch eingefuegt, aber verwendet ihn bitte
nur wenn notwendig, denn er verwirrt dem Spieler mehr als er nuetzt.
---
Vielen ist die Syntax ( A ? B : C ) noch ungewohnt.
Sie bedeutet einfach: wenn A dann B ansonsten C
Der Vorteil dieser Schreibweise liegt darin, dass man sie direkt in einen
String legen kann.
"Er grinst"+(wie?wie:"")+" und geht."
Ergibt, wenn wie==" breit" "Er grinst breit und geht."
Ergibt, wenn wie==0 "Er grinst und geht."
---
In manchen Mudlibs kann es zu Problemen mit den Rechten fuer rename_object()
kommen. In diesem Fall sind fuer STD_ROOM andere Einstellungen
als "/obj/room" nicht moeglich. (Sofern die Admins nicht die Rechte anpassen)