#include <moving.h>#include <thing/language.h>#include <exploration.h>#include <thing/description.h>#include <thing/commands.h>
gehe zum Quellcode dieser Datei
Makrodefinitionen | |
| #define | NEED_PROTOTYPES |
| #define | DBG(x) if(find_player("jof")) tell_object(find_player("jof"),sprintf("%O\n",x)); |
| #define | CHECK_PRESENT 1 |
| #define | CHECK_ID 2 |
| #define | CHECK_PUTGETNONE 4 |
| #define | CHECK_PUTGETDROP 8 |
| #define | CHECK_PUTGETTAKE 16 |
| #define | CHECK_PUTGET (CHECK_PUTGETNONE|CHECK_PUTGETDROP|CHECK_PUTGETTAKE) |
Funktionen | |
| protected void | create () |
| protected void | create_super () |
| varargs void | AddCmd (mixed cmd, mixed func, mixed flag, mixed cmdid) |
| varargs int | RemoveCmd (mixed cmd, int del_norule, mixed onlyid) |
| static int | _execute (mixed fun, string str, mixed *parsed) |
| static int | _process_command (string str, string *noparsestr, mixed *fun, mixed *flag, mixed *rule) |
| public int | _cl (string str) |
| void | init () |
| static void | _check_copy_commands (string ind, mixed *fun, mixed *flag, mixed *rule) |
| static mapping | _set_commands (mapping commands) |
| static mapping | _query_commands () |
Variablen | |
| private nosave mapping | added_cmds |
| #define CHECK_ID 2 |
Definiert in Zeile 256 der Datei commands.c.
Wird benutzt von _process_command().
| #define CHECK_PRESENT 1 |
Definiert in Zeile 255 der Datei commands.c.
Wird benutzt von _process_command().
| #define CHECK_PUTGET (CHECK_PUTGETNONE|CHECK_PUTGETDROP|CHECK_PUTGETTAKE) |
Definiert in Zeile 260 der Datei commands.c.
Wird benutzt von _process_command().
| #define CHECK_PUTGETDROP 8 |
Definiert in Zeile 258 der Datei commands.c.
Wird benutzt von _process_command().
| #define CHECK_PUTGETNONE 4 |
Definiert in Zeile 257 der Datei commands.c.
Wird benutzt von _process_command().
| #define CHECK_PUTGETTAKE 16 |
Definiert in Zeile 259 der Datei commands.c.
Wird benutzt von _process_command().
| #define DBG | ( | x | ) | if(find_player("jof")) tell_object(find_player("jof"),sprintf("%O\n",x)); |
Definiert in Zeile 157 der Datei commands.c.
| #define NEED_PROTOTYPES |
Definiert in Zeile 40 der Datei commands.c.
| static void _check_copy_commands | ( | string | ind, | |
| mixed * | fun, | |||
| mixed * | flag, | |||
| mixed * | rule | |||
| ) | [static] |
Definiert in Zeile 475 der Datei commands.c.
Benutzt added_cmds.
00476 { 00477 if(pointerp(fun)) added_cmds[ind,0]=fun+allocate(0); 00478 else added_cmds[ind,0]=({fun}); 00479 if(pointerp(flag)) added_cmds[ind,1]=flag+allocate(0); 00480 else if(flag) added_cmds[ind,1]=({flag}); 00481 else added_cmds[ind,1]=allocate(sizeof(added_cmds[ind])); 00482 if(pointerp(rule)) added_cmds[ind,2]=rule+allocate(0); 00483 else added_cmds[ind,2]=allocate(sizeof(added_cmds[ind])); 00484 00485 if(sizeof(added_cmds[ind])!=sizeof(added_cmds[ind,1]) || 00486 sizeof(added_cmds[ind])!=sizeof(added_cmds[ind,2])) { 00487 added_cmds=(mapping)0; 00488 raise_error("SetProp(P_COMMANDS): corrupt commands-mapping.\n"); 00489 } 00490 }
| public int _cl | ( | string | str | ) |
Definiert in Zeile 425 der Datei commands.c.
Benutzt _execute(), _process_command(), added_cmds, EP_CMD, GiveEP(), i, ids und keys.
00425 { 00426 int nindex; 00427 string *keys; 00428 mixed *flag; 00429 // Verb existiert, Kommandos auch, Eintrag fuer Verb gefunden 00430 if(mappingp(added_cmds) && query_verb()) { 00431 mixed *fun, *rule, *ids; 00432 00433 // ist das Verb ein Key im Kommandomapping? 00434 if(m_contains(&fun, &flag, &rule, &ids, added_cmds, query_verb())) { 00435 string *noparsestr; 00436 nindex=sizeof(fun); 00437 noparsestr=explode((str||"")," ")-({""}); 00438 // dann matche ungeparsten Input gegen etwaige Regeln 00439 // -- nicht aendern: neue Kommandos sollen alte "ueberschreiben" koennen 00440 while(nindex--) 00441 if(_process_command(&str, noparsestr, 00442 fun[nindex], flag[nindex], rule[nindex])) 00443 { 00444 GiveEP(EP_CMD, query_verb()); 00445 return 1; 00446 } 00447 } 00448 00449 // keine Regel passte, unscharfe Auswertung auf alle 00450 // AddCmdverben ausdehnen 00451 keys=m_indices(added_cmds); 00452 nindex=sizeof(keys); 00453 while(nindex--) 00454 if(!strstr(query_verb(),keys[nindex]) && 00455 member((flag=added_cmds[keys[nindex],1]),1)>=0) { 00456 int i,ret; 00457 i=sizeof(flag); 00458 // Reihenfolge nicht aendern ! 00459 while(i--) 00460 if(flag[i]==1 && _execute(added_cmds[keys[nindex],0][i],str,0)) 00461 { 00462 GiveEP(EP_CMD, query_verb()); 00463 return 1; 00464 } 00465 } 00466 } 00467 return 0; 00468 }

| static int _execute | ( | mixed | fun, | |
| string | str, | |||
| mixed * | parsed | |||
| ) | [static] |
Definiert in Zeile 247 der Datei commands.c.
Wird benutzt von _cl() und _process_command().
00247 { 00248 if(closurep(fun)) 00249 return ((int)funcall(fun,str,&parsed)); 00250 if(stringp(fun)) 00251 return ((int)call_other(this_object(),fun,str,&parsed)); 00252 return 0; 00253 }

| static int _process_command | ( | string | str, | |
| string * | noparsestr, | |||
| mixed * | fun, | |||
| mixed * | flag, | |||
| mixed * | rule | |||
| ) | [static] |
Definiert in Zeile 263 der Datei commands.c.
Benutzt _execute(), break_string(), CHECK_ID, CHECK_PRESENT, CHECK_PUTGET, CHECK_PUTGETDROP, CHECK_PUTGETNONE, CHECK_PUTGETTAKE, find_obs(), notify_fail(), PUT_GET_DROP, PUT_GET_NONE, PUT_GET_TAKE und replace_personal().
Wird benutzt von _cl().
00264 { 00265 int tmpint; 00266 mixed *parsed, *pointermatches; 00267 00268 // eine Regel ... auswerten ... 00269 if(pointerp(rule)) { 00270 int lastmatchpos, nrul, rs; 00271 parsed=pointermatches=allocate(0); 00272 lastmatchpos=-1; 00273 00274 // Abgleichen der gesplitteten Eingabe mit Regeln: 00275 // vorwaerts durch die Synonymgruppen 00276 rs=sizeof(rule); 00277 while(nrul<rs) { 00278 int matchpos; 00279 string *synonym; 00280 mixed matchstr, tmp; 00281 00282 matchpos=-1; 00283 matchstr=0; 00284 00285 // Synonyme extrahieren 00286 tmpint=sizeof(synonym=rule[nrul]); 00287 00288 // egal wie durch Synonyme bis Match - Abgleich mit Eingabe 00289 while(tmpint--) { 00290 // ist Synonym im Eingabestring und kommt spaeter als vorheriges Synonym? 00291 if((tmp=member(noparsestr,synonym[tmpint]))>=0 && 00292 tmp>lastmatchpos) { 00293 // Erfolg: merken der Position im Eingabestring und den matchenden String 00294 matchpos=tmp; 00295 matchstr=noparsestr[tmp]; 00296 break; 00297 } 00298 } 00299 00300 // kein Match durch Synonyme? 00301 if(matchpos<0) { 00302 int check_present; 00303 // ist Abpruefen von ID/PRESENT in der Synonymgruppe verlangt 00304 // bei present()/find_obs gleich Grundvoraussetzung mitprufen 00305 if(member(synonym,"@ID")>=0) check_present=CHECK_ID; 00306 if(this_player()) { 00307 if(member(synonym,"@PRESENT")>=0) check_present|=CHECK_PRESENT; 00308 else if(member(synonym,"@PUT_GET_NONE")>=0) 00309 check_present|=CHECK_PUTGETNONE; 00310 else if(member(synonym,"@PUT_GET_TAKE")>=0) 00311 check_present|=CHECK_PUTGETDROP; 00312 else if(member(synonym,"@PUT_GET_DROP")>=0) 00313 check_present|=CHECK_PUTGETTAKE; 00314 } 00315 if(check_present) { 00316 int q,r; 00317 // wir fangen hinter dem letzten Match an 00318 if(lastmatchpos<0) q=0; 00319 else q=lastmatchpos+1; 00320 r=sizeof(noparsestr)-1; 00321 00322 while((tmp=r-q)>=0) { 00323 mixed tmpobj; 00324 00325 // wie weit wollen wir zurückgehen? 00326 if(tmp) 00327 if(!(check_present&CHECK_PUTGET)) 00328 tmp=1; // 2 Fragmente fuer @ID / @PRESENT 00329 else if(tmp>4) 00330 tmp=4; // 5 Fragmente fuer @PUT_XXX 00331 00332 // und jetzt die Substrings prüfen 00333 while(tmp>=0 && !matchstr) { 00334 string tmpstr; 00335 00336 if(tmp) tmpstr=implode(noparsestr[q..(q+tmp)]," "); 00337 else tmpstr=noparsestr[q]; 00338 00339 // DBG(tmpstr); 00340 if(check_present&CHECK_PRESENT && // PRESENT ? 00341 ((tmpobj=present(tmpstr,this_player())) || 00342 (tmpobj=present(tmpstr,environment(this_player()))))) 00343 matchstr=tmpobj; 00344 else if(check_present&CHECK_ID && id(tmpstr)) // ID ? 00345 matchstr=this_object(); 00346 else if((check_present&CHECK_PUTGET) && // PUT_GET_??? ? 00347 (tmpobj=(object*) 00348 this_player()->find_obs(tmpstr, 00349 ([CHECK_PUTGETNONE:PUT_GET_NONE, 00350 CHECK_PUTGETDROP:PUT_GET_TAKE, 00351 CHECK_PUTGETTAKE:PUT_GET_DROP]) 00352 [CHECK_PUTGET&check_present])) && 00353 sizeof(tmpobj)) { 00354 if(sizeof(tmpobj)==1) matchstr=tmpobj[0]; 00355 else { // Arrays werden zwischengespeichert ... 00356 pointermatches+=({sizeof(parsed),tmpobj}); 00357 matchstr=tmpstr; 00358 } 00359 } else { 00360 tmp--; 00361 continue; 00362 } 00363 } 00364 00365 // Match gefunden! 00366 if(matchstr) { 00367 matchpos=tmp+q; 00368 // DBG(matchpos); 00369 break; 00370 } 00371 q++; 00372 } // end while 00373 } 00374 } 00375 00376 00377 // Fehlermeldung fuer diese fehlgeschlagene Synonymgruppe setzen 00378 if(matchpos<0) { 00379 // Fehlermeldungen und ein Eintrag an der Fehlerstelle? 00380 if(pointerp(flag) && sizeof(flag)>nrul) { 00381 00382 matchstr=flag[nrul]; 00383 00384 if(stringp(matchstr) && strlen(matchstr)) { 00385 if(member(matchstr,'@')>=0) { 00386 matchstr=replace_personal(&matchstr,({this_player()})+parsed,1); 00387 tmp=((query_verb()[<1]^'e')?query_verb():query_verb()[0..<2]); 00388 matchstr=regreplace(matchstr,"@VERB",capitalize(tmp),1); 00389 matchstr=regreplace(matchstr,"@verb",tmp,1); 00390 } 00391 00392 // ist Fehlermeldung ein WRITE? 00393 // dann return 1 ! 00394 if(intp(flag[<1]) && (tmpint=flag[<1])<=nrul) { 00395 if(member(matchstr,'^')>=0) { 00396 matchstr=explode(matchstr,"^"); 00397 write(capitalize(break_string(matchstr[0],78,0,1))); 00398 if(strlen(matchstr[1])) 00399 say(capitalize(break_string(matchstr[1],78,0,1)),({this_player()}) ); 00400 } else write(capitalize(break_string(matchstr,78,0,1))); 00401 return 1; 00402 } else notify_fail(capitalize(break_string(matchstr,78,0,1))); 00403 } 00404 } 00405 return 0; 00406 } 00407 00408 // Updaten der Hilfsvariablen 00409 parsed+=({matchstr}); 00410 lastmatchpos=matchpos; 00411 nrul++; 00412 } // end while(nrul<rs) ... Erfolg ... ab zum naechsten Regelteil 00413 } 00414 00415 // Arrays resubstituieren 00416 if((tmpint=sizeof(pointermatches))) 00417 while((tmpint-=2)>=0) 00418 parsed[pointermatches[tmpint]]=pointermatches[tmpint+1]; 00419 00420 // erfolgreich Methode gefunden/eine Regel bis zum Ende durchgeparst: 00421 return(_execute(&fun,&str,&parsed)); 00422 }


| static mapping _query_commands | ( | ) | [static] |
Definiert in Zeile 504 der Datei commands.c.
00504 { 00505 if (mappingp(added_cmds)) 00506 return(deep_copy(added_cmds)); 00507 else 00508 return (mapping)0; 00509 }
| static mapping _set_commands | ( | mapping | commands | ) | [static] |
Definiert in Zeile 492 der Datei commands.c.
Benutzt added_cmds.
00492 { 00493 if(!commands) added_cmds=(mapping)0; 00494 else if(mappingp(commands)) { 00495 added_cmds=m_allocate(sizeof(commands),4); 00496 walk_mapping(commands,#'_check_copy_commands); 00497 } 00498 if (mappingp(added_cmds)) 00499 return(deep_copy(added_cmds)); 00500 else 00501 return (mapping)0; 00502 }
| varargs void AddCmd | ( | mixed | cmd, | |
| mixed | func, | |||
| mixed | flag, | |||
| mixed | cmdid | |||
| ) |
Definiert in Zeile 55 der Datei commands.c.
Benutzt added_cmds, cl und i.
Wird benutzt von create(), MakeDrink() und SetTravelCmds().
00055 { 00056 int i,j; 00057 closure cl; 00058 mixed *rule; 00059 00060 // potentielle AddCmd mit Regel? 00061 if(stringp(cmd)) { 00062 // eine Regel? - aufsplitten 00063 if((i=member(cmd,'&'))>0) { 00064 // ... in Array mit Verknuepfungselementen 00065 rule=explode(cmd[(i+1)..],"&"); 00066 j=sizeof(rule); 00067 // ... in Array mit Arrays mit Alternativelementen: 00068 // "p|q&r|s" -> ({ ({"p","q"}), ({"r","s"}} }) 00069 while(j--) 00070 rule[j]=explode(rule[j],"|"); 00071 00072 // Regeln von Kommandoverben abschneiden 00073 cmd=cmd[0..(i-1)]; 00074 } 00075 // Kommandoverben extrahieren 00076 cmd=explode(cmd,"|"); 00077 00078 // Satz von Regeln existiert: Aufsplitten von Fehlermeldungen 00079 if(rule) 00080 if(stringp(flag)) { 00081 mixed *fail; 00082 // in einfaches Array mit jeweiligen Fehlermeldungen 00083 fail=explode(flag,"|"); 00084 j=0; 00085 i=sizeof(fail); 00086 while(j<i) { 00087 // write - Fehlermeldung entdeckt - Position ggf. eintragen 00088 if(member(fail[j],'^')>=0 && !intp(fail[<1])) 00089 fail+=({j}); 00090 if(member(fail[j],'@')>=0) { 00091 int s; 00092 flag=regexplode(fail[j], "@WE[A-SU]*[0-9]"); 00093 s=sizeof(flag); 00094 while((s-=2)>0) { 00095 int tmpint; 00096 tmpint=flag[s][<1]-'1'; 00097 if(tmpint<0 || tmpint>j) 00098 raise_error(sprintf( 00099 "AddCmd: error-message %d contains out-of-bounds @WExx-rule.\n",j+1)); 00100 } 00101 } 00102 j++; 00103 } 00104 // "Was?|Wie das?" -> ({"Was?","Wie das?"}) 00105 // "Was?|Wie das?^|Womit das?|Worauf das?^@WER1 macht was." -> 00106 // ({"Was?", 00107 // "Wie das?^Womit das?", 00108 // "Worauf das?^@WER1 macht was.",1}) 00109 flag=sizeof(fail); 00110 if(flag && flag<sizeof(rule)) 00111 raise_error( 00112 "AddCmd: number of error-messages does not match number of rules.\n"); 00113 flag=fail; // ueberschreiben mit den parsefreundlichen Format 00114 } else if(flag) 00115 raise_error("AddCmd: rules exist but flags are not an error-string.\n"); 00116 } // end if(stringp(cmd)) ... kein Regelstring vorhanden 00117 00118 // kein Kommandoarray gewesen noch erzeugt? 00119 if(!pointerp(cmd)) 00120 raise_error("AddCmd: missing string/pointer-parameter for command.\n"); 00121 00122 // Closure aus einem String erzeugen, wenn moeglich und sicher 00123 // (function_exists() filtert unnoetigerweise auch reine "static" funs, 00124 // die genaue Pruefung ueber functionlist() kostet jedoch zuviel) 00125 if(stringp(func) && 00126 (!extern_call() || function_exists(func,this_object())) && 00127 closurep(cl=symbol_function(func,this_object()))) 00128 func=cl; 00129 00130 // jedes einzelne Verb mit seinen Regeln und Funktionen eintragen 00131 i=sizeof(cmd); 00132 if(!added_cmds) added_cmds=m_allocate(i,4); 00133 while(i--) { 00134 string str; 00135 str=cmd[i]; 00136 if(!func) 00137 if(extern_call()) func=previous_object(); 00138 else func=this_object(); 00139 if(!member(added_cmds,str)) 00140 added_cmds+=([str:allocate(0);allocate(0);allocate(0);0]); 00141 // existierendes Verb ergaenzen 00142 added_cmds[str,0]+=({func}); 00143 added_cmds[str,1]+=({flag}); 00144 added_cmds[str,2]+=({rule}); 00145 // ggf. id in das ID-Mapping eintragen 00146 if(cmdid) { 00147 mixed *tmp; 00148 j=sizeof((string*)added_cmds[str,0]); 00149 tmp=added_cmds[str,3]||allocate(j); 00150 if(sizeof(tmp)<j) tmp+=allocate(j-sizeof(tmp)); 00151 tmp[<1]=cmdid; 00152 added_cmds[str,3]=tmp; 00153 } 00154 } 00155 }

| protected void create | ( | ) |
Definiert in Zeile 47 der Datei commands.c.
| protected void create_super | ( | ) |
Definiert in Zeile 51 der Datei commands.c.
Benutzt set_next_reset().
00051 { 00052 set_next_reset(-1); 00053 }

| void init | ( | ) |
Definiert in Zeile 470 der Datei commands.c.
Benutzt init(), ob() und set_light().

| varargs int RemoveCmd | ( | mixed | cmd, | |
| int | del_norule, | |||
| mixed | onlyid | |||
| ) |
Definiert in Zeile 160 der Datei commands.c.
Benutzt added_cmds, dtime(), flag, i, ids, log_file und m_delete().
Wird benutzt von MakeDrink().
00160 { 00161 int ret; 00162 00163 // Falls Magier das RemoveCmd falsch nutzen (z.B. analog zu AddCmd) 00164 // wird das Regelsystem verwirrt. Da das del_norule nur int sein darf, 00165 // gibt es hier eine gute Chance den Fehler abwaertskompatibel zu ent- 00166 // decken. Damit Spieler den Fehler nicht mitbekommen, wird hier auf 00167 // ein raise_error verzichtet, und statt dessen in ein Logfile ge- 00168 // schrieben. 00169 if (!intp(del_norule)) 00170 { 00171 log_file("REMOVE_CMD", 00172 sprintf("\n-- %s --\nIllegal RemoveCommand() in Object [%O]:\n %O\n", 00173 dtime(time()), this_object(), cmd)); 00174 del_norule=0; 00175 onlyid=0; 00176 } 00177 00178 if(!added_cmds || (!cmd && !del_norule && !onlyid)) 00179 added_cmds=(mapping)0; 00180 else { 00181 int i, j; 00182 mixed *rule, *flag, *fun, *delrule, *ids; 00183 00184 if(stringp(cmd)) { 00185 // Regeln entdeckt - Zerlegen (wie AddCmd) 00186 if((i=member(cmd,'&'))>0) { 00187 delrule=explode(cmd[(i+1)..],"&"); 00188 j=sizeof(delrule); 00189 while(j--) 00190 delrule[j]=explode(delrule[j],"|"); 00191 cmd=cmd[0..(i-1)]; 00192 } 00193 cmd=explode(cmd,"|"); 00194 } else if(del_norule || onlyid) cmd=m_indices(added_cmds); 00195 00196 if(!pointerp(cmd)) 00197 raise_error("RemoveCmd: missing string/pointer-parameter.\n"); 00198 i=sizeof(cmd); 00199 00200 while(i--) { 00201 // keine Regeln da und Regeln loeschen erlaubt: alles loeschen 00202 if(!delrule && !del_norule && !onlyid) efun::m_delete(added_cmds,cmd[i]); 00203 else if(m_contains(&fun, &flag, &rule, &ids, added_cmds, cmd[i])) { 00204 j=sizeof(fun); 00205 while(j--) { 00206 int k; 00207 // DBG(rule[j]); 00208 // Regeln nicht löschen und Regel? 00209 if(!(del_norule && pointerp(rule[j])) && 00210 // nur bestimmte ID löschen und ID passt nicht? 00211 !(onlyid && (!pointerp(ids) || sizeof(ids)<=j || ids[j]!=onlyid)) && 00212 // Löschregel existiert und passt nicht auf Regel? 00213 !(delrule && (k=sizeof(rule[j]))!=sizeof(delrule))) { 00214 // partielles Testen einer Löschregel ... 00215 if(delrule) { 00216 while(k--) 00217 if(!sizeof(rule[j][k]&delrule[k])) break; 00218 if(k>=0) continue; 00219 } 00220 // alles korrekt: Löschen! 00221 // (Arraybereich durch leeres Array loeschen) 00222 flag[j..j] = allocate(0); 00223 fun[j..j] = allocate(0); 00224 rule[j..j] = allocate(0); 00225 if(ids) { 00226 ids[j..j] = allocate(0); 00227 if(!sizeof(ids-allocate(1))) ids=(mixed*)0; 00228 } 00229 ret++; 00230 } 00231 } // end while(j--) { 00232 } 00233 // Funktions/Regelliste update oder ggf. Kommando voellig loeschen 00234 if(sizeof(rule)) { 00235 added_cmds[cmd[i],0]=fun; 00236 added_cmds[cmd[i],1]=flag; 00237 added_cmds[cmd[i],2]=rule; 00238 added_cmds[cmd[i],3]=ids; 00239 } else efun::m_delete(added_cmds,cmd[i]); 00240 } 00241 if(!sizeof(added_cmds)) added_cmds=(mapping)0; 00242 } 00243 return ret; 00244 }


| private nosave mapping added_cmds |
Definiert in Zeile 45 der Datei commands.c.
Wird benutzt von _check_copy_commands(), _cl(), _set_commands(), AddCmd() und RemoveCmd().
1.6.3