blob: 3254c2ba9c7b342014ab5f027e962acab42445dd [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001#include "../haus.h"
2
3inherit "/p/service/wargon/sm/statemachine";
4
5#include "/p/service/wargon/sm/statemachine.h"
6#include <properties.h>
7
8#define STATE_IDLE 0
9#define STATE_HOUSE 1
10#define STATE_ROOM 2
11#define STATE_CHEST 3
12#define STATE_DETAIL 4
13#define STATE_RDETAIL 5
14#define STATE_COMMAND 6
15#define STATE_FINALIZE 7
16#define STATE_EXITS 8
17
18#define SIG_INITIALIZE 0
19#define SIG_HOUSE 1
20#define SIG_HOUSE_DONE 2
21#define SIG_ROOM 3
22#define SIG_DO_CHEST 4
23#define SIG_DO_DETAIL 5
24#define SIG_DETAIL_DONE 6
25#define SIG_RDETAIL_DONE 7
26#define SIG_COMMAND_DONE 8
27#define SIG_DO_EXITS 9
28#define SIG_ROOM_DONE 10
29
30private nosave string file;
31private nosave int final;
32private nosave object raum;
33private nosave int nr;
34private nosave object hausmeister;
35private nosave mixed hmargs;
36
37string dump(object env, int final, mixed args);
38
39private string special(string str);
40private void removeOutputFile();
41private void dumpHouse();
42private void dumpRoomHeader();
43private void dumpChest();
44private void dumpDetails();
45private void dumpReadDetails();
46private void dumpCommands();
47private void doFinalize();
48private void dumpExits();
49private void dumpRoomTrailer();
50private void doReturn();
51private void sProp(string file, string pName, string pStr);
52static void mProp(string file, string pName, mixed map_ldfied, int pos, int signal);
53static void cProp(string file, string pName, mixed cmd, int pos, int signal);
54private void prettyString(string file, string *str, int indent);
55private void prettyArray(string file, string *arr, int sep);
56private void headerRoom();
57private void trailerRoom();
58private void headerHouse();
59private void trailerHouse();
60
61create()
62{
63 ::create();
64 seteuid(getuid());
65
66 AddState(STATE_IDLE, 0, 0);
67 AddState(STATE_HOUSE, #'dumpHouse, 0);
68 AddState(STATE_ROOM, #'dumpRoomHeader, 0);
69 AddState(STATE_CHEST, #'dumpChest, 0);
70 AddState(STATE_DETAIL, #'dumpDetails, 0);
71 AddState(STATE_RDETAIL, #'dumpReadDetails, 0);
72 AddState(STATE_COMMAND, #'dumpCommands, 0);
73 AddState(STATE_FINALIZE, #'doFinalize, 0);
74 AddState(STATE_EXITS, #'dumpExits, 0);
75
76 AddTransition(SM_INVALID, SIG_INITIALIZE, STATE_IDLE, 0);
77
78 // Zustandsuebergaenge zum Schreiben des Hauses
79 AddTransition(STATE_IDLE, SIG_HOUSE, STATE_HOUSE, #'removeOutputFile);
80 AddTransition(STATE_HOUSE, SIG_HOUSE_DONE, STATE_IDLE, #'doReturn);
81
82 // Zustandsuebergaenge zum Schreiben eines Raums
83 AddTransition(STATE_IDLE, SIG_ROOM, STATE_ROOM, #'removeOutputFile);
84 AddTransition(STATE_ROOM, SIG_DO_CHEST, STATE_CHEST);
85 AddTransition(STATE_ROOM, SIG_DO_DETAIL, STATE_DETAIL);
86 AddTransition(STATE_CHEST, SIG_DO_DETAIL, STATE_DETAIL);
87 AddTransition(STATE_DETAIL, SIG_DETAIL_DONE, STATE_RDETAIL);
88 AddTransition(STATE_RDETAIL, SIG_RDETAIL_DONE, STATE_COMMAND);
89 AddTransition(STATE_COMMAND, SIG_COMMAND_DONE, STATE_FINALIZE);
90 AddTransition(STATE_FINALIZE, SIG_DO_EXITS, STATE_EXITS);
91 AddTransition(STATE_FINALIZE, SIG_ROOM_DONE, STATE_IDLE, #'doReturn);
92 AddTransition(STATE_EXITS, SIG_ROOM_DONE, STATE_IDLE, #'dumpRoomTrailer);
93
94 StateTransition(SIG_INITIALIZE);
95}
96
97
98// Erzeuge normalen LPC-Quellcode aus einem Haus oder Raum.
99//
100// Parameter:
101// env: Das Haus oder der Raum, aus dem Quellcode erzeugt werden soll
102// fin: Falls gleich 0, so wird Quellcode fuer Typofixes o.ae.
103// erzeugt; das erzeugte File heisst immer 'fixed.c'.
104// Andernfalls wird Quellcode fuer ein eigenstaendiges Objekt
105// erzeugt. Dieses kann z.B. zum Anschluss als "Magierhaus"
106// verwendet werden. Die erzeugten Files heissen
107// 'rep/<name>raum<nr>.c' bzw. 'rep/<name>haus.c'. Befindet sich
108// in dem Raum die Truhe, wird zusaetzlich die Datei
109// 'rep/<name>truhe.c' geschrieben.
110//
111// Rueckgabewert:
112// Der Dateiname, in den die Daten geschrieben wurden.
113
114string
115dump(object env, int fin, mixed args)
116{
117 string out;
118 int num;
119
120 hausmeister = previous_object();
121 hmargs = args;
122
123 if (QueryState() != STATE_IDLE)
124 {
125 write("Der Generator arbeitet noch...\nBitte warten!\n");
126 return "<keine Datei generiert>\n";
127 }
128
129 // Falls ein Raum generiert wird, erhaelt <nr> die Raumnummer.
130 // Bei der Aussenansicht des Hauses wird <nr> auf -1 gesetzt.
131 if (sscanf(object_name(env), "%sraum%d", out, num) < 2)
132 {
133 num = -1;
134 }
135
136 if (fin)
137 {
138 out = PATH+"rep/"+env->QueryOwner();
139
140 if (num >= 0)
141 {
142 out += "raum"+num+".c";
143 }
144 else
145 {
146 out += "haus.c";
147 }
148 }
149 else
150 {
151 out = PATH+"fixed.c";
152 }
153
154 // Informationen fuer die Statemachine setzen
155 file = out;
156 final = fin;
157 raum = env;
158 nr = num;
159
160 if (num >= 0)
161 {
162 StateTransition(SIG_ROOM);
163 }
164 else
165 {
166 StateTransition(SIG_HOUSE);
167 }
168 return out;
169}
170
171// Sonderzeichen \, " und TAB korrekt umwandeln
172private string special(string s)
173{
174 s = implode(explode(s, "\\"), "\\\\");
175 s = implode(explode(s, "\t"), "\\t");
176 s = implode(explode(s, "\""), "\\\"");
177
178 return s;
179}
180
181/*** Funktionen zum Generieren einer Datei aus den Properties des Hauses ***/
182
183#define EXIT_TMPL "\"/players/%s/seherhaus/%sraum%d\""
184
185private void
186removeOutputFile()
187{
188 catch(rm(file));
189}
190
191private void
192dumpHouse()
193{
194 headerHouse();
195
196 sProp(file, "P_SHORT", raum->QueryProp(P_SHORT));
197 write_file(file, "\n");
198 sProp(file, "P_LONG", raum->QueryProp(P_LONG));
199 write_file(file, "\n");
200
201 if (final)
202 {
203 mixed n;
204
205 write_file(file, " SetProp(P_NOGET, 1);\n");
206 write_file(file,
207 " SetProp(P_GENDER, "+
208 ({"NEUTER","MALE","FEMALE"})[raum->QueryProp(P_GENDER)]+
209 " );\n SetProp(P_NAME, ");
210 n = raum->QueryProp(P_NAME);
211
212 if (stringp(n))
213 {
214 write_file(file, "\""+n+"\"");
215 }
216 else
217 {
218 prettyArray(file, n, 0);
219 }
220 write_file(file, " );\n\n AddId( ");
221 prettyArray(file,
222 raum->QueryProp(P_IDS)-({ "sehe\rhaus",
223 "\n"+raum->QueryOwner()+"haus" }),
224 0);
225 write_file(file, " );\n");
226 }
227 trailerHouse();
228
229 StateTransition(SIG_HOUSE_DONE);
230}
231
232private void
233dumpRoomHeader()
234{
235 headerRoom();
236
237 sProp(file, "P_INT_SHORT", raum->QueryProp(P_INT_SHORT));
238 write_file(file, "\n");
239 sProp(file, "P_INT_LONG", raum->QueryProp(P_INT_LONG));
240 write_file(file, "\n");
241
242 if (final && raum->QueryProp(H_CHEST))
243 {
244 StateTransition(SIG_DO_CHEST);
245 }
246 else
247 {
248 StateTransition(SIG_DO_DETAIL);
249 }
250}
251
252private void
253dumpChest()
254{
255 mixed n;
256 string cfile;
257 object chest;
258
259 cfile = PATH+"rep/"+raum->QueryOwner()+"truhe.c";
260 chest = present(TRUHE, raum);
261
262 catch(rm(cfile));
263
264 write_file(cfile,
265 "#include <properties.h>\n#include <moving.h>\n\n"
266 "inherit \"/d/wueste/durian/behaelter\";\n\n"
267 "void create()\n{\n if(!clonep(this_object())) return;\n\n"
268 " ::create();\n\n" );
269 sProp(cfile, "P_SHORT", chest->QueryProp(P_SHORT));
270 sProp(cfile, "P_LONG", chest->QueryProp(P_LONG));
271
272 write_file(cfile, " SetProp(P_NOGET, 1);\n");
273 write_file(cfile,
274 " SetProp(P_GENDER, "+
275 ({"NEUTER","MALE","FEMALE"})[chest->QueryProp(P_GENDER)]+
276 " );\n SetProp(P_NAME, ");
277
278 n = chest->QueryProp(P_NAME);
279 if (stringp(n))
280 {
281 write_file(cfile, "\""+n+"\"");
282 }
283 else
284 {
285 prettyArray(file, n, 0);
286 }
287 write_file(cfile, " );\n\n AddId( ");
288 prettyArray(cfile, chest->QueryProp(P_IDS)-({ TRUHE }), 0);
289 write_file(cfile, " );\n");
290
291 if ((n=chest->QueryProp(P_ADJECTIVES)) && sizeof(n))
292 {
293 write_file(cfile, "\n AddAdjective( ");
294 prettyArray(cfile, n, 0);
295 write_file(cfile, " );\n");
296 }
297 if ((n=chest->QueryProp(P_NAME_ADJ)) && sizeof(n))
298 {
299 write_file(cfile, "\n SetProp(P_NAME_ADJ, ");
300 prettyArray(cfile, n, 0);
301 write_file(cfile, " );\n");
302 }
303 write_file(cfile, "}\n");
304
305 StateTransition(SIG_DO_DETAIL);
306}
307
308private void
309dumpDetails()
310{
311 mapping prop;
312 mixed det;
313
314 prop = raum->QueryProp(P_DETAILS);
315
316 if (sizeof(prop))
317 {
318 det = VERWALTER->PCrunch(prop);
319 // next state transition happens when do_mProp is done
320 mProp(file, "AddDetail", det, sizeof(det)-1, SIG_DETAIL_DONE);
321 }
322 else
323 {
324 StateTransition(SIG_DETAIL_DONE);
325 }
326}
327
328private void
329dumpReadDetails()
330{
331 mapping prop;
332 mixed rdet;
333
334 prop = raum->QueryProp(P_READ_DETAILS);
335
336 if (sizeof(prop))
337 {
338 rdet = VERWALTER->PCrunch(prop);
339 // next state transition happens when do_mProp is done
340 mProp(file, "AddReadDetail", rdet, sizeof(rdet)-1, SIG_RDETAIL_DONE);
341 }
342 else
343 {
344 StateTransition(SIG_RDETAIL_DONE);
345 }
346}
347
348private void
349dumpCommands()
350{
351 mapping comm;
352 mixed cmd;
353
354 comm = raum->QueryProp(H_COMMANDS);
355
356 if (sizeof(comm))
357 {
358 cmd = VERWALTER->PCrunch(comm);
359 // next state transition happens when do_cProp is done
360 cProp(file, "AddUserCmd", cmd, sizeof(cmd)-1, SIG_COMMAND_DONE);
361 }
362 else
363 {
364 StateTransition(SIG_COMMAND_DONE);
365 }
366}
367
368private void
369doFinalize()
370{
371 if (final)
372 {
373 StateTransition(SIG_DO_EXITS);
374 }
375 else
376 {
377 StateTransition(SIG_ROOM_DONE);
378 }
379}
380
381private void
382dumpExits()
383{
384 string *k, o;
385 mapping prop;
386 int i, num;
387
388 prop = raum->QueryProp(P_EXITS);
389 k = m_indices(prop);
390 if (member(k, "raus") >= 0)
391 {
392 k -= ({ "raus" });
393 write_file(file, sprintf(" AddExit( \"raus\", \"%s\");\n", prop["raus"]));
394 }
395
396 for (i=sizeof(k)-1; i>=0; i--)
397 {
398 if (sscanf(prop[k[i]], PATH+"%sraum%d", o, num) != 2)
399 {
400 printf("Komischer Exit (%O)\n%s -> %s\n", raum, k[i], prop[k[i]]);
401 }
402 else
403 {
404 if (o == raum->QueryOwner())
405 {
406 o = sprintf(EXIT_TMPL, o, o, num);
407 write_file(file, sprintf(" AddExit( \"%s\", %s);\n", k[i], o));
408 }
409 else
410 {
411 write_file(file,
412 sprintf(" AddExit( \"%s\", \"%s\");\n", k[i], prop[k[i]]));
413 printf("Exit von %O nach %s!\n", raum, prop[k[i]]);
414 }
415 }
416 }
417 StateTransition(SIG_ROOM_DONE);
418}
419
420private void
421dumpRoomTrailer()
422{
423 trailerRoom();
424 doReturn();
425}
426
427private void
428doReturn()
429{
430 if (hausmeister != 0)
431 {
432 apply(#'call_other, hausmeister, "GenerationDone", hmargs);
433 }
434 destruct(this_object());
435}
436
437private void
438sProp(string f, string pName, string pStr)
439{
440 string *str;
441
442 write_file(f, " SetProp( "+pName+",");
443
444 if (!pStr)
445 {
446 write_file(f, "0 );\n");
447 return;
448 }
449
450 pStr = special(pStr);
451
452 if (sizeof(str=old_explode(pStr,"\n")) > 1)
453 {
454 prettyString(f, str, 4);
455 }
456 else
457 {
458 if (sizeof(str)==0)
459 {
460 str = ({""});
461 }
462 write_file(f, "\n \""+str[0]);
463
464 if (pStr[<1] == '\n')
465 {
466 write_file(f, "\\n\"");
467 }
468 else
469 {
470 write_file(f, "\"");
471 }
472 }
473 write_file(f, " );\n");
474}
475
476static void
477mProp(string file, string pName, mixed cmd, int pos, int signal)
478{
479 int i;
480 string *eq, t1;
481
482 for (i = pos; (i >= 0) && (get_eval_cost() > 10000); --i)
483 {
484 write_file(file, " "+pName+"(\n ");
485 eq = cmd[i][0];
486 t1 = cmd[i][1];
487
488 prettyArray(file, eq, 0);
489 write_file(file, ", ");
490
491 prettyString(file, old_explode(special(t1), "\n"), 6);
492 write_file(file, " );\n");
493 }
494
495 // Falls wir die eval_cost ausgereizt haben, aber noch nicht
496 // alle Einträge bearbeitet wurden, wird jetzt die naechste
497 // Runde gestartet
498 if (i >= 0)
499 {
500 call_out("mProp", 1, file, pName, cmd, i, signal);
501 }
502 else
503 {
504 // Ansonsten wechseln wir jetzt in den naechsten Zustand
505 write_file(file, "\n");
506 StateTransition(signal);
507 }
508}
509
510static void
511cProp(string file, string pName, mixed cmd, int pos, int signal)
512{
513 string t1, t2;
514 mixed eq;
515 int i;
516
517 for (i = pos; (i >= 0) && (get_eval_cost() > 10000); --i)
518 {
519 write_file(file, " "+pName+"(\n ");
520 eq = cmd[i][0];
521 t1 = cmd[i][1];
522 t2 = cmd[i][2];
523
524 prettyArray(file, eq, 1);
525 write_file(file, ", 0, ");
526
527 prettyString(file, old_explode(special(t1), "\n"), 4);
528 write_file(file, ", ");
529
530 if (t2)
531 {
532 prettyString(file, old_explode(special(t2), "\n"), 4);
533 }
534 else
535 {
536 write_file(file, "0");
537 }
538
539 write_file(file, " );\n");
540 }
541
542 // Falls wir die eval_cost ausgereizt haben, aber noch nicht
543 // alle Einträge bearbeitet wurden, wird jetzt die naechste
544 // Runde gestartet
545 if (i >= 0)
546 {
547 call_out("cProp", 1, file, pName, cmd, i, signal);
548 }
549 else
550 {
551 // Ansonsten wechseln wir jetzt in den naechsten Zustand
552 write_file(file, "\n");
553 StateTransition(signal);
554 }
555}
556
557private void
558prettyString(string f, string *str, int indent)
559{
560 string ind;
561 int i;
562
563 ind = extract("\n ",0,indent);
564
565 if (!sizeof(str))
566 {
567 write_file(f, ind+" \"\\n\"");
568 return;
569 }
570
571 write_file(f, ind+" \""+str[0]+"\\n\"");
572
573 for (i=1; i<sizeof(str); i++)
574 {
575 write_file(f, ind+"+\""+str[i]+"\\n\"");
576 }
577}
578
579private void
580prettyArray(string f, string *arr, int sep)
581{
582 int i,j;
583 string res, t1, t2;
584
585 write_file(f, "({");
586
587 if (sizeof(arr))
588 {
589 t1 = ("\""+arr[0]+"\"");
590 res = " "+t1;
591 t2 = "";
592
593 for (i=1, j=sizeof(arr); i<j; i++)
594 {
595 t2 = "\""+arr[i]+"\"";
596 if (!sep)
597 {
598 if ((sizeof(t1) + sizeof(t2)) > 69)
599 {
600 res += (",\n "+t2);
601 t1 = t2;
602 t2 = "";
603 }
604 else {
605 t1 += (", "+t2);
606 res += (", "+t2);
607 }
608 }
609 else {
610 res += (",\n "+t2);
611 }
612 }
613 }
614 write_file(f, res + " })" );
615}
616
617private void
618headerRoom()
619{
620 if (final)
621 {
622 write_file(file,
623 "#include <properties.h>\n\n"
624 "inherit \"std/room\";\n"
625 "inherit \""+PATH+"modules/usercmd\";\n\n"
626 "create()\n"
627 "{\n"
628 " room::create();\n"
629 " usercmd::create();\n\n"
630 " SetProp(P_LIGHT, 1);\n"
631 " SetProp(P_INDOORS, 1);\n\n");
632 }
633 else
634 {
635 write_file(file,
636 "#include \"haus.h\"\n"
637 "#include <properties.h>\n\n"
638 "inherit RAUM;\n"
639 "inherit \"/std/thing/moving\";\n\n"
640 "create()\n"
641 "{\n"
642 " if (!clonep(this_object())) return;\n"
643 " ::create();\n\n"
644 " SetOwner(\""+raum->QueryOwner()+"\", "+nr+");\n"
645 " Load();\n\n"
646 " SetProp(P_DETAILS, ([]));\n"
647 " SetProp(P_READ_DETAILS, ([]));\n\n");
648 }
649}
650
651private void
652trailerRoom()
653{
654 if (final)
655 {
656 write_file(file, "}\n");
657 }
658 else
659 {
660 write_file(file,
661 " Save(1);\n\n"
662 " { object raum;\n"
663 " if (raum = find_object(RAUMNAME("
664 "\""+raum->QueryOwner()+"\", "+nr+")))\n"
665 " raum->Load();\n"
666 " }\n\n"
667 " call_out(\"remove\",0);\n"
668 "}\n");
669 }
670}
671
672private void
673headerHouse()
674{
675 if (final)
676 {
677 write_file(file,
678 "#include <properties.h>\n"
679 "#include <moving.h>\n"
680 "#include \""+PATH+"haus.h\"\n\n"
681 "inherit \"std/thing\";\n"
682 "inherit HAUSTUER;\n\n"
683 "create()\n"
684 "{\n"
685 " thing::create();\n"
686 " haustuer::create();\n\n");
687 }
688 else
689 {
690 write_file(file,
691 "#include \"haus.h\"\n"
692 "#include <properties.h>\n\n"
693 "inherit HAUS;\n"
694 "inherit \"/std/thing/moving\";\n\n"
695 "create()\n"
696 "{\n"
697 " if (!clonep(this_object())) return;\n"
698 " ::create();\n\n"
699 " SetOwner(\""+raum->QueryOwner()+"\"\n"
700 " Load();\n\n");
701 }
702}
703
704private void
705trailerHouse()
706{
707 if (final)
708 {
709 write_file(file, read_file(PATH+"tools/haus.apx"));
710 write_file(file, " this_player()->move(");
711 write_file(file, sprintf(EXIT_TMPL,
712 raum->QueryOwner(), raum->QueryOwner(), 0));
713 write_file(file,
714 ",\n\t\t\tM_GO, 0, \"betritt \"+name(WEN,1), \"kommt herein\");\n"
715 " return 1;\n}\n");
716 if (!raum->QueryProp(P_SHORT))
717 {
718 write_file(file,
719 "\nstring short()\n"
720 "{\n"
721 " string ret;\n\n"
722 " ret = ::short();\n"
723 " if (previous_object() != environment() && !ret)\n"
724 " ret =\"\";\n\n"
725 " return ret;\n"
726 "}\n");
727 }
728 }
729 else
730 {
731 write_file(file,
732 " Save(1);\n\n"
733 " { object raum;\n"
734 " if (raum = find_object(HAUSNAME("
735 "\""+raum->QueryOwner()+"\")))\n"
736 " raum->Load();\n"
737 " }\n\n"
738 " call_out(\"remove\",0);\n}\n");
739 }
740}