Registrado: 22 May 2004 10:50 Mensajes: 892
|
Después de mirar un poco la documentación ya tengo una versión funcionando. El código de momento no es muy elegante pero funciona como yo quería. Para probarlo, se puede crear una función y llamarla desde una verbo especial, por ejemplo: Código: [test_prologo; ! Testeo del prólogo... test_machine.clear(); test_machine.inserta("e"); test_machine.inserta("o"); test_machine.inserta("examinar casona"); test_machine.inserta("llama a la puerta"); test_machine.inserta("deja el equipaje"); test_machine.inserta("empuja la puerta"); test_machine.inserta("abre la puerta"); test_machine.inserta("entra"); test_machine.run(); ]; Otra opción es meterlo en una rutina que se ejecute cada turno, vaya monitorizando ciertas variables e inserte unos comandos u otros. Con un poco de imaginación tenemos una aventura que se juega a si misma... De momento sólo GLULX e INFORMATE Código: ! Sistema automático de testeo para inform ! Añadir Replace Parser__parse; ! 19 de Marzo de 2011
Global parse_input_externo=0; Array input_buffer_aux -> 121; ! Buffer for injecting commands
! Cada mensaje puede alojar hasta Array input_array --> "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" ! 10 "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" !20 "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" !30 "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" !40 "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" !50 "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" !60 "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" !70 "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" !80 "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" !90 "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" !100 ;
Constant MAX_COMANDOS 100;
Object test_machine with estado 0, with capitulo 0, with posicion 0, ! Puntero de pila inserta[ comando puntero i; if (self.posicion<MAX_COMANDOS) { input_array-->self.posicion = comando; ! Copia el comando al array self.posicion=self.posicion+1; } ], ! Borra borra [num_comando i; ! Compacta las pilas i = num_comando; while (i<(self.posicion-1)) { input_array-->i=input_array-->(i+1); i=i+1; } self.posicion=self.posicion-1; ], clear[i; ! Resetea el array de comandos... self.posicion=0; ], run[; ! Extrae los comandos de la cola y los inyecta como si fueran el input del jugador parse_input_externo=1; ], get_input[i puntero longitud; ! Extrae el comando actual if (self.posicion==0) { parse_input_externo=0; ! Si no quedan comandos devuelve el control rfalse; ! No hay comandos disponibles } ! Puntero al buffer... puntero = input_array-->0; ! Array de cadenas de texto, FIRST IN, FIRST OUT print "#",(string)puntero,"^"; longitud = PrintanyToArray (buffer+4,INPUT_BUFFER_LEN,puntero); buffer-->0=longitud; ! Borra el comando actual self.borra(0); ! Se extraen desde abajo de la pila. FIRST IN, FIRST OUT rtrue; ];
! Modificamos la rutina Parser__parse para que admita una cadena de texto ! externa en función de una variable global.
! ---------------------------------------------------------------------------- ! To simplify the picture a little, a rough map of the main routine: ! ! (A) Get the input, do "oops" and "again" ! (B) Is it a direction, and so an implicit "go"? If so go to (K) ! (C) Is anyone being addressed? ! (D) Get the verb: try all the syntax lines for that verb ! (E) Break down a syntax line into analysed tokens ! (F) Look ahead for advance warning for multiexcept/multiinside ! (G) Parse each token in turn (calling InterpretarToken to do most of the work) ! (H) Cheaply parse otherwise unrecognised conversation and return ! (I) Print best possible error message ! (J) Retry the whole lot ! (K) Last thing: check for "then" and further instructions(s), return. ! ! The strategic points (A) to (K) are marked in the commentary. ! ! Note that there are three different places where a return can happen. ! ----------------------------------------------------------------------------
[ Parser__parse results syntax line num_lines line_address i j k token l m;
! **** (A) ****
! Firstly, in "not held" mode, we still have a command left over from last ! time (eg, the user typed "eat biscuit", which was parsed as "take biscuit" ! last time, with "eat biscuit" tucked away until now). So we return that. if (modo_noposeido==1) { for (i=0:i<8:i++) results-->i=resultados_guardados-->i; modo_noposeido=0; rtrue; }
if (modo_mantenido==1) { modo_mantenido=0; Tokenise__(buffer,parse); jump ReParse; }
.ReType;
if (parse_input_externo==0) { Teclado(buffer,parse); } else { if (test_machine.get_input()==0) { Teclado(buffer,parse); ! Si no había nada en cola ejecuta el flujo normal } ! En caso contrario toma el buffer directamente. else { Tokenise__(buffer,parse); ! Imprime el comando extraido... ! print "#",(string) buffer-->4," "; } }
.ReParse;
parser_inflexion = nombre;
! Initially assume the command is aimed at the jugador, and the verb ! is the first word
#Ifdef TARGET_ZCODE; num_palabras=parse->1; #Ifnot; ! TARGET_GLULX num_palabras=parse-->0; #Endif; ! TARGET_ np=1; #Ifdef IdiomaAInformes; IdiomaAInformes(); #IfV5; ! Re-tokenise: Tokenise__(buffer,parse); #Endif; #Endif;
AntesDelParsing(); #Ifdef TARGET_ZCODE; num_palabras=parse->1; #Ifnot; ! TARGET_GLULX num_palabras=parse-->0; #Endif; ! TARGET_
k=0; #Ifdef DEBUG; if (parser_trace>=2) { print "[ "; for (i=0:i<num_palabras:i++) { #Ifdef TARGET_ZCODE; j=parse-->(i*2 + 1); #Ifnot; ! TARGET_GLULX j=parse-->(i*3 + 1); #Endif; ! TARGET_ k=DireccionDePalabra(i+1); l=LongitudDePalabra(i+1); print "~"; for (m=0:m<l:m++) print (char) k->m; print "~ ";
if (j == 0) print "?"; else { #Ifdef TARGET_ZCODE; if (CompararSinSigno(j, 0-->4)>=0 && CompararSinSigno(j, 0-->2)<0) print (address) j; else print j; #Ifnot; ! TARGET_GLULX if (j->0 == $60) print (address) j; else print j; #Endif; ! TARGET_ } if (i ~= num_palabras-1) print " / "; } print " ]^"; } #Endif; palabra_verbonum=1; actor=jugador; localizacion_actor = TopeAlcanzable(jugador); gramatica_normal_tras = 0;
.AlmostReParse;
token_alcance = 0; accion_que_seria = NULL;
! Begin from what we currently think is the verb word
.BeginCommand; np=palabra_verbonum; palabra_verbo = SiguientePalabraParar();
! If there's no input here, we must have something like ! "person,".
if (palabra_verbo==-1) { mejor_tipoerror = ATASCADO_PE; jump GiveError; }
! Now try for "again" or "g", which are special cases: ! don't allow "again" if nothing has previously been typed; ! simply copy the s
if (palabra_verbo==OTRAVEZ2__WD or OTRAVEZ3__WD) palabra_verbo=OTRAVEZ1__WD; if (palabra_verbo==OTRAVEZ1__WD) { if (actor~=jugador) { M__L(##Miscelanea,20); jump ReType; } #Ifdef TARGET_ZCODE; if (buffer3->1==0) { M__L(##Miscelanea,21); jump ReType; } #Ifnot; ! TARGET_GLULX if (buffer3-->0==0) { M__L(##Miscelanea,21); jump ReType; } #Endif; ! TARGET_ for (i=0:i<INPUT_BUFFER_LEN:i++) buffer->i=buffer3->i; jump ReParse; }
! Save the present input in case of an "again" next time
if (palabra_verbo~=OTRAVEZ1__WD) for (i=0:i<INPUT_BUFFER_LEN:i++) buffer3->i=buffer->i;
if (gramatica_normal_tras==0) { i = EjecutarRutinas(actor, gramatica); #Ifdef DEBUG; if (parser_trace>=2 && actor.gramatica~=0 or NULL) print " [La propiedad Gramatica ha retornado ", i, "]^"; #Endif; if (i<0) { gramatica_normal_tras = palabra_verbonum; i=-i; } if (i == 1) { results-->0 = accion; results-->1 = 2; ! [080625] Aquí va el número de parámetros results-->2 = uno; results-->3 = otro; rtrue; } if (i~=0) { palabra_verbo = i; np--; palabra_verbonum--; } else { np = palabra_verbonum; palabra_verbo=SiguientePalabra(); } } else gramatica_normal_tras=0;
! **** (B) ****
#Ifdef IdiomaEsVerbo; if (palabra_verbo==0) { i = np; palabra_verbo=IdiomaEsVerbo(buffer, parse, palabra_verbonum); np = i; } #Endif;
! If the first word is not listed as a verb, it must be a direction ! or the nombre of someone to talk to
if (palabra_verbo==0 || ((palabra_verbo->#dict_par1) & 1) == 0) {
! So is the first word an object contained in the special object "compass" ! (i.e., a direction)? This needs use of DominioNombre, a routine which ! does the object matching, returning the object number, or 0 if none found, ! or CODIGO_REPARSE if it has restructured the parse table so the whole parse ! must be begun again...
np=palabra_verbonum; modo_indef = false; filtro_token = 0; l=DominioNombre(Brujula,0,0); if (l==CODIGO_REPARSE) jump ReParse;
! If it is a direction, send back the results: ! accion=IrSub, no of arguments=1, argument 1=the direction.
if (l~=0) { results-->0 = ##Ir; accion_que_seria = ##Ir; results-->1 = 1; results-->2 = l; jump LookForMore; }
! **** (C) ****
! Only check for a comma (a "someone, do something" command) if we are ! not already in the middle of one. (This simplification stops us from ! worrying about "robot, wizard, you are an idiot", telling the robot to ! tell the wizard that she is an idiot.)
if (actor==jugador) { for (j=2:j<=num_palabras:j++) { i=SiguientePalabra(); if (i==palabra_coma) jump Conversation; }
palabra_verbo=VerboDesconocido(palabra_verbo); if (palabra_verbo~=0) jump VerbAccepted; }
mejor_tipoerror=VERBO_PE; jump GiveError;
! SiguientePalabra nudges the word number np on by one each time, so we've now ! advanced past a comma. (A comma is a word all on its own in the table.)
.Conversation; j = np - 1; if (j==1) { M__L(##Miscelanea,22); jump ReType; }
! Use DominioNombre (in the context of "animado creature") to see if the ! words make sense as the nombre of someone held or nearby
np=1; elsiguiente=TOKEN_POSEIDO; razon_alcance = RAZON_HABLAR; l=DominioNombre(jugador,localizacion_actor,6); razon_alcance = RAZON_PARSING; if (l==CODIGO_REPARSE) jump ReParse;
if (l==0) { M__L(##Miscelanea,23); jump ReType; }
! The object addressed must at least be "hablable" if not actually "animado" ! (the distinction allows, for instance, a microphone to be spoken to, ! without the parser thinking that the microphone is human).
if (l hasnt animado && l hasnt hablable) { M__L(##Miscelanea, 24, l); jump ReType; }
! Check that there aren't any mystery words between the end of the person's ! nombre and the comma (eg, throw out "dwarf sdfgsdgs, go north").
if (np~=j) { M__L(##Miscelanea, 25); jump ReType; }
! The jugador has now successfully named someone. Adjust "him", "her", "it":
ActualizarPronombre(l);
! Set the global variable "actor", adjust the number of the first word, ! and begin parsing again from there.
palabra_verbonum=j+1;
! Stop things like "me, again":
if (l == jugador) { np = palabra_verbonum; if (SiguientePalabraParar() == OTRAVEZ1__WD or OTRAVEZ2__WD or OTRAVEZ3__WD) { M__L(##Miscelanea,20); jump ReType; } }
actor=l; localizacion_actor=TopeAlcanzable(l); #Ifdef DEBUG; if (parser_trace>=1) print "[El actor es ", (the) actor, " que está en ", (name) localizacion_actor, "]^"; #Endif; jump BeginCommand; }
! **** (D) ****
.VerbAccepted;
! We now definitely have a verb, not a direction, whether we got here by the ! "take ..." or "person, take ..." method. Get the meta flag for this verb:
meta=((palabra_verbo->#dict_par1) & 2)/2;
! You can't order other people to "full score" for you, and so on...
if (meta==1 && actor~=jugador) { mejor_tipoerror=VERBO_PE; meta=0; jump GiveError; }
! Now let i be the corresponding verb number, stored in the dictionary entry ! (in a peculiar 255-n fashion for traditional Infocom reasons)...
i=$ff-(palabra_verbo->#dict_par2);
! ...then look up the i-th entry in the verb table, whose address is at word ! 7 in the Z-machine (in the header), so as to get the address of the syntax ! table for the given verb...
#Ifdef TARGET_ZCODE; syntax=(0-->7)-->i; #Ifnot; ! TARGET_GLULX syntax=(#grammar_table)-->(i+1); #Endif; ! TARGET_
! ...and then see how many lines (ie, different patrons corresponding to the ! same verb) are stored in the parse table...
num_lines = (syntax -> 0) - 1;
! ...and now go through them all, one by one. ! To prevent palabra_pronombre 0 being misunderstood,
palabra_pronombre=NULL; objeto_pronombre=NULL;
#Ifdef DEBUG; if (parser_trace>=1) print "[Interpretando el verbo '", (address) palabra_verbo, "' (", num_lines+1, " líneas)]^"; #Endif;
mejor_tipoerror=ATASCADO_PE; proxmejor_tipoerror=ATASCADO_PE;
! "mejor_tipoerror" is the current failure-to-match error - it is by default ! the least informative one, "don't understand that sentence". ! "proxmejor_tipoerror" remembers the best alternative to having to ask a ! scope token for an error message (i.e., the best not counting PREGUNTAAMBITO_PE).
! **** (E) ****
line_address = syntax + 1;
for (line=0:line<=num_lines:line++) { for (i = 0 : i < 32 : i++) { linea_token-->i = TOKEN_FINAL; linea_tipot-->i = TT_ELEMENTAL; linea_tdatos-->i = TOKEN_FINAL; }
! Unpack the syntax line from Inform format into three arrays; ensure that ! the sequence of tokens ends in an TOKEN_FINAL.
line_address = DesempaquetarLineaGramatica(line_address);
#Ifdef DEBUG; if (parser_trace >= 1) { if (parser_trace >= 2) new_line; print "[línea ", line; DepurarLineaGramatica(); print "]^"; } #Endif;
! We aren't in "not holding" or inferring modes, and haven't entered ! any parametros on the line yet, or any special numbers; the multiple ! object is still empty.
no_poseido=0; deducedesde=0; parametros=0; nsns=0; palabra_especial=0; numero_especial=0; objeto_multiple-->0 = 0; multi_contexto = 0; tipoerror=ATASCADO_PE;
! Put the word marker back to just despues the verb
np=palabra_verbonum+1;
! **** (F) **** ! There are two special cases where parsing a token now has to be ! affected by the result of parsing another token later, and these ! two cases (multiexcept and multiinside tokens) are helped by a quick ! look ahead, to work out the future token now. We can only carry this ! out in the simple (but by far the most common) case: ! ! multiexcept <one or more prepositions> noun ! ! and similarly for multiinside.
aviso_avanzar = NULL; modo_indef = false; for (i=0,m=false,contadorp=0:linea_token-->contadorp ~= TOKEN_FINAL:contadorp++) { token_alcance = 0;
if (linea_tipot-->contadorp ~= TT_PREPOSICION) i++;
if (linea_tipot-->contadorp == TT_ELEMENTAL) { if (linea_tdatos-->contadorp == TOKEN_MULTI) m=true; ! [001115] Añadida la comprobación TOKEN_MULTIPOSEIDO ! para capturar correctamente el caso DEJA TODO if (linea_tdatos-->contadorp == TOKEN_MULTIPOSEIDO) { m=true; indef_propietario=actor; } if (linea_tdatos-->contadorp == TOKEN_MULTIEXCEPTO or TOKEN_MULTIDENTRO && i==1) { ! First non-preposition is "multiexcept" or ! "multiinside", so look ahead.
#Ifdef DEBUG; if (parser_trace>=2) print " [Intentando anticipar]^"; #Endif;
! We need this to be followed by 1 or more prepositions.
contadorp++; if (linea_tipot-->contadorp == TT_PREPOSICION) { while (linea_tipot-->contadorp == TT_PREPOSICION) contadorp++;
if ((linea_tipot-->contadorp == TT_ELEMENTAL) && (linea_tdatos-->contadorp == TOKEN_NOMBRE)) { ! Advance past the last preposition
while (np <= num_palabras) { if (SiguientePalabra() == linea_tdatos-->(contadorp-1)) { l = DominioNombre(localizacion_actor, actor, TOKEN_NOMBRE); #Ifdef DEBUG; if (parser_trace>=2) { print " [Avanzando hasta el token ~noun~: "; if (l==CODIGO_REPARSE) print "petición de re-interpretar]^"; if (l==1) print "pero se ha encontrado múltiple]^"; if (l==0) print "error ", tipoerror, "]^"; if (l>=2) print (the) l, "]^"; } #Endif; if (l==CODIGO_REPARSE) jump ReParse; if (l>=2) aviso_avanzar = l; } } } } break; } } }
! Slightly different line-parsing rules will apply to "take multi", to ! prevent "take all" behaving correctly but misleadingly when there's ! nothing to take.
regla_coger_todo = 0; if (m && parametros_deseados==1 && (accion_que_seria==##Coger or ##Dejar)) regla_coger_todo = 1;
! And now start again, properly, forearmed or not as the case may be. ! As a precaution, we clear all the variables again (they may have been ! disturbed by the call to DominioNombre, which may have called outside ! code, which may have done anything!).
no_poseido=0; deducedesde=0; parametros=0; nsns=0; palabra_especial=0; numero_especial=0; objeto_multiple-->0 = 0; tipoerror=ATASCADO_PE; np=palabra_verbonum+1;
! **** (G) **** ! "Patron" gradually accumulates what has been recognised so far, ! so that it may be reprinted by the parser later on
for (contadorp=1::contadorp++) { patron-->contadorp = PATRON_NULO; token_alcance=0;
token = linea_token-->(contadorp-1); elsiguiente = linea_token-->contadorp;
#Ifdef DEBUG; if (parser_trace >= 2) print " [línea ", line, " token ", contadorp, " palabra ", np, " : ", (DepurarToken) token, "]^"; #Endif;
if (token ~= TOKEN_FINAL) { razon_alcance = RAZON_PARSING; parser_inflexion = nombre; AnalizarToken(token); l = ParseToken__(ttipo_encontrado, tdatos_encontrado, contadorp-1, token); while (l<-200) l = ParseToken__(TT_ELEMENTAL, l + 256); razon_alcance = RAZON_PARSING;
if (l==RPG_PREPOSICION) { if (ttipo_encontrado~=TT_PREPOSICION && (ttipo_encontrado~=TT_ELEMENTAL || tdatos_encontrado~=TOKEN_TEMA)) parametros_deseados--; l = true; } else if (l<0) l = false; else if (l~=RPG_REPARSE) { if (l==RPG_NUMERO) { if (nsns==0) numero_especial1=numero_interpretado; else numero_especial2=numero_interpretado; nsns++; l = 1; } if (l==RPG_MULTIPLE) l = 0; results-->(parametros+2) = l; parametros++; patron-->contadorp = l; l = true; }
#Ifdef DEBUG; if (parser_trace >= 3) { print " [el token ha "; if (l==CODIGO_REPARSE) print "causado petición de reinterpretar]^"; if (l==0) print "causado fallo con error ", tipoerror, "]^"; if (l==1) print "sido interpretado con éxito]^"; } #Endif;
if (l==CODIGO_REPARSE) jump ReParse; if (l==false) break; } else {
! If the jugador has entered enough already but there's still ! text to wade through: store the patron away so as to be able to produce ! a decent error message if this turnos out to be the best we ever manage, ! and in the mean time give up on this line
! However, if the superfluous text begins with a comma or "then" then ! take that to be the start of another instruction
if (np <= num_palabras) { l=SiguientePalabra(); if (l==DESPUES1__WD or DESPUES2__WD or DESPUES3__WD or palabra_coma or Y1__WD or Y2__WD or Y3__WD) { modo_mantenido=1; mant_np=np-1; } else { for (m=0:m<32:m++) patron2-->m=patron-->m; contadorp2=contadorp; tipoerror=HASTAQUI_PE; break; } }
! Now, we may need to revise the multiple object because of the single one ! we now know (but didn't when the list was drawn up).
if (parametros>=1 && results-->2 == 0) { l=RevisarMulti(results-->3); if (l~=0) { tipoerror=l; break; } } if (parametros>=2 && results-->3 == 0) { l=RevisarMulti(results-->2); if (l~=0) { tipoerror=l; break; } }
! To trap the case of "take all" inferring only "yourself" when absolutely ! nothing else is in the vicinity... if (regla_coger_todo==2 && results-->2 == actor) { mejor_tipoerror = NADA_PE; jump GiveError; }
#Ifdef DEBUG; if (parser_trace>=1) print "[Línea interpretada con éxito]^"; #Endif;
! The line has successfully matched the text. Declare the input error-free...
eepa_desde = 0;
! ...explain any inferences made (using the patron)... #Ifdef IMPRIMIR_DEDUCCIONES; if (deducedesde~=0) { print "("; ImprimirComando(deducedesde); print ")^"; } #Endif; ! ...copy the accion number, and the number of parametros...
results-->0 = accion_que_seria; results-->1 = parametros;
! ...reverse first and otro parametros if need be...
if (accion_invertida && parametros==2) { i = results-->2; results-->2 = results-->3; results-->3 = i; if (nsns == 2) { i = numero_especial1; numero_especial1=numero_especial2; numero_especial2=i; } }
! ...and to reset "it"-style objects to the first of these parametros, if ! there is one (and it really is an object)...
if (parametros > 0 && results-->2 >= 2) ActualizarPronombre(results-->2);
! ...and worry about the case where an object was allowed as a parameter ! even though the jugador wasn't holding it and should have been: in this ! event, keep the results for next time round, go into "not holding" mode, ! and for now tell the jugador what's happening and return a "take" request ! instead...
if (no_poseido~=0 && actor==jugador) { modo_noposeido=1; for (i=0:i<8:i++) resultados_guardados-->i = results-->i; results-->0 = ##Coger; results-->1 = 1; results-->2 = no_poseido; M__L(##Miscelanea, 26, no_poseido); }
! (Notice that implicit takes are only generated for the jugador, and not ! for other actors. This avoids entirely logical, but misleading, text ! being printed.)
! ...and return from the parser altogether, having successfully matched ! a line.
if (modo_mantenido==1) { np=mant_np; jump LookForMore; } rtrue; } }
! The line has failed to match. ! We continue the outer "for" loop, trying the next line in the gramatica.
if (tipoerror>mejor_tipoerror) mejor_tipoerror=tipoerror; if (tipoerror~=PREGUNTAAMBITO_PE && tipoerror>proxmejor_tipoerror) proxmejor_tipoerror=tipoerror;
! ...unless the line was something like "take all" which failed because ! nothing matched the "all", in which case we stop and give an error now.
if (regla_coger_todo == 2 && mejor_tipoerror==NADA_PE) break;
! Añadido para evitar que DEJA TODO cause problemas cuando no hay nada ! qué dejar
if (accion_que_seria == ##Dejar && mejor_tipoerror==NADA_PE) break; }
! The gramatica is exhausted: every line has failed to match.
! **** (H) ****
.GiveError; tipoerror=mejor_tipoerror;
! Errors are handled differently depending on who was talking.
! If the command was addressed to somebody else (eg, "dwarf, sfgh") then ! it is taken as conversation which the parser has no business in disallowing.
if (actor~=jugador) { if (gramatica_normal_tras>0) { palabra_verbonum = gramatica_normal_tras; jump AlmostReParse; } np=palabra_verbonum; palabra_especial=SiguientePalabra(); if (palabra_especial==palabra_coma) { palabra_especial=SiguientePalabra(); palabra_verbonum++; } numero_especial=IntentarNumero(palabra_verbonum); results-->0=##NoComprendido; results-->1=2; results-->2=1; numero_especial1=palabra_especial; results-->3=actor; consultar_desde = palabra_verbonum; consultar_num_palabras = num_palabras-consultar_desde+1; rtrue; }
! **** (I) ****
! If the jugador was the actor (eg, in "take dfghh") the error must be printed, ! and fresh input called for. In three cases the oops word must be jiggled.
if (ErrorParser(tipoerror)~=0) jump ReType; palabra_pronombre = palabra__pronombre; objeto_pronombre = objeto__pronombre;
if (tipoerror==ATASCADO_PE) { M__L(##Miscelanea, 27); eepa_desde=1; } if (tipoerror==HASTAQUI_PE) {
if (parser_listo) { for (m=0:m<32:m++) patron-->m = patron2-->m; contadorp=contadorp2; }
! accion=accion_que_seria; ! uno=results-->2; ! otro=results-->3;
#Ifdef DEBUG; if (parser_trace>0) print "[Entendido sólo hasta la palabra número ", eepa_desde,".]^"; #Endif;
M__L(##Miscelanea, 28); if (si_pl) ! 030305 { modo_mantenido=0; num_palabras=eepa_desde; np=1; #Ifdef DEBUG; if (parser_trace>0) print "[Reparseando hasta la palabra número ",num_palabras,".]^"; #Endif; jump AlmostReParse; } } if (tipoerror==NUMERO_PE) M__L(##Miscelanea, 29); if (tipoerror==NOVEO_PE) { M__L(##Miscelanea, 30); eepa_desde=eepa_guardado; } if (tipoerror==MUYPOCO_PE) M__L(##Miscelanea, 31); if (tipoerror==NOTIENES_PE) { M__L(##Miscelanea, 32); eepa_desde=eepa_guardado; } if (tipoerror==MULTI_PE) M__L(##Miscelanea, 33); if (tipoerror==MMULTI_PE) M__L(##Miscelanea, 34); if (tipoerror==PRONOM_PE) M__L(##Miscelanea, 35); if (tipoerror==EXCEPTO_PE) M__L(##Miscelanea, 36); if (tipoerror==ANIMA_PE) M__L(##Miscelanea, 37); if (tipoerror==VERBO_PE) M__L(##Miscelanea, 38); if (tipoerror==ESCENARIO_PE) M__L(##Miscelanea, 39); if (tipoerror==YANOPRON_PE) { if (objeto_pronombre == NULL) M__L(##Miscelanea, 35); else M__L(##Miscelanea, 40); } if (tipoerror==KKFINAL_PE) M__L(##Miscelanea, 41); if (tipoerror==HAYPOCOS_PE) M__L(##Miscelanea, 42, multi_hallado); if (tipoerror==NADA_PE) { if (multi_esperado==100) M__L(##Miscelanea, 43); else M__L(##Miscelanea, 44); }
if (tipoerror==PREGUNTAAMBITO_PE) { estadio_alcance=3; if (indirect(error_alcance)==-1) { mejor_tipoerror=proxmejor_tipoerror; jump GiveError; } }
! **** (J) ****
! And go (almost) right back to square one...
jump ReType;
! ...being careful not to go all the way back, to avoid infinite repetition ! of a deferred command causing an error.
! **** (K) ****
! At this point, the return value is all prepared, and we are only looking ! to see if there is a "then" followed by subsequent instruction(s).
.LookForMore;
if (np>num_palabras) rtrue;
i=SiguientePalabra(); if (i==DESPUES1__WD or DESPUES2__WD or DESPUES3__WD or palabra_coma) { if (np>num_palabras) { modo_mantenido = false; return; } i = DireccionDePalabra(palabra_verbonum); j = DireccionDePalabra(np); for (:i<j:i++) i->0 = ' '; i = SiguientePalabra(); if (i==OTRAVEZ1__WD or OTRAVEZ2__WD or OTRAVEZ3__WD) { ! Delete the words "then again" from the again buffer, ! in which we have just realised that it must occur: ! prevents an infinite loop on "i. again"
i = DireccionDePalabra(np-2)-buffer; if (np > num_palabras) j = INPUT_BUFFER_LEN-1; else j = DireccionDePalabra(np)-buffer; for (:i<j:i++) buffer3->i = ' '; } Tokenise__(buffer,parse); modo_mantenido = true; return; } mejor_tipoerror=HASTAQUI_PE; jump GiveError; ];
_________________ --- KMBR! http://www.aliensuavito.org @lecambre
Última edición por saimazoom el 20 Mar 2011 20:25, editado 1 vez en total
|
|