blob: 3254c2ba9c7b342014ab5f027e962acab42445dd [file] [log] [blame]
#include "../haus.h"
inherit "/p/service/wargon/sm/statemachine";
#include "/p/service/wargon/sm/statemachine.h"
#include <properties.h>
#define STATE_IDLE 0
#define STATE_HOUSE 1
#define STATE_ROOM 2
#define STATE_CHEST 3
#define STATE_DETAIL 4
#define STATE_RDETAIL 5
#define STATE_COMMAND 6
#define STATE_FINALIZE 7
#define STATE_EXITS 8
#define SIG_INITIALIZE 0
#define SIG_HOUSE 1
#define SIG_HOUSE_DONE 2
#define SIG_ROOM 3
#define SIG_DO_CHEST 4
#define SIG_DO_DETAIL 5
#define SIG_DETAIL_DONE 6
#define SIG_RDETAIL_DONE 7
#define SIG_COMMAND_DONE 8
#define SIG_DO_EXITS 9
#define SIG_ROOM_DONE 10
private nosave string file;
private nosave int final;
private nosave object raum;
private nosave int nr;
private nosave object hausmeister;
private nosave mixed hmargs;
string dump(object env, int final, mixed args);
private string special(string str);
private void removeOutputFile();
private void dumpHouse();
private void dumpRoomHeader();
private void dumpChest();
private void dumpDetails();
private void dumpReadDetails();
private void dumpCommands();
private void doFinalize();
private void dumpExits();
private void dumpRoomTrailer();
private void doReturn();
private void sProp(string file, string pName, string pStr);
static void mProp(string file, string pName, mixed map_ldfied, int pos, int signal);
static void cProp(string file, string pName, mixed cmd, int pos, int signal);
private void prettyString(string file, string *str, int indent);
private void prettyArray(string file, string *arr, int sep);
private void headerRoom();
private void trailerRoom();
private void headerHouse();
private void trailerHouse();
create()
{
::create();
seteuid(getuid());
AddState(STATE_IDLE, 0, 0);
AddState(STATE_HOUSE, #'dumpHouse, 0);
AddState(STATE_ROOM, #'dumpRoomHeader, 0);
AddState(STATE_CHEST, #'dumpChest, 0);
AddState(STATE_DETAIL, #'dumpDetails, 0);
AddState(STATE_RDETAIL, #'dumpReadDetails, 0);
AddState(STATE_COMMAND, #'dumpCommands, 0);
AddState(STATE_FINALIZE, #'doFinalize, 0);
AddState(STATE_EXITS, #'dumpExits, 0);
AddTransition(SM_INVALID, SIG_INITIALIZE, STATE_IDLE, 0);
// Zustandsuebergaenge zum Schreiben des Hauses
AddTransition(STATE_IDLE, SIG_HOUSE, STATE_HOUSE, #'removeOutputFile);
AddTransition(STATE_HOUSE, SIG_HOUSE_DONE, STATE_IDLE, #'doReturn);
// Zustandsuebergaenge zum Schreiben eines Raums
AddTransition(STATE_IDLE, SIG_ROOM, STATE_ROOM, #'removeOutputFile);
AddTransition(STATE_ROOM, SIG_DO_CHEST, STATE_CHEST);
AddTransition(STATE_ROOM, SIG_DO_DETAIL, STATE_DETAIL);
AddTransition(STATE_CHEST, SIG_DO_DETAIL, STATE_DETAIL);
AddTransition(STATE_DETAIL, SIG_DETAIL_DONE, STATE_RDETAIL);
AddTransition(STATE_RDETAIL, SIG_RDETAIL_DONE, STATE_COMMAND);
AddTransition(STATE_COMMAND, SIG_COMMAND_DONE, STATE_FINALIZE);
AddTransition(STATE_FINALIZE, SIG_DO_EXITS, STATE_EXITS);
AddTransition(STATE_FINALIZE, SIG_ROOM_DONE, STATE_IDLE, #'doReturn);
AddTransition(STATE_EXITS, SIG_ROOM_DONE, STATE_IDLE, #'dumpRoomTrailer);
StateTransition(SIG_INITIALIZE);
}
// Erzeuge normalen LPC-Quellcode aus einem Haus oder Raum.
//
// Parameter:
// env: Das Haus oder der Raum, aus dem Quellcode erzeugt werden soll
// fin: Falls gleich 0, so wird Quellcode fuer Typofixes o.ae.
// erzeugt; das erzeugte File heisst immer 'fixed.c'.
// Andernfalls wird Quellcode fuer ein eigenstaendiges Objekt
// erzeugt. Dieses kann z.B. zum Anschluss als "Magierhaus"
// verwendet werden. Die erzeugten Files heissen
// 'rep/<name>raum<nr>.c' bzw. 'rep/<name>haus.c'. Befindet sich
// in dem Raum die Truhe, wird zusaetzlich die Datei
// 'rep/<name>truhe.c' geschrieben.
//
// Rueckgabewert:
// Der Dateiname, in den die Daten geschrieben wurden.
string
dump(object env, int fin, mixed args)
{
string out;
int num;
hausmeister = previous_object();
hmargs = args;
if (QueryState() != STATE_IDLE)
{
write("Der Generator arbeitet noch...\nBitte warten!\n");
return "<keine Datei generiert>\n";
}
// Falls ein Raum generiert wird, erhaelt <nr> die Raumnummer.
// Bei der Aussenansicht des Hauses wird <nr> auf -1 gesetzt.
if (sscanf(object_name(env), "%sraum%d", out, num) < 2)
{
num = -1;
}
if (fin)
{
out = PATH+"rep/"+env->QueryOwner();
if (num >= 0)
{
out += "raum"+num+".c";
}
else
{
out += "haus.c";
}
}
else
{
out = PATH+"fixed.c";
}
// Informationen fuer die Statemachine setzen
file = out;
final = fin;
raum = env;
nr = num;
if (num >= 0)
{
StateTransition(SIG_ROOM);
}
else
{
StateTransition(SIG_HOUSE);
}
return out;
}
// Sonderzeichen \, " und TAB korrekt umwandeln
private string special(string s)
{
s = implode(explode(s, "\\"), "\\\\");
s = implode(explode(s, "\t"), "\\t");
s = implode(explode(s, "\""), "\\\"");
return s;
}
/*** Funktionen zum Generieren einer Datei aus den Properties des Hauses ***/
#define EXIT_TMPL "\"/players/%s/seherhaus/%sraum%d\""
private void
removeOutputFile()
{
catch(rm(file));
}
private void
dumpHouse()
{
headerHouse();
sProp(file, "P_SHORT", raum->QueryProp(P_SHORT));
write_file(file, "\n");
sProp(file, "P_LONG", raum->QueryProp(P_LONG));
write_file(file, "\n");
if (final)
{
mixed n;
write_file(file, " SetProp(P_NOGET, 1);\n");
write_file(file,
" SetProp(P_GENDER, "+
({"NEUTER","MALE","FEMALE"})[raum->QueryProp(P_GENDER)]+
" );\n SetProp(P_NAME, ");
n = raum->QueryProp(P_NAME);
if (stringp(n))
{
write_file(file, "\""+n+"\"");
}
else
{
prettyArray(file, n, 0);
}
write_file(file, " );\n\n AddId( ");
prettyArray(file,
raum->QueryProp(P_IDS)-({ "sehe\rhaus",
"\n"+raum->QueryOwner()+"haus" }),
0);
write_file(file, " );\n");
}
trailerHouse();
StateTransition(SIG_HOUSE_DONE);
}
private void
dumpRoomHeader()
{
headerRoom();
sProp(file, "P_INT_SHORT", raum->QueryProp(P_INT_SHORT));
write_file(file, "\n");
sProp(file, "P_INT_LONG", raum->QueryProp(P_INT_LONG));
write_file(file, "\n");
if (final && raum->QueryProp(H_CHEST))
{
StateTransition(SIG_DO_CHEST);
}
else
{
StateTransition(SIG_DO_DETAIL);
}
}
private void
dumpChest()
{
mixed n;
string cfile;
object chest;
cfile = PATH+"rep/"+raum->QueryOwner()+"truhe.c";
chest = present(TRUHE, raum);
catch(rm(cfile));
write_file(cfile,
"#include <properties.h>\n#include <moving.h>\n\n"
"inherit \"/d/wueste/durian/behaelter\";\n\n"
"void create()\n{\n if(!clonep(this_object())) return;\n\n"
" ::create();\n\n" );
sProp(cfile, "P_SHORT", chest->QueryProp(P_SHORT));
sProp(cfile, "P_LONG", chest->QueryProp(P_LONG));
write_file(cfile, " SetProp(P_NOGET, 1);\n");
write_file(cfile,
" SetProp(P_GENDER, "+
({"NEUTER","MALE","FEMALE"})[chest->QueryProp(P_GENDER)]+
" );\n SetProp(P_NAME, ");
n = chest->QueryProp(P_NAME);
if (stringp(n))
{
write_file(cfile, "\""+n+"\"");
}
else
{
prettyArray(file, n, 0);
}
write_file(cfile, " );\n\n AddId( ");
prettyArray(cfile, chest->QueryProp(P_IDS)-({ TRUHE }), 0);
write_file(cfile, " );\n");
if ((n=chest->QueryProp(P_ADJECTIVES)) && sizeof(n))
{
write_file(cfile, "\n AddAdjective( ");
prettyArray(cfile, n, 0);
write_file(cfile, " );\n");
}
if ((n=chest->QueryProp(P_NAME_ADJ)) && sizeof(n))
{
write_file(cfile, "\n SetProp(P_NAME_ADJ, ");
prettyArray(cfile, n, 0);
write_file(cfile, " );\n");
}
write_file(cfile, "}\n");
StateTransition(SIG_DO_DETAIL);
}
private void
dumpDetails()
{
mapping prop;
mixed det;
prop = raum->QueryProp(P_DETAILS);
if (sizeof(prop))
{
det = VERWALTER->PCrunch(prop);
// next state transition happens when do_mProp is done
mProp(file, "AddDetail", det, sizeof(det)-1, SIG_DETAIL_DONE);
}
else
{
StateTransition(SIG_DETAIL_DONE);
}
}
private void
dumpReadDetails()
{
mapping prop;
mixed rdet;
prop = raum->QueryProp(P_READ_DETAILS);
if (sizeof(prop))
{
rdet = VERWALTER->PCrunch(prop);
// next state transition happens when do_mProp is done
mProp(file, "AddReadDetail", rdet, sizeof(rdet)-1, SIG_RDETAIL_DONE);
}
else
{
StateTransition(SIG_RDETAIL_DONE);
}
}
private void
dumpCommands()
{
mapping comm;
mixed cmd;
comm = raum->QueryProp(H_COMMANDS);
if (sizeof(comm))
{
cmd = VERWALTER->PCrunch(comm);
// next state transition happens when do_cProp is done
cProp(file, "AddUserCmd", cmd, sizeof(cmd)-1, SIG_COMMAND_DONE);
}
else
{
StateTransition(SIG_COMMAND_DONE);
}
}
private void
doFinalize()
{
if (final)
{
StateTransition(SIG_DO_EXITS);
}
else
{
StateTransition(SIG_ROOM_DONE);
}
}
private void
dumpExits()
{
string *k, o;
mapping prop;
int i, num;
prop = raum->QueryProp(P_EXITS);
k = m_indices(prop);
if (member(k, "raus") >= 0)
{
k -= ({ "raus" });
write_file(file, sprintf(" AddExit( \"raus\", \"%s\");\n", prop["raus"]));
}
for (i=sizeof(k)-1; i>=0; i--)
{
if (sscanf(prop[k[i]], PATH+"%sraum%d", o, num) != 2)
{
printf("Komischer Exit (%O)\n%s -> %s\n", raum, k[i], prop[k[i]]);
}
else
{
if (o == raum->QueryOwner())
{
o = sprintf(EXIT_TMPL, o, o, num);
write_file(file, sprintf(" AddExit( \"%s\", %s);\n", k[i], o));
}
else
{
write_file(file,
sprintf(" AddExit( \"%s\", \"%s\");\n", k[i], prop[k[i]]));
printf("Exit von %O nach %s!\n", raum, prop[k[i]]);
}
}
}
StateTransition(SIG_ROOM_DONE);
}
private void
dumpRoomTrailer()
{
trailerRoom();
doReturn();
}
private void
doReturn()
{
if (hausmeister != 0)
{
apply(#'call_other, hausmeister, "GenerationDone", hmargs);
}
destruct(this_object());
}
private void
sProp(string f, string pName, string pStr)
{
string *str;
write_file(f, " SetProp( "+pName+",");
if (!pStr)
{
write_file(f, "0 );\n");
return;
}
pStr = special(pStr);
if (sizeof(str=old_explode(pStr,"\n")) > 1)
{
prettyString(f, str, 4);
}
else
{
if (sizeof(str)==0)
{
str = ({""});
}
write_file(f, "\n \""+str[0]);
if (pStr[<1] == '\n')
{
write_file(f, "\\n\"");
}
else
{
write_file(f, "\"");
}
}
write_file(f, " );\n");
}
static void
mProp(string file, string pName, mixed cmd, int pos, int signal)
{
int i;
string *eq, t1;
for (i = pos; (i >= 0) && (get_eval_cost() > 10000); --i)
{
write_file(file, " "+pName+"(\n ");
eq = cmd[i][0];
t1 = cmd[i][1];
prettyArray(file, eq, 0);
write_file(file, ", ");
prettyString(file, old_explode(special(t1), "\n"), 6);
write_file(file, " );\n");
}
// Falls wir die eval_cost ausgereizt haben, aber noch nicht
// alle Einträge bearbeitet wurden, wird jetzt die naechste
// Runde gestartet
if (i >= 0)
{
call_out("mProp", 1, file, pName, cmd, i, signal);
}
else
{
// Ansonsten wechseln wir jetzt in den naechsten Zustand
write_file(file, "\n");
StateTransition(signal);
}
}
static void
cProp(string file, string pName, mixed cmd, int pos, int signal)
{
string t1, t2;
mixed eq;
int i;
for (i = pos; (i >= 0) && (get_eval_cost() > 10000); --i)
{
write_file(file, " "+pName+"(\n ");
eq = cmd[i][0];
t1 = cmd[i][1];
t2 = cmd[i][2];
prettyArray(file, eq, 1);
write_file(file, ", 0, ");
prettyString(file, old_explode(special(t1), "\n"), 4);
write_file(file, ", ");
if (t2)
{
prettyString(file, old_explode(special(t2), "\n"), 4);
}
else
{
write_file(file, "0");
}
write_file(file, " );\n");
}
// Falls wir die eval_cost ausgereizt haben, aber noch nicht
// alle Einträge bearbeitet wurden, wird jetzt die naechste
// Runde gestartet
if (i >= 0)
{
call_out("cProp", 1, file, pName, cmd, i, signal);
}
else
{
// Ansonsten wechseln wir jetzt in den naechsten Zustand
write_file(file, "\n");
StateTransition(signal);
}
}
private void
prettyString(string f, string *str, int indent)
{
string ind;
int i;
ind = extract("\n ",0,indent);
if (!sizeof(str))
{
write_file(f, ind+" \"\\n\"");
return;
}
write_file(f, ind+" \""+str[0]+"\\n\"");
for (i=1; i<sizeof(str); i++)
{
write_file(f, ind+"+\""+str[i]+"\\n\"");
}
}
private void
prettyArray(string f, string *arr, int sep)
{
int i,j;
string res, t1, t2;
write_file(f, "({");
if (sizeof(arr))
{
t1 = ("\""+arr[0]+"\"");
res = " "+t1;
t2 = "";
for (i=1, j=sizeof(arr); i<j; i++)
{
t2 = "\""+arr[i]+"\"";
if (!sep)
{
if ((sizeof(t1) + sizeof(t2)) > 69)
{
res += (",\n "+t2);
t1 = t2;
t2 = "";
}
else {
t1 += (", "+t2);
res += (", "+t2);
}
}
else {
res += (",\n "+t2);
}
}
}
write_file(f, res + " })" );
}
private void
headerRoom()
{
if (final)
{
write_file(file,
"#include <properties.h>\n\n"
"inherit \"std/room\";\n"
"inherit \""+PATH+"modules/usercmd\";\n\n"
"create()\n"
"{\n"
" room::create();\n"
" usercmd::create();\n\n"
" SetProp(P_LIGHT, 1);\n"
" SetProp(P_INDOORS, 1);\n\n");
}
else
{
write_file(file,
"#include \"haus.h\"\n"
"#include <properties.h>\n\n"
"inherit RAUM;\n"
"inherit \"/std/thing/moving\";\n\n"
"create()\n"
"{\n"
" if (!clonep(this_object())) return;\n"
" ::create();\n\n"
" SetOwner(\""+raum->QueryOwner()+"\", "+nr+");\n"
" Load();\n\n"
" SetProp(P_DETAILS, ([]));\n"
" SetProp(P_READ_DETAILS, ([]));\n\n");
}
}
private void
trailerRoom()
{
if (final)
{
write_file(file, "}\n");
}
else
{
write_file(file,
" Save(1);\n\n"
" { object raum;\n"
" if (raum = find_object(RAUMNAME("
"\""+raum->QueryOwner()+"\", "+nr+")))\n"
" raum->Load();\n"
" }\n\n"
" call_out(\"remove\",0);\n"
"}\n");
}
}
private void
headerHouse()
{
if (final)
{
write_file(file,
"#include <properties.h>\n"
"#include <moving.h>\n"
"#include \""+PATH+"haus.h\"\n\n"
"inherit \"std/thing\";\n"
"inherit HAUSTUER;\n\n"
"create()\n"
"{\n"
" thing::create();\n"
" haustuer::create();\n\n");
}
else
{
write_file(file,
"#include \"haus.h\"\n"
"#include <properties.h>\n\n"
"inherit HAUS;\n"
"inherit \"/std/thing/moving\";\n\n"
"create()\n"
"{\n"
" if (!clonep(this_object())) return;\n"
" ::create();\n\n"
" SetOwner(\""+raum->QueryOwner()+"\"\n"
" Load();\n\n");
}
}
private void
trailerHouse()
{
if (final)
{
write_file(file, read_file(PATH+"tools/haus.apx"));
write_file(file, " this_player()->move(");
write_file(file, sprintf(EXIT_TMPL,
raum->QueryOwner(), raum->QueryOwner(), 0));
write_file(file,
",\n\t\t\tM_GO, 0, \"betritt \"+name(WEN,1), \"kommt herein\");\n"
" return 1;\n}\n");
if (!raum->QueryProp(P_SHORT))
{
write_file(file,
"\nstring short()\n"
"{\n"
" string ret;\n\n"
" ret = ::short();\n"
" if (previous_object() != environment() && !ret)\n"
" ret =\"\";\n\n"
" return ret;\n"
"}\n");
}
}
else
{
write_file(file,
" Save(1);\n\n"
" { object raum;\n"
" if (raum = find_object(HAUSNAME("
"\""+raum->QueryOwner()+"\")))\n"
" raum->Load();\n"
" }\n\n"
" call_out(\"remove\",0);\n}\n");
}
}